ruby on rails - ActiveModel::MissingAttributeError (can't write unknown attribute 'Russian Federation'): -
getting strange error when running reduce on activemodel relation. seems calling "c.name" in reduce code causes error. c.name returns string "russian federation". using reduce incorrectly?
here error:
[2014-03-17t21:12:40.174655 #9240] fatal -- : activemodel::missingattributeerror (can't write unknown attribute `russian federation'): app/controllers/registrations_controller.rb:96:in `block in pluck_countries' app/controllers/registrations_controller.rb:96:in `pluck_countries' larger stacktrace console:
@third_party_countries.reduce(@hsh) {|hsh, c| hsh[c.name] = thirdpartyshipping.first } activemodel::missingattributeerror: can't write unknown attribute `russian federation' /var/www/html/babiators.com/landf/vendor/bundle/ruby/2.0.0/gems/activerecord-4.0.2/lib/active_record/attribute_methods/write.rb:47:in `write_attribute' /var/www/html/babiators.com/landf/vendor/bundle/ruby/2.0.0/gems/activerecord-4.0.2/lib/active_record/attribute_methods/dirty.rb:70:in `write_attribute' /var/www/html/babiators.com/landf/vendor/bundle/ruby/2.0.0/gems/activerecord-4.0.2/lib/active_record/attribute_methods.rb:341:in `[]=' (irb):3:in `block in irb_binding' /var/www/html/babiators.com/landf/vendor/bundle/ruby/2.0.0/gems/activerecord-4.0.2/lib/active_record/relation/delegation.rb:63:in `each' /var/www/html/babiators.com/landf/vendor/bundle/ruby/2.0.0/gems/activerecord-4.0.2/lib/active_record/relation/delegation.rb:63:in `reduce' /var/www/html/babiators.com/landf/vendor/bundle/ruby/2.0.0/gems/activerecord-4.0.2/lib/active_record/relation/delegation.rb:63:in `method_missing' (irb):3 /var/www/html/babiators.com/landf/vendor/bundle/ruby/2.0.0/gems/railties-4.0.2/lib/rails/commands/console.rb:90:in `start' /var/www/html/babiators.com/landf/vendor/bundle/ruby/2.0.0/gems/railties-4.0.2/lib/rails/commands/console.rb:9:in `start' /var/www/html/babiators.com/landf/vendor/bundle/ruby/2.0.0/gems/railties-4.0.2/lib/rails/commands.rb:62:in `<top (required)>' bin/rails:4:in `require' bin/rails:4:in `<main>' here code:
@third_party_countries = country.third_party_countries @hsh = hashwithindifferentaccess.new @third_party_countries.reduce(@hsh) {|hsh, c| hsh[c.name] = c.third_party_shipping } country schema:
create_table "countries", force: true |t| t.string "name" t.float "shipping_rate" t.integer "third_party_shipping_id" t.datetime "created_at" t.datetime "updated_at" t.integer "product_id" end country model:
class country < activerecord::base belongs_to :third_party_shipping has_and_belongs_to_many :products has_many :addresses validates_presence_of :name validates_uniqueness_of :name before_create :init after_initialize :init scope :shippable, -> { where(third_party_shipping_id: nil) } scope :third_party_countries, -> { where.not(third_party_shipping_id: nil) } def shipping_price self.shipping_rate * 100 end def free_shipping self.shipping_rate <= 0 , self.third_party_shipping_id.nil? end def paid_shipping !self.free_shipping end def shipping_display if self.free_shipping "free" elsif self.paid_shipping self.shipping_rate end end private def init if self.shipping_rate.blank? self.shipping_rate = 0 end end end
since you're declaring @hsh outside loop, have no need of complexity introduced inject/reduce. use each:
@hsh = hashwithindifferentaccess.new @third_party_countries.each{ |c| @hsh[c.name] = c.third_party_shipping } the problem existing code that, inject/reduce, return value of block passed first argument next invocation. need return hsh block, otherwise value of c.third_party_shipping passed hsh next invocation, , you're doing c.third_party_shipping[c.name].
you could make work returning hsh...
@third_party_countries.reduce(@hsh) |hsh, c| hsh[c.name] = c.third_party_shipping hsh end but shouldn't. don't need functionality. each_with_object correct method use:
@hsh = @third_party_countries.each_with_object(hashwithindifferentaccess.new) |hsh, c| hsh[c.name] = c.third_party_shipping end you map collection array, , initialize hash array:
@hsh = hashwithindifferentaccess[@third_party_countries.map { |c| [c.name, c.third_party_shipping] }] this relies on ability freely convert between arrays , hashes. array [[a, b], [c, d]] converts hash { => b, c => d }.
Comments
Post a Comment