mickey
mickey

Reputation: 185

How not to repeat this code in my models

I have this piece of code in a model that sets a start date and end date according to the time of the day that the method is run.

Let's jump right into the code example:

#MODEL
now = Time.now
if now.hour >= 17 && now.hour <= 23
    #night
    n = now+1.day
    startd = Time.local(now.year, now.month, now.day, 17, 00, 00)
    endd = Time.local(n.year, n.month, n.day, 8, 00, 00)
elsif now.hour >= 0 && now.hour <= 7
    #morning
    n = now-1.day
    startd = Time.local(n.year, n.month, n.day, 8, 00, 00)
    endd = Time.local(now.year, now.month, now.day, 17, 00, 00)     
end

Then inside a model (same or another), I am trying to run this function inside a find.

#MODEL(SAME OR OTHER)
Model.find(:all, 
 :conditions => ['created_at >= ? AND created_at <= ?', startd, endd])

The problem is that I'm going to use that function to set the start and end dates a lot, and I dont know where to place it to not repeat myself. It's going to be used from different models.

Thanks for any help.

Upvotes: 1

Views: 275

Answers (3)

erik
erik

Reputation: 6436

You can include it in a module in the lib directory. All ruby files in RAILS_ROOT/lib are automatically loaded.

# time_calculations.rb

module TimeCalculations
  def calc_start_and_end_times
    now = Time.now
    if now.hour >= 17 && now.hour <= 23
        #night
        n = now+1.day
        startd = Time.local(now.year, now.month, now.day, 17, 00, 00)
        endd = Time.local(n.year, n.month, n.day, 8, 00, 00)
    elsif now.hour >= 0 && now.hour <= 7
        #morning
        n = now-1.day
        startd = Time.local(n.year, n.month, n.day, 8, 00, 00)
        endd = Time.local(now.year, now.month, now.day, 17, 00, 00)     
    end
    [startd, endd]
  end
end

# model.rb

class Model < ActiveRecord::Base
  extend TimeCalculations

  def self.my_find()
    startd, endd = calc_start_and_end_times
    Model.find(:all, 
      :conditions => ['created_at >= ? AND created_at <= ?', startd, endd])
  end

end

Edited to reflect final/correct answer.

Upvotes: 3

mixonic
mixonic

Reputation: 2703

The simplest way is to add your code to a module, maybe in an initializer:

module SmartDates

  def start_date
    now = Time.now
    if now.hour >= 17 && now.hour <= 23
      #night
      n = now+1.day
      return Time.local(now.year, now.month, now.day, 17, 00, 00)
    elsif now.hour >= 0 && now.hour <= 7
      #morning
      n = now-1.day
      return Time.local(n.year, n.month, n.day, 8, 00, 00)
    end
  end

  def end_date
    now = Time.now
    if now.hour >= 17 && now.hour <= 23
      #night
      n = now+1.day
      return Time.local(n.year, n.month, n.day, 8, 00, 00)
    elsif now.hour >= 0 && now.hour <= 7
      #morning
      n = now-1.day
      return Time.local(now.year, now.month, now.day, 17, 00, 00)
    end
  end

end

# Now include your module
ActiveRecord::Base.include(SmartDates)
ActionController::Base.include(SmartDates)

Now start_date and end_date are available in both models and controllers.

Upvotes: 1

Alexey Poimtsev
Alexey Poimtsev

Reputation: 2847

you can add method find_by_date_range (startd, endd) inside model class and use Model.find_by_date_range(something, something_else)

Upvotes: 0

Related Questions