せたがやえんじにあぶろぐ

Ruby | Rails | iPhone | Web

Ruby on Railsで今の季節が分かるライブラリ的なのが無かったので、ActiveModelでクラスを作ってみたよ

Rails 4.0.0
Ruby 2.0.0

RubyのDateやTimeのライブラリは、とても使いやすくて素晴らしいのだけど、今の季節が一瞬でわかるライブラリや、Dateクラスにもそんなメソッドが無かった気がするので、

簡単に実装してみたよ。

@season = Season.new
# => #<Season:0x00000104f4c298 @from=Wed, 01 Oct 2014, @to=Wed, 31 Dec 2014, @from_to=Wed, 01 Oct 2014..Wed, 31 Dec 2014, @name="秋", @code=:autumn> 

↑こんなコードで、今日がどの季節なのかが分かるインスタンスが得られるように

ActiveModelを使ってクラスを作ってみたよ。


IDEで書いたコードをそのままペタ張りしてるので、インデントがアレで見づらいです。

class Season

 include ActiveModel::Model

 @@seasons = {winter: "",
              spring: "",
              summer: "",
              autumn: ""}

 attr_accessor :from
 attr_accessor :to
 attr_accessor :from_to
 attr_accessor :name
 attr_accessor :code

 def initialize opt={}
  super
  now_season    = self.class.now_season(opt[:code])
  self.from     = now_season[:from]
  self.to       = now_season[:to]
  self.from_to  = now_season[:from_to]
  self.name     = now_season[:name]
  self.code     = opt[:code] || now_season[:code]
 end

 @@seasons.keys.each {|code|
  define_method("#{code}?"){ self.code == code }
 }

 class << self
  @@seasons.each { |code, name|
   define_method("#{code}_attributes") {
    from, to = eval(code.to_s)
    {from: from, to: to, from_to: from..to, name: name, code: code}
   }
  }

  def winter?
   season?(winter)
  end

  def spring?
   season?(spring)
  end

  def summer?
   season?(summer)
  end

  def autumn?
   season?(autumn)
  end

  def season?(from_to)
   from_to = from_to[0]..from_to[1]
   from_to.include?(Date.today)
  end

  def winter
   season_from_to("01-01","03-31")
  end

  def spring
   season_from_to("04-01","06-30")
  end

  def summer
   season_from_to("07-01","09-30")
  end

  def autumn
   season_from_to("10-01","12-31")
  end

  def season_from_to(from,to)
   today = Date.today
   from  = "#{today.year}-#{from}".to_date
   to    = "#{today.year}-#{to}".to_date
   return from, to
  end

  def now_season (code = nil)
   if code
    return eval("#{code}_attributes")
   end

   attr = case
           when winter? then winter_attributes
           when spring? then spring_attributes
           when summer? then summer_attributes
           when autumn? then autumn_attributes
          end; attr
  end
 end
end

生成したインスタンス

season = Season.new #=> #<Season @from=Wed, 01 Oct 2014, @to=Wed, 31 Dec 2014, @from_to=Wed, 01 Oct 2014..Wed, 31 Dec 2014, @name="秋", @code=:autumn>
season.autumn? # => true
season.winter? # => false 

season.from_to # => Wed, 01 Oct 2014..Wed, 31 Dec 2014

として、今の季節を調べたり

season = Season.new(code: :summer)
# =>  #<Season:0x00000104f479a0 @from=Tue, 01 Jul 2014, @to=Tue, 30 Sep 2014, @from_to=Tue, 01 Jul 2014..Tue, 30 Sep 2014, @name="夏", @code=:summer> 

などとして、明示的に季節を指定してインスタンスを生成したり出来るようにしたよ。

Rails 4のActiveModelというAPIがとても便利で、DBに関係ないモデルをActiveRecordのように使えるようになるよ。

ActiveModelの練習で今の季節が分かるSeasonクラスを作ってみて楽しかったけど、

あんまり使いところがなさそうだね!!

...。