Hello,
I came across what I believe is to be a bug in ActiveRecord with the
latest revision of edge rails.
Basically what the problem deals with is any passed options to a
secondary find which are being modified internally when I believe they
shouldn''t be. Further explanation is easiest with code, so
I''ll just
jump right into it.
Here''s my scenario. I have two models, Division and Team, and one
controller TestController...
class Team < ActiveRecord::Base
# don''t need anything to show the bug
end
class Division < ActiveRecord::Base
has_many :teams
end
class TestController < ApplicationController
def index
options = {:limit => 10}
logger.debug Division.find(1).teams.find(:all, options)
logger.debug Division.find(2).teams.find(:all, options)
logger.debug Division.find(3).teams.find(:all, options)
render :text => ''complete''
end
end
This produces the following sql in the order seen in the controller
(notice how the WHERE clause keeps getting appended too?)
SELECT * FROM teams WHERE (teams.division_id = 1)
SELECT * FROM teams WHERE (teams.division_id = 2 AND
(teams.division_id = 1)) LIMIT 10
SELECT * FROM teams WHERE (teams.division_id = 3 AND
(teams.division_id = 2 AND (teams.division_id = 1))) LIMIT 10
Now if I change the controller method to the following the "error" is
gone.
def index
logger.debug Division.find(1).teams.find :all, {:limit => 10}
logger.debug Division.find(2).teams.find :all, {:limit => 10}
logger.debug Division.find(3).teams.find :all, {:limit => 10}
render :text => ''complete''
end
So the options are being modified on subsequent calls here which I
would say is not good. This is a narrowed down example from some real
code I''m using, but the essence of the problem is the same. I dug
around some of the rails code, but didn''t see anything obvious right
away.
Thanks,
Andrew
On 3/23/06, Andrew Kaspick <akaspick@gmail.com> wrote:> Hello, > > I came across what I believe is to be a bug in ActiveRecord with the > latest revision of edge rails. > > Basically what the problem deals with is any passed options to a > secondary find which are being modified internally when I believe they > shouldn''t be. Further explanation is easiest with code, so I''ll just > jump right into it. > > Here''s my scenario. I have two models, Division and Team, and one > controller TestController... > > class Team < ActiveRecord::Base > # don''t need anything to show the bug > end > > class Division < ActiveRecord::Base > has_many :teams > end > > class TestController < ApplicationController > def index > options = {:limit => 10} > > logger.debug Division.find(1).teams.find(:all, options) > logger.debug Division.find(2).teams.find(:all, options) > logger.debug Division.find(3).teams.find(:all, options) > > render :text => ''complete'' > end > end > > This produces the following sql in the order seen in the controller > (notice how the WHERE clause keeps getting appended too?) > > SELECT * FROM teams WHERE (teams.division_id = 1) > SELECT * FROM teams WHERE (teams.division_id = 2 AND > (teams.division_id = 1)) LIMIT 10 > SELECT * FROM teams WHERE (teams.division_id = 3 AND > (teams.division_id = 2 AND (teams.division_id = 1))) LIMIT 10 > > Now if I change the controller method to the following the "error" is gone. > > def index > logger.debug Division.find(1).teams.find :all, {:limit => 10} > logger.debug Division.find(2).teams.find :all, {:limit => 10} > logger.debug Division.find(3).teams.find :all, {:limit => 10} > > render :text => ''complete'' > end > > So the options are being modified on subsequent calls here which I > would say is not good. This is a narrowed down example from some real > code I''m using, but the essence of the problem is the same. I dug > around some of the rails code, but didn''t see anything obvious right > away. > > Thanks, > AndrewThe scoping method must be directly modifying the hash. Try this: Division.find(1).teams.find(:all, options.dup) Division.find(1).teams.find(:all, options.dup) Division.find(1).teams.find(:all, options.dup) -- Rick Olson http://techno-weenie.net
Andrew Kaspick wrote:> options = {:limit => 10} > > logger.debug Division.find(1).teams.find(:all, options) > logger.debug Division.find(2).teams.find(:all, options) > logger.debug Division.find(3).teams.find(:all, options) > > This produces the following sql in the order seen in the controller > (notice how the WHERE clause keeps getting appended too?) > > SELECT * FROM teams WHERE (teams.division_id = 1) > SELECT * FROM teams WHERE (teams.division_id = 2 AND > (teams.division_id = 1)) LIMIT 10 > SELECT * FROM teams WHERE (teams.division_id = 3 AND > (teams.division_id = 2 AND (teams.division_id = 1))) LIMIT 10 > > > So the options are being modified on subsequent calls here which I > would say is not good. This is a narrowed down example from some real > code I''m using, but the essence of the problem is the same. I dug > around some of the rails code, but didn''t see anything obvious right > away.The problem that the method extract_options_from_args! is not dup-ing the args of find.
Yes, I did that and works, just seems like a "hack" to an underlying issue. Currently the solutions you proposed is what I have done, but it took some time to figure it out. On 3/23/06, Rick Olson <technoweenie@gmail.com> wrote:> On 3/23/06, Andrew Kaspick <akaspick@gmail.com> wrote: > > Hello, > > > > I came across what I believe is to be a bug in ActiveRecord with the > > latest revision of edge rails. > > > > Basically what the problem deals with is any passed options to a > > secondary find which are being modified internally when I believe they > > shouldn''t be. Further explanation is easiest with code, so I''ll just > > jump right into it. > > > > Here''s my scenario. I have two models, Division and Team, and one > > controller TestController... > > > > class Team < ActiveRecord::Base > > # don''t need anything to show the bug > > end > > > > class Division < ActiveRecord::Base > > has_many :teams > > end > > > > class TestController < ApplicationController > > def index > > options = {:limit => 10} > > > > logger.debug Division.find(1).teams.find(:all, options) > > logger.debug Division.find(2).teams.find(:all, options) > > logger.debug Division.find(3).teams.find(:all, options) > > > > render :text => ''complete'' > > end > > end > > > > This produces the following sql in the order seen in the controller > > (notice how the WHERE clause keeps getting appended too?) > > > > SELECT * FROM teams WHERE (teams.division_id = 1) > > SELECT * FROM teams WHERE (teams.division_id = 2 AND > > (teams.division_id = 1)) LIMIT 10 > > SELECT * FROM teams WHERE (teams.division_id = 3 AND > > (teams.division_id = 2 AND (teams.division_id = 1))) LIMIT 10 > > > > Now if I change the controller method to the following the "error" is gone. > > > > def index > > logger.debug Division.find(1).teams.find :all, {:limit => 10} > > logger.debug Division.find(2).teams.find :all, {:limit => 10} > > logger.debug Division.find(3).teams.find :all, {:limit => 10} > > > > render :text => ''complete'' > > end > > > > So the options are being modified on subsequent calls here which I > > would say is not good. This is a narrowed down example from some real > > code I''m using, but the essence of the problem is the same. I dug > > around some of the rails code, but didn''t see anything obvious right > > away. > > > > Thanks, > > Andrew > > The scoping method must be directly modifying the hash. Try this: > > Division.find(1).teams.find(:all, options.dup) > Division.find(1).teams.find(:all, options.dup) > Division.find(1).teams.find(:all, options.dup) > > -- > Rick Olson > http://techno-weenie.net > _______________________________________________ > Rails-core mailing list > Rails-core@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails-core >
My last response was to Rick''s message, not Mark''s. I''ll blame gmail for the confusion. :) Mark''s response looks to be correct. On 3/23/06, Andrew Kaspick <akaspick@gmail.com> wrote:> Yes, I did that and works, just seems like a "hack" to an underlying > issue. Currently the solutions you proposed is what I have done, but > it took some time to figure it out. > > On 3/23/06, Rick Olson <technoweenie@gmail.com> wrote: > > On 3/23/06, Andrew Kaspick <akaspick@gmail.com> wrote: > > > Hello, > > > > > > I came across what I believe is to be a bug in ActiveRecord with the > > > latest revision of edge rails. > > > > > > Basically what the problem deals with is any passed options to a > > > secondary find which are being modified internally when I believe they > > > shouldn''t be. Further explanation is easiest with code, so I''ll just > > > jump right into it. > > > > > > Here''s my scenario. I have two models, Division and Team, and one > > > controller TestController... > > > > > > class Team < ActiveRecord::Base > > > # don''t need anything to show the bug > > > end > > > > > > class Division < ActiveRecord::Base > > > has_many :teams > > > end > > > > > > class TestController < ApplicationController > > > def index > > > options = {:limit => 10} > > > > > > logger.debug Division.find(1).teams.find(:all, options) > > > logger.debug Division.find(2).teams.find(:all, options) > > > logger.debug Division.find(3).teams.find(:all, options) > > > > > > render :text => ''complete'' > > > end > > > end > > > > > > This produces the following sql in the order seen in the controller > > > (notice how the WHERE clause keeps getting appended too?) > > > > > > SELECT * FROM teams WHERE (teams.division_id = 1) > > > SELECT * FROM teams WHERE (teams.division_id = 2 AND > > > (teams.division_id = 1)) LIMIT 10 > > > SELECT * FROM teams WHERE (teams.division_id = 3 AND > > > (teams.division_id = 2 AND (teams.division_id = 1))) LIMIT 10 > > > > > > Now if I change the controller method to the following the "error" is gone. > > > > > > def index > > > logger.debug Division.find(1).teams.find :all, {:limit => 10} > > > logger.debug Division.find(2).teams.find :all, {:limit => 10} > > > logger.debug Division.find(3).teams.find :all, {:limit => 10} > > > > > > render :text => ''complete'' > > > end > > > > > > So the options are being modified on subsequent calls here which I > > > would say is not good. This is a narrowed down example from some real > > > code I''m using, but the essence of the problem is the same. I dug > > > around some of the rails code, but didn''t see anything obvious right > > > away. > > > > > > Thanks, > > > Andrew > > > > The scoping method must be directly modifying the hash. Try this: > > > > Division.find(1).teams.find(:all, options.dup) > > Division.find(1).teams.find(:all, options.dup) > > Division.find(1).teams.find(:all, options.dup) > > > > -- > > Rick Olson > > http://techno-weenie.net > > _______________________________________________ > > Rails-core mailing list > > Rails-core@lists.rubyonrails.org > > http://lists.rubyonrails.org/mailman/listinfo/rails-core > > >