Here''s an idea, I''m making an import module for a customer and have to look up related models all the time to link them to the imported record; ... @item.color = Color.find_by_name(color_from_import) ... Instead of hitting the database all the time, I''m extending the array class with a "search" call that searches values in a preloaded list "ActiveRecord find" style; @colors = Color.all ... @item.color = @colors.search(:first, :conditions => { :name => color_from_import }) or @item.color = @colors.search(12) @item.color = @colors.search(:all, :conditions => { :name => /test/}) Can someone tell me if behaviour like this is already implementent (in core or using a plugin)? Here is my (premature) plugin code; http://pastie.org/570795 Stijn
Uh yeah, Color.all(:conditions => { :name => color_from_import }) http://guides.rubyonrails.org/active_record_querying.html 2009/8/4 Stijnster <stijn@skylight.be>> > Here''s an idea, > > I''m making an import module for a customer and have to look up related > models all the time to link them to the imported record; > > ... > @item.color = Color.find_by_name(color_from_import) > ... > > Instead of hitting the database all the time, I''m extending the array > class with a "search" call that searches values in a preloaded list > "ActiveRecord find" style; > > @colors = Color.all > ... > @item.color = @colors.search(:first, :conditions => { :name => > color_from_import }) > > or > > @item.color = @colors.search(12) > @item.color = @colors.search(:all, :conditions => { :name => /test/}) > > Can someone tell me if behaviour like this is already implementent (in > core or using a plugin)? Here is my (premature) plugin code; > > http://pastie.org/570795 > > > Stijn > > >-- Ryan Bigg --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
Oh and if you want to "preload" a list I recommend using with_scope to further scope down that list. 2009/8/4 Ryan Bigg (Radar) <radarlistener@gmail.com>> Uh yeah, Color.all(:conditions => { :name => color_from_import }) > > http://guides.rubyonrails.org/active_record_querying.html > > 2009/8/4 Stijnster <stijn@skylight.be> > > >> Here''s an idea, >> >> I''m making an import module for a customer and have to look up related >> models all the time to link them to the imported record; >> >> ... >> @item.color = Color.find_by_name(color_from_import) >> ... >> >> Instead of hitting the database all the time, I''m extending the array >> class with a "search" call that searches values in a preloaded list >> "ActiveRecord find" style; >> >> @colors = Color.all >> ... >> @item.color = @colors.search(:first, :conditions => { :name => >> color_from_import }) >> >> or >> >> @item.color = @colors.search(12) >> @item.color = @colors.search(:all, :conditions => { :name => /test/}) >> >> Can someone tell me if behaviour like this is already implementent (in >> core or using a plugin)? Here is my (premature) plugin code; >> >> http://pastie.org/570795 >> >> >> Stijn >> >> >> > > > -- > Ryan Bigg >-- Ryan Bigg --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
Ryan, he is talking about a mechanism for use with already-loaded arrays or collections, so reducing the number of queries made, as is clear from his examples. Regarding your next email, there is no mechanism to preload several named_scopes on the same model with different conditions in one query, nor would it be at all easy to do in SQL, and reducing the number of separate queries needed is what Stinjster''s interested in. Stinjster, I''m not aware of a mechanism to do this. I think it would sometimes be useful, but it''s probably not going to get used by too many people as most of the time people just need to load a certain set of records, and then index them by a particular thing. For example, it''s quite common to use: @colors_by_name = Color.all.index_by(&:name) @item.color = @colors[color_for_import] What you''re talking about is really a more generalised mechanism for doing Enumerable#detect calls, but I think they''re already short enough to write for the bulk of use cases, so I would say that most people would be happy to use: @item.color = @colors.detect {|color| color.name =~ /test} which isn''t really any more verbose than: @item.color = @colors.search(:all, :conditions => {:name => /test/}) (And is more powerful since you can put in arbitrary ruby code.) Could you give an example where a #search method is really a time saver over #detect? On Tue, Aug 4, 2009 at 10:02 PM, Ryan Bigg (Radar)<radarlistener@gmail.com> wrote:> Uh yeah, Color.all(:conditions => { :name => color_from_import }) > > http://guides.rubyonrails.org/active_record_querying.html > 2009/8/4 Stijnster <stijn@skylight.be> >> >> Here''s an idea, >> >> I''m making an import module for a customer and have to look up related >> models all the time to link them to the imported record; >> >> ... >> @item.color = Color.find_by_name(color_from_import) >> ... >> >> Instead of hitting the database all the time, I''m extending the array >> class with a "search" call that searches values in a preloaded list >> "ActiveRecord find" style; >> >> @colors = Color.all >> ... >> @item.color = @colors.search(:first, :conditions => { :name => >> color_from_import }) >> >> or >> >> @item.color = @colors.search(12) >> @item.color = @colors.search(:all, :conditions => { :name => /test/}) >> >> Can someone tell me if behaviour like this is already implementent (in >> core or using a plugin)? Here is my (premature) plugin code; >> >> http://pastie.org/570795 >> >> >> Stijn >> > > > > -- > Ryan Bigg > > > >
Hi Will, indeed, I am looking for a way to search in already loaded sets, instead of caching the query itself. When running an import job, I want to prevent a hit on the database for each color lookup when I''m importing +1000 of records. Detect sounds great! It would indeed help me to identify all records. So I think I''ll go with that. Thanks for pointing me into that direction. One thing detect doesn''t do (for as far as I can see/test) is return a set that matches the detected data (e.g. when "blue" is found several times, using a regexp, it would only return the first instance where blue is detected). In my example above you can specify :all, :one, :first, ... which return the appropriate result. But again, thanks for your advice! Stijn On Aug 4, 12:12 pm, Will Bryant <will.bry...@gmail.com> wrote:> Ryan, he is talking about a mechanism for use with already-loaded > arrays or collections, so reducing the number of queries made, as is > clear from his examples. > > Regarding your next email, there is no mechanism to preload several > named_scopes on the same model with different conditions in one query, > nor would it be at all easy to do in SQL, and reducing the number of > separate queries needed is what Stinjster''s interested in. > > Stinjster, I''m not aware of a mechanism to do this. I think it would > sometimes be useful, but it''s probably not going to get used by too > many people as most of the time people just need to load a certain set > of records, and then index them by a particular thing. For example, > it''s quite common to use: > > @colors_by_name = Color.all.index_by(&:name) > @item.color = @colors[color_for_import] > > What you''re talking about is really a more generalised mechanism for > doing Enumerable#detect calls, but I think they''re already short > enough to write for the bulk of use cases, so I would say that most > people would be happy to use: > > @item.color = @colors.detect {|color| color.name =~ /test} > > which isn''t really any more verbose than: > > @item.color = @colors.search(:all, :conditions => {:name => /test/}) > > (And is more powerful since you can put in arbitrary ruby code.) > > Could you give an example where a #search method is really a time > saver over #detect? > > On Tue, Aug 4, 2009 at 10:02 PM, Ryan Bigg > > (Radar)<radarliste...@gmail.com> wrote: > > Uh yeah, Color.all(:conditions => { :name => color_from_import }) > > >http://guides.rubyonrails.org/active_record_querying.html > > 2009/8/4 Stijnster <st...@skylight.be> > > >> Here''s an idea, > > >> I''m making an import module for a customer and have to look up related > >> models all the time to link them to the imported record; > > >> ... > >> @item.color = Color.find_by_name(color_from_import) > >> ... > > >> Instead of hitting the database all the time, I''m extending the array > >> class with a "search" call that searches values in a preloaded list > >> "ActiveRecord find" style; > > >> @colors = Color.all > >> ... > >> @item.color = @colors.search(:first, :conditions => { :name => > >> color_from_import }) > > >> or > > >> @item.color = @colors.search(12) > >> @item.color = @colors.search(:all, :conditions => { :name => /test/}) > > >> Can someone tell me if behaviour like this is already implementent (in > >> core or using a plugin)? Here is my (premature) plugin code; > > >>http://pastie.org/570795 > > >> Stijn > > > -- > > Ryan Bigg
Cool, glad to help. You want Enumerable#select (aka #grep) to return an array of all the matching results. Making the most out of Ruby''s built-in (or ActiveSupport-extended) Enumerable functionality is a common area for improvement people see, so I think there are some good guides out there - google should sort you out. Cheers, Will On Tue, Aug 4, 2009 at 10:25 PM, Stijnster<stijn@skylight.be> wrote:> > Hi Will, > > indeed, I am looking for a way to search in already loaded sets, > instead of caching the query itself. When running an import job, I > want to prevent a hit on the database for each color lookup when I''m > importing +1000 of records. > > Detect sounds great! It would indeed help me to identify all records. > So I think I''ll go with that. Thanks for pointing me into that > direction. > > One thing detect doesn''t do (for as far as I can see/test) is return a > set that matches the detected data (e.g. when "blue" is found several > times, using a regexp, it would only return the first instance where > blue is detected). In my example above you can > specify :all, :one, :first, ... which return the appropriate result. > > But again, thanks for your advice! > > > Stijn > > > > > > On Aug 4, 12:12 pm, Will Bryant <will.bry...@gmail.com> wrote: >> Ryan, he is talking about a mechanism for use with already-loaded >> arrays or collections, so reducing the number of queries made, as is >> clear from his examples. >> >> Regarding your next email, there is no mechanism to preload several >> named_scopes on the same model with different conditions in one query, >> nor would it be at all easy to do in SQL, and reducing the number of >> separate queries needed is what Stinjster''s interested in. >> >> Stinjster, I''m not aware of a mechanism to do this. I think it would >> sometimes be useful, but it''s probably not going to get used by too >> many people as most of the time people just need to load a certain set >> of records, and then index them by a particular thing. For example, >> it''s quite common to use: >> >> @colors_by_name = Color.all.index_by(&:name) >> @item.color = @colors[color_for_import] >> >> What you''re talking about is really a more generalised mechanism for >> doing Enumerable#detect calls, but I think they''re already short >> enough to write for the bulk of use cases, so I would say that most >> people would be happy to use: >> >> @item.color = @colors.detect {|color| color.name =~ /test} >> >> which isn''t really any more verbose than: >> >> @item.color = @colors.search(:all, :conditions => {:name => /test/}) >> >> (And is more powerful since you can put in arbitrary ruby code.) >> >> Could you give an example where a #search method is really a time >> saver over #detect? >> >> On Tue, Aug 4, 2009 at 10:02 PM, Ryan Bigg >> >> (Radar)<radarliste...@gmail.com> wrote: >> > Uh yeah, Color.all(:conditions => { :name => color_from_import }) >> >> >http://guides.rubyonrails.org/active_record_querying.html >> > 2009/8/4 Stijnster <st...@skylight.be> >> >> >> Here''s an idea, >> >> >> I''m making an import module for a customer and have to look up related >> >> models all the time to link them to the imported record; >> >> >> ... >> >> @item.color = Color.find_by_name(color_from_import) >> >> ... >> >> >> Instead of hitting the database all the time, I''m extending the array >> >> class with a "search" call that searches values in a preloaded list >> >> "ActiveRecord find" style; >> >> >> @colors = Color.all >> >> ... >> >> @item.color = @colors.search(:first, :conditions => { :name => >> >> color_from_import }) >> >> >> or >> >> >> @item.color = @colors.search(12) >> >> @item.color = @colors.search(:all, :conditions => { :name => /test/}) >> >> >> Can someone tell me if behaviour like this is already implementent (in >> >> core or using a plugin)? Here is my (premature) plugin code; >> >> >>http://pastie.org/570795 >> >> >> Stijn >> >> > -- >> > Ryan Bigg > > >
> One thing detect doesn''t do (for as far as I can see/test) is return a > set that matches the detected data (e.g. when "blue" is found several > times, using a regexp, it would only return the first instance where > blue is detected).Use Enumerable#select for that: array.select { |x| x.color =~ /blue/ } Eloy
Great! Ruby keeps amazing me, thanks for all the tips guys. Stijn On Aug 4, 12:32 pm, Eloy Duran <eloy.de.en...@gmail.com> wrote:> > One thing detect doesn''t do (for as far as I can see/test) is return a > > set that matches the detected data (e.g. when "blue" is found several > > times, using a regexp, it would only return the first instance where > > blue is detected). > > Use Enumerable#select for that: array.select { |x| x.color =~ /blue/ } > > Eloy