I have a Model called "Tenant" and it has two Date attributes tenant_from and tenant_until.
I want to write a method that checks if Date.today is between the two dates I mentioned above. I want to do something along these lines:
IF Date.today IS BETWEEN tenant.tenant_from AND tenant.tenant_until DO
...
ELSE
...
Try
if Time.zone.today.between?(tenant.tenant_from, tenant.tenant_until)
# YOUR CODE GOES HERE
else
# YOUR CODE GOES HERE
end
Just for an alternate solution. You can use a Date range and cover? to achieve the same effect.
(tenant.tenant_from .. tenant.tenant_until).cover?(Date.today)
Class Tenant < ActiveRecord::Base
def current? #name this what you want, but keep the question mark, since it returns a boolean
(tenant.tenant_from.to_date .. tenant.tenant_until.to_date).include?(Date.today)
end
end
Now you have model logic on an instance of the model (where it belongs). Your logic is then if #tenant.current?.
Related
Is there any way to define a method for a class instance in the console?
e.g.
def Model.old?
self.created_at < Time.now - 35.years
end
And then run it with
Model.find(1).old?
Based on the code you provided, this should be what you want:
class Model
def old?
created_at < 35.years.ago
end
end
You just need to enter each line into the console one by one.
P.S. - Your comparison logic is backwards, so I flipped it back around.
I have two models, Project and Event. Project has_many events.
I want to automatically create many Events after_create of one Project.
My Project model has two Date columns prep_start and prep_end
I am trying to find an array of dates between prep_start and prep_end
I have created a concern that is supposed to automatically create events after_create a new #Project. My concern (Add_Events.erb) file looks like this:
module AddEvents
extend ActiveSupport::Concern
included do
after_create :event_dates, :add_events
end
def event_dates
#project = Project.new
(#project.prep_start..#project.prep_end)
end
end
def add_events
#event_dates.each do |event_date|
self.events.create!(occurs_on: event_date)
end
end
I can't get the array to complete.
I assume you want to create events daily, right? First, you need to find the the array of dates between your start date and end date. There is a very nice ruby gem that helps you do that here: IceCube.
Once you have your array of dates, you can loop through them and create your events:
def create_events
# Assuming you have #event_dates = ["2014-09-20", "2014-09-21", "2014-09-22", "2014-09-23"]
#event_dates.each do |event_date|
self.events.create!(event_date: event_date)
end
end
Ruby ranges (x .. y) are enumerable objects, this means you can do .each on them.
Iterating a range of dates works fine, but iterating a range of datetimes will yield every second between the start and the end of range.
(It will also issue a lot of warnings, because the succ method on datetime is obsolete)
So you'll have to make sure your items are of type Date.
It is safe to call to_date on instances of Date, Time, DateTime and TimeWithZone, the example below should do the trick
(project.start_at.to_date .. project.end_at.to_date).each do |date|
Event.create(:occurs_at => date)
end
What is the best way to store Time in milliseconds when using Rails+Mysql?
I am about to use a decimal and composed_of in order to be able to manipulate this value as a Ruby Time. Does anyone have a better idea?!
Several years have passed since this was asked. Here's an updated solution:
https://gist.github.com/MarkMurphy/93adca601b05acffb8b5601df09f66df
I'm not sure I fully understand what you're trying to do, but have you considered simply overriding the reader/writer methods in your model?. If this works for you, it might be preferred over your proposed solution since it's arguably more readable.
MyClass < ActiveRecord::Base
# Override reader method
def my_attribute
super().from_milis
end
# Override writer method
def my_attribute=(value)
super(value.to_milis)
end
end
Posted a solution to store millisecond precision in MySql using composed_of
http://ternarylabs.com/2011/09/26/millisecond-precision-timestamp-in-rails-with-mysql/
1) Store it as a :decimal with ample precision for your purposes.
2) Create a helper method yourself. Something like this:
# app/helpers/application_helper.rb
module ApplicationHelper
def time_with_ms(time)
minutes = (time % 1.minute).floor
seconds = time % 1.minute
"%02d:%05.2f" % [minutes, seconds]
end
end
My approach was to:
open the time class and implement the methods :from_milis and :to_milis :
class Time
def self.from_milis(milis)
self.at(milis.to_f/1000)
end
def to_milis
self.to_f*1000
end
end
migrate the column from timestamp to :decimal,:precision=>17
then, in the AR class in which i am using this column as attribute:
composed_of :ts,
:class_name=>"Time",
:mapping=>%w(ts to_milis),
:constructor=>:from_milis,
:converter=>:from_milis
I just had gochas when using this attribute in arel queries, where I had to explicitly call to_milis in order to get the intended value in the comparision.
I created this helper method. In my view I call it with days_left(duedate). I dont really like my helper. Is it possible to use it with self. Since I dont really know how self is being used. Is it the same as this in java or javascript? What object is it related to? Feel free to tune this method. Thx for your time!
def days_left(duedate)
(if duedate.date == Date.today
"Today"
elsif duedate.date-Date.today < 1
"expired"
elsif duedate.date-Date.today == 1
"Tomorrow"
else
"#{(duedate.date-Date.today).to_i}"
end).to_s.html_safe
end
You might try moving this method to your model.
This would be similar to adding a 'full_name' method to a model with the attributes 'first_name' and 'last_name.' You wouldn't store 'full_name' separately in your database, because that would result in redundant, denormalized data.
For example:
class Employee < ActiveRecord::Base
def full_name
"#{first_name} #{last_name}"
end
end
So you could similarly add the 'days_left' method to your model, which fits there because it's adding a friendlier version of an existing data attribute.
I'm trying to compare a couple of dates from my form.
Im my validation I have something like:
:mydate - 1.day
But I get:
undefined method `-' for :mydate:Symbol"
Totally a newb question, but I cant figure it out LOL - how do I perform date math on a symbol?
Edit:
OK, so I cant access the params from the controller either, or the form object. I'm using basic restful controllers:
def create
#booking = Booking.new(params[:booking])
etc...
end
and then in my model I want to validate some dates - the end result should be that a Checkin date should be the same as a Checkout date minus the number of nights
So my model:
class Booking < ActiveRecord::Base
def validate
errors.add_to_base "Nights Borked" if :checkin != (:checkout - :nights.day)
end
end
Or I'd like to do something like that but cant.
If I try and access #booking.checkin I get:
undefined method `checkin'
If I try to do
#foo = params[:booking][:checkin]
I get
undefined local variable or method `params' for #<Class:0x103fd1408>
What am I missing here. Something obvious probably lol :)
You can't perform date math on a symbol, because a symbol is merely a more-sophisticated string. It'd not holding a value other than its name. But assuming you have a model with an attribute called mydate:
#object.mydate - 1.day
or if you have a parameter passed in from a form:
params[:mydate] - 1.day
Given your updated code samples, you want to call attributes as self.attribute, like so:
class Booking < ActiveRecord::Base
def validate
errors.add_to_base "Nights Borked" if self.checkin != (self.checkout - self.nights.day)
end
end
The validate method is being called on a booking object already, so you want to call the attributes in that context.