in standby for an annoying problem.

I have a model Reservation with reserved_from and reserve_to attributes of type date. I want create a scope of all reservations where Date.today is between reserved_from and reserved_to. In the model I've done:

def self.today_reservation     find_each do |res|       if (Date.today).between?(res.reserved_from, res.reserved_to)         return       else         puts "false"       end     end   end   scope :today_reservations, today_reservation

but it doesn't work. If reserved_from is 2012-11-01 and reserved_to is 2012-11-02 and Date.today is 2012-11-14 the method above method return an activerecord relation. Some advice? Thank you.

I have a model Reservation with reserved_from and reserve_to attributes of type date. I want create a scope of all reservations where Date.today is between reserved_from and reserved_to. In the model I've done:

def self.today_reservation     find_each do |res|         if (Date.today).between?(res.reserved_from, res.reserved_to)                 return         else                 puts "false"         end     end   end   scope :today_reservations, today_reservation

but it doesn't work. If reserved_from is 2012-11-01 and reserved_to is 2012-11-02 and Date.today is 2012-11-14 the method above method return an activerecord relation.

That is not how scopes work. You need something like (not tested) scope :today_reservations, lambda { where("reserved_from > ? and reserved_to <= ?", Date.today, Date.today ) }

I expect there is a neater way to do it. Make sure your automated tests check it on the end points of the range.

Colin

I have a model Reservation with reserved_from and reserve_to attributes of type date. I want create a scope of all reservations where Date.today is between reserved_from and reserved_to. In the model I've done:

def self.today_reservation     find_each do |res|         if (Date.today).between?(res.reserved_from, res.reserved_to)                 return         else                 puts "false"         end     end   end   scope :today_reservations, today_reservation

but it doesn't work. If reserved_from is 2012-11-01 and reserved_to is 2012-11-02 and Date.today is 2012-11-14 the method above method return an activerecord relation.

That is not how scopes work. You need something like (not tested) scope :today_reservations, lambda { where("reserved_from > ? and reserved_to <= ?", Date.today, Date.today ) }

Without lamda it's the same thing? scope :today_reservations, where("reserved_from > ? and

I have a model Reservation with reserved_from and reserve_to attributes of type date. I want create a scope of all reservations where Date.today is between reserved_from and reserved_to. In the model I've done:

def self.today_reservation     find_each do |res|         if (Date.today).between?(res.reserved_from, res.reserved_to)                 return         else                 puts "false"         end     end   end   scope :today_reservations, today_reservation

but it doesn't work. If reserved_from is 2012-11-01 and reserved_to is 2012-11-02 and Date.today is 2012-11-14 the method above method return an activerecord relation.

That is not how scopes work. You need something like (not tested) scope :today_reservations, lambda { where("reserved_from > ? and reserved_to <= ?", Date.today, Date.today ) }

Without lamda it's the same thing? scope :today_reservations, where("reserved_from > ? and

reserved_to <= ?", Date.today, Date.today ) works the same.

No it doesn't. Well it does today but if you don't restart the server then it won't work tomorrow. Without the lambda it is determining Date.today only once when it loads that line of code. You need the lambda so that it recalculates it every time you run the scope.

Colin

>>> I have a model Reservation with reserved_from and reserve_to >>> attributes of type date. >>> I want create a scope of all reservations where Date.today is between >>> reserved_from and reserved_to. >>> In the model I've done: >>> >>> def self.today_reservation >>> find_each do |res| >>> if (Date.today).between?(res.reserved_from, res.reserved_to) >>> return >>> else >>> puts "false" >>> end >>> end >>> end >>> scope :today_reservations, today_reservation >>> >>> but it doesn't work. >>> If reserved_from is 2012-11-01 and reserved_to is 2012-11-02 and >>> Date.today is 2012-11-14 the method above method return an >>> activerecord relation. >> >> That is not how scopes work. You need something like (not tested) >> scope :today_reservations, lambda { where("reserved_from > ? and >> reserved_to <= ?", Date.today, Date.today ) } > > Without lamda it's the same thing? > scope :today_reservations, where("reserved_from > ? and >> reserved_to <= ?", Date.today, Date.today ) works the same.

No it doesn't. Well it does today but if you don't restart the server then it won't work tomorrow. Without the lambda it is determining Date.today only once when it loads that line of code. You need the lambda so that it recalculates it every time you run the scope.

Colin is right but you can also use class methods so you dont have to worry about adding lambdas

def self.today_reservations   where('reserved_from > :date AND reserved_to <= :date', date: Date.today) end

Does that have any advantage over using a scope? It has the disadvantage that one could not say things like Reservation.where(some conditions).today_reservations

In fact I think my previous comment only applies to production mode since the code would be reloaded for each request in development mode and so all would appear to work well - until deployment that is. I am not even sure how to write a test that would fail for the code without the lambda.

Colin

> > > >> >> >>> I have a model Reservation with reserved_from and reserve_to >> >>> attributes of type date. >> >>> I want create a scope of all reservations where Date.today is between >> >>> reserved_from and reserved_to. >> >>> In the model I've done: >> >>> >> >>> def self.today_reservation >> >>> find_each do |res| >> >>> if (Date.today).between?(res.reserved_from, res.reserved_to) >> >>> return >> >>> else >> >>> puts "false" >> >>> end >> >>> end >> >>> end >> >>> scope :today_reservations, today_reservation >> >>> >> >>> but it doesn't work. >> >>> If reserved_from is 2012-11-01 and reserved_to is 2012-11-02 and >> >>> Date.today is 2012-11-14 the method above method return an >> >>> activerecord relation. >> >> >> >> That is not how scopes work. You need something like (not tested) >> >> scope :today_reservations, lambda { where("reserved_from > ? and >> >> reserved_to <= ?", Date.today, Date.today ) } >> > >> > Without lamda it's the same thing? >> > scope :today_reservations, where("reserved_from > ? and >> >> reserved_to <= ?", Date.today, Date.today ) works the same. >> >> No it doesn't. Well it does today but if you don't restart the server >> then it won't work tomorrow. Without the lambda it is determining >> Date.today only once when it loads that line of code. You need the >> lambda so that it recalculates it every time you run the scope. > > > Colin is right but you can also use class methods so you dont have to worry > about > adding lambdas > > def self.today_reservations > where('reserved_from > :date AND reserved_to <= :date', date: Date.today) > end

Does that have any advantage over using a scope? It has the disadvantage that one could not say things like Reservation.where(some conditions).today_reservations

i don't know if it has any advantage but you can definitely do that. You can chain class methods as long as the method returns an active record relation

def self.foo   # build conditions here   where(conds) end

def self.order_method   order(order_here) end

then you can use these methods like scopes

Reservation.foo.order_method.where(foo)

In fact I think my previous comment only applies to production mode

Experimentation shows me that you are right, that is a bit of rails magic that I was not aware of. In fact it seems that one can call any class method on an ActiveRecord relation for the class. Thanks for the education.

So the question is, is there any significant difference between a scope with a lambda and a class method performing the same operation?

Colin

Experimentation shows me that you are right, that is a bit of rails magic that I was not aware of. In fact it seems that one can call any class method on an ActiveRecord relation for the class. Thanks for the education.

It's one of my favorite things to do with ActiveRecord, especially when storing certain types of records in things like Memcached where security is more of a cocern to me than a database (in that it has no scoped ACL like our db's) so I always do something like only with a where or find_by_* especially since arel (or it might be activerecord itself) is smart enough to build the entire query long before the last method in the chain.

So the question is, is there any significant difference between a scope with a lambda and a class method performing the same operation?

just reordering your chain in some cases it might not work at all. One would have to provide scenarios for a question like this because it's really up in the air with such a broad scope.

I was trying to ask the general question, that if one has a scope and a class method that perform exactly the same operation (such as the example in this thread), so

scope :today_reservations, lambda { where("reserved_from > ? and reserved_to <= ?", Date.today, Date.today ) }

and

self.today_reservations   where("reserved_from > ? and reserved_to <= ?", Date.today, Date.today ) } end

Is there actually any difference between the two, or is the former just a way of defining the latter in a railsy sort of way?

Colin

From what I remember briefly while playing (since I have always preferred the latter) scope is like attr_writer and attr_reader in that it's all the same in the end one just gives you more control over the flow, the other does it all for you but in the end, the result is exactly the same.

OK, thanks

Colin

I believe some consider the existance of scope :blah, … to be an error - it adds complexity internally and the potential for the super common lack of lambda error without adding any functionality. I can’t remember who said it though.

Fred