I have an Event model which has_many :attendees. My Attendee model has a
column called participants, which is an integer representing the number
of participants in the attendees party. I want to sum the total number
of participants for a given event. This works fine if I just the default
option of 0 for the method inject, but inject fails if you don’t give it
a default. In ruby, injects normal behavior will default the sum to 0 if
you don’t provide an argument. See my console output below:
myevent = Event.find(1)
=> #<Event:0x34d95ec @attributes={“title”=>“Canned Food Drive”,
“date”=>“2007-02-01 12:00:00”, “id”=>“1”, “description”=>“We need a
least 20 people to sign up for the canned food drive. This will could
toward service hours and will be a great event to help younger scouts
get involved with the community. We will be collecting, sorting and
delivering donated cans.”, “rsvp_date”=>“2007-01-15”,
“permission_url”=>"/docs/permission.jpg", “location”=>“Saint David’s”}>
myevent.attendees.inject(0){|sum,att| sum = att.participants}
=> 1
As you can see, if a default of 0 is not provided, inject returns an
instance of the Attendee class rather than the value in sum. Very
strange…
My inject statements should have read inject{|sum,att| sum +
att.participants}. I’ve rerun the code, now I am getting a full-fledged
error when I don’t provide a default value:
myevent.attendees.inject{|sum,att| sum + att.participants}
NoMethodError: undefined method +' for #<Attendee:0x34cca90> from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.14.4.5618/lib/active_record/base.rb:1848:inmethod_missing’
from (irb):2
from
/opt/local/lib/ruby/gems/1.8/gems/activerecord-1.14.4.5618/lib/active_record/base.rb:1928:in inject' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.14.4.5618/lib/active_record/associations/association_proxy.rb:123:ineach’
from
/opt/local/lib/ruby/gems/1.8/gems/activerecord-1.14.4.5618/lib/active_record/associations/association_proxy.rb:123:in inject' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.14.4.5618/lib/active_record/associations/association_proxy.rb:123:insend’
from
/opt/local/lib/ruby/gems/1.8/gems/activerecord-1.14.4.5618/lib/active_record/associations/association_proxy.rb:123:in method_missing' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.14.4.5618/lib/active_record/associations/has_many_association.rb:98:inmethod_missing’
from (irb):2
myevent.attendees.inject(0){|sum,att| sum + att.participants}
=> 5
NoMethodError: undefined method +' for #<Attendee:0x34cca90> from method_missing’
from (irb):2>> myevent.attendees.inject(0){|sum,att| sum + att.participants}
=> 5
–
Posted viahttp://www.ruby-forum.com/.
IIRC,
Calling inject with no parameter copies the first element of the
enumerable into the accumulator. In this case it fills it with the
first attendee. It never calls ‘participants’ on it.
This works fine when you are using it on numbers, but runs into
trouble with more complicated data types.
Doing this would probably work as you expect.
myevent.attendees.map(&:participants).inject {|sum,att| sum + att}
_Kevin
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.