Hi ! I just have a simple question. I am writing an app using rails to familiarize myself with the framework (which is pretty cool, by the way). I just wanted to know why these two work differently (since "find" should be a synonym for "detect" according to the Pick Axe) : current_item = @invoice.line_items.detect {|i| i.product.id == key} current_item = @invoice.line_items.find {|i| i.product.id == key} (The details of my project are irrelevant, I think.) The first one works, the second doesn''t. With the "find" variant, I get this error : "Couldn''t find LineItem without an ID" It seems as though rails is trying to work with an ActiveRecord. Is this normal, or is it a bug ? By the way, could someone point me to somewhere I can find out about the "can''t modify frozen hash error" (or explain it) ? David Sulc
Find is an active record method that is part of the rails frame work, detect is part of Ruby. http://api.rubyonrails.com ~ Ben On 5/2/06, David Sulc <david.sulc@epfl.ch> wrote:> Hi ! > > I just have a simple question. > > I am writing an app using rails to familiarize myself with the framework (which is pretty cool, by the way). > > I just wanted to know why these two work differently (since "find" should be a synonym for "detect" according to the Pick Axe) : > > current_item = @invoice.line_items.detect {|i| i.product.id == key} > > current_item = @invoice.line_items.find {|i| i.product.id == key} > > (The details of my project are irrelevant, I think.) The first one works, the second doesn''t. With the "find" variant, I get this error : > > "Couldn''t find LineItem without an ID" > > It seems as though rails is trying to work with an ActiveRecord. Is this normal, or is it a bug ? > > By the way, could someone point me to somewhere I can find out about the "can''t modify frozen hash error" (or explain it) ? > > David Sulc > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Ben Reubenstein 303-947-0446 http://www.benr75.com
Correct. What I meant was that find is ALSO part of ruby (http://www.rubycentral.com/ref/ref_m_enumerable.html#find). Shouldn''t rails be able to select the correct method (i. e. Ruby method VS ActiveRecord method) according to the object on which find is called ? In my case it is called on an array, so the Ruby version should called, don''t you think ?> > Find is an active record method that is part of the rails frame work, > detect is part of Ruby. > > http://api.rubyonrails.com > > ~ Ben > > On 5/2/06, David Sulc <david.sulc@epfl.ch> wrote: > >> Hi ! >> >> I just have a simple question. >> >> I am writing an app using rails to familiarize myself with the >> framework (which is pretty cool, by the way). >> >> I just wanted to know why these two work differently (since "find" >> should be a synonym for "detect" according to the Pick Axe) : >> >> current_item = @invoice.line_items.detect {|i| i.product.id == key} >> >> current_item = @invoice.line_items.find {|i| i.product.id == key} >> >> (The details of my project are irrelevant, I think.) The first one >> works, the second doesn''t. With the "find" variant, I get this error : >> >> "Couldn''t find LineItem without an ID" >> >> It seems as though rails is trying to work with an ActiveRecord. Is >> this normal, or is it a bug ? >> >> By the way, could someone point me to somewhere I can find out about >> the "can''t modify frozen hash error" (or explain it) ? >> >> David Sulc >> > > > -- > Ben Reubenstein > 303-947-0446 > http://www.benr75.com >
Hello David,> I just wanted to know why these two work differently (since "find" > should be a synonym for "detect" according to the Pick Axe) : > > current_item = @invoice.line_items.detect {|i| i.product.id == key} > > current_item = @invoice.line_items.find {|i| i.product.id == key} > > (The details of my project are irrelevant, I think.) The first one works, > the second doesn''t. With the "find" variant, I get this error : > > "Couldn''t find LineItem without an ID" > > It seems as though rails is trying to work with an ActiveRecord. Is this > normal, or is it a bug ?with a :has_many association, your collection gets additional methods : See: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#M000530 "collection.find - finds an associated object according to the same rules as Base.find." "Firm#clients.find (similar to Client.find(id, :conditions => "firm_id = #{id}")) " By the way, if a method doesn''t use a block passed during the call, Ruby doesn''t bother : irb(main):001:0> def foo; puts "hello world";end => nil irb(main):002:0> foo { puts "hello sky" } hello world => nil> By the way, could someone point me to somewhere I can find out > about the "can''t modify frozen hash error" (or explain it) ?If an object is frozen, you can''t modify its attributes, the object becomes immutable. So for an hash : irb(main):003:0> h = { :foo => :bar } => {:foo=>:bar} irb(main):004:0> h.freeze => {:foo=>:bar} irb(main):005:0> h[:ga] = :bu TypeError: can''t modify frozen hash from (irb):5:in `[]='' from (irb):5 from :0 -- Jean-Fran?ois. -- ? la renverse.
David Sulc wrote:> Correct. What I meant was that find is ALSO part of ruby > (http://www.rubycentral.com/ref/ref_m_enumerable.html#find). Shouldn''t > rails be able to select the correct method (i. e. Ruby method VS > ActiveRecord method) according to the object on which find is called ?The problem is that the selection of the correct method is done by the object that receives the message - which in this case is @invoice.line_items, which has a find method that differs from Enumerable#find.> In my case it is called on an array, so the Ruby version should called, > don''t you think ?@invoice.line_items here isn''t just an Array, it''s an Array with a whole bunch of mixins to modify behaviour - part of which is to add the custom find method, overriding the original. From script/console, doing @invoice.line_items.class should show Array, but @invoice.line_items.ancestors will show something like: [FragmentHolder, ActiveRecord::Base, ActsAsBackground, FileColumn::Validations, FileColumn, ActiveRecord::Acts::NestedSet, ActiveRecord::Acts::List, ActiveRecord::Acts::Tree, ActiveRecord::Reflection, ActiveRecord::Transactions, ActiveRecord::Aggregations, ActiveRecord::Associations, ActiveRecord::Timestamp, ActiveRecord::Observing, ActiveRecord::Callbacks, ActiveRecord::Locking, ActiveRecord::Validations, Object, PP::ObjectMixin, Base64::Deprecated, Base64, Kernel] If you want the original find() method, you can call @invoice.line_items.to_a to get a vanilla Array. -- Alex