Scopes using ARel `where` statement containing TimeWithZone arguments behave differently by order #6635

Closed
lucasprim opened this Issue Jun 5, 2012 · 6 comments

Comments

Projects
None yet
2 participants

I've stumbled upon a weird behavior today. I have these two scopes implemented on my model:

class Purchase
  scope :since, lambda { |time| where('created_at >= ?', time) }
  scope :to, lambda { |time| where('created_at <= ?', time) }
end

And when i put arguments on the following order:

Purchase.since(Time.zone.now - 1.day).to(Time.zone.now)

i get an exception:

TypeError: can't convert ActiveSupport::TimeWithZone into Integer
    from /home/lucasprim/.rvm/gems/ruby-1.9.3-p125@kimitachi32/gems/activesupport-3.2.3/lib/active_support/core_ext/array/access.rb:19:in `first'
    from /home/lucasprim/.rvm/gems/ruby-1.9.3-p125@kimitachi32/gems/activesupport-3.2.3/lib/active_support/core_ext/array/access.rb:19:in `to'
    from /home/lucasprim/.rvm/gems/ruby-1.9.3-p125@kimitachi32/gems/activerecord-3.2.3/lib/active_record/relation/delegation.rb:36:in `to'
    from (irb):15
    from /home/lucasprim/.rvm/gems/ruby-1.9.3-p125@kimitachi32/gems/railties-3.2.3/lib/rails/commands/console.rb:47:in `start'
    from /home/lucasprim/.rvm/gems/ruby-1.9.3-p125@kimitachi32/gems/railties-3.2.3/lib/rails/commands/console.rb:8:in `start'
    from /home/lucasprim/.rvm/gems/ruby-1.9.3-p125@kimitachi32/gems/railties-3.2.3/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

But when i perform the same query on another order, the query performs fine:

1.9.3p125 :018 > Purchase.to(Time.zone.now).since(Time.zone.now - 1.day).to_sql
 => "SELECT `purchases`.* FROM `purchases`  WHERE (created_at <= '2012-06-05 13:31:29') AND (created_at >= '2012-06-04 13:31:29')" 
Contributor

kennyj commented Jun 6, 2012

I can reproduce this issue. And I realize the cause of this one (maybe).

If you execute since method, a return value class is ActiveRecord::Relation.
But, ActiveRecord::Relation has many delegations.

$ vim rails/activerecord/lib/active_record/relation/delegation.rb
...
    delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to_ary, :to => :to_a
    delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key,
             :connection, :columns_hash, :auto_explain_threshold_in_seconds, :to => :klass
...

Thus, when you call to method, really you can't call your to method, but you call Array#to method.
If you rename to to to2, maybe it's work fine.

I'll try to consider this problem tomorrow.

Contributor

kennyj commented Jun 7, 2012

Hi @lucasprim
I think I fixed this issue by the above commit :-)
Can you confirm it ?

@kennyj sorry for the delay! i'm out of office for the week! as soon as i get to my office again i can tell you if it worked! Thanks a lot!

Contributor

kennyj commented Jun 10, 2012

@lucasprim I believe my commit solve your problem. Anyway, I'm going to submit PR :-)
If you confirm it, please tell me.

kennyj closed this in cd1be1a Jun 10, 2012

@ganeshkumar ganeshkumar pushed a commit to ganeshkumar/rails that referenced this issue Jun 10, 2012

@rafaelfranca rafaelfranca Merge pull request #6695 from kennyj/fix_6635
Fix #6635. We should call Scoping methods, before calling Array methods.
4da1af7

absolutely fixed! thanks a lot @kennyj

Contributor

kennyj commented Jun 11, 2012

My pleasure 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment