Naming both associations has_many/belongs_to in rails fails
我确信这是一个简单的问题,但我不知道为什么它不起作用。我有两个模型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class RecipeInstruction < ActiveRecord::Base belongs_to :recipe has_many :images, class_name: 'InstructionImage', autosave: true, inverse_of: :instruction accepts_nested_attributes_for :images end class InstructionImage < ActiveRecord::Base belongs_to :chef belongs_to :instruction, class_name: 'RecipeInstruction', inverse_of: :images, foreign_key: :instruction_id mount_uploader :file, PictureUploader validates :chef_id, presence: true validates :file, presence: true validates :instruction_id, presence: true end |
但是以下代码失败:
1 2 | instruction = RecipeInstruction.new({"id"=>"","text"=>"","position"=>"0","images_attributes"=>{"0"=>{"file"=>'test.png'}}}) expect(instruction).to be_an_instance_of(RecipeInstruction) |
with
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | Failure/Error: instruction = RecipeInstruction.new({"id"=>"","text"=>"","position"=>"0","images_attributes"=>{"0"=>{"file"=>'test.png'}}}) NoMethodError: undefined method `val' for"?":Arel::Nodes::BindParam /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/relation.rb:574:in `block (2 levels) in where_values_hash' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/relation.rb:570:in `fetch' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/relation.rb:570:in `block in where_values_hash' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/relation.rb:563:in `map' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/relation.rb:563:in `where_values_hash' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/relation.rb:581:in `scope_for_create' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/associations/collection_association.rb:483:in `create_scope' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/associations/association.rb:168:in `initialize_attributes' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/associations/association.rb:248:in `block in build_record' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/core.rb:274:in `initialize' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/inheritance.rb:61:in `new' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/inheritance.rb:61:in `new' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/reflection.rb:130:in `build_association' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/associations/association.rb:247:in `build_record' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/associations/collection_association.rb:130:in `build' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/nested_attributes.rb:465:in `block in assign_nested_attributes_for_collection_association' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/nested_attributes.rb:460:in `each' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/nested_attributes.rb:460:in `assign_nested_attributes_for_collection_association' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/nested_attributes.rb:343:in `images_attributes=' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/attribute_assignment.rb:54:in `public_send' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/attribute_assignment.rb:54:in `_assign_attribute' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/attribute_assignment.rb:65:in `block in assign_nested_parameter_attributes' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/attribute_assignment.rb:65:in `each' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/attribute_assignment.rb:65:in `assign_nested_parameter_attributes' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/attribute_assignment.rb:45:in `assign_attributes' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/core.rb:551:in `init_attributes' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/core.rb:272:in `initialize' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/inheritance.rb:61:in `new' /Users/alias/.rvm/src/rvm/gems/ruby-2.1.6/gems/activerecord-4.2.0.beta2/lib/active_record/inheritance.rb:61:in `new' ./spec/recipe_instruction_spec.rb:9:in `block (2 levels) in <top (required)>' |
我找到了未定义foreign_key列但我确实定义了的解决方案。我在
中调试了这个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | def where_values_hash(relation_table_name = table_name) equalities = where_values.grep(Arel::Nodes::Equality).find_all { |node| node.left.relation.name == relation_table_name } binds = Hash[bind_values.find_all(&:first).map { |column, v| [column.name, v] }] Hash[equalities.map { |where| name = where.left.name puts 'debug' puts @klass.inspect puts @table.inspect puts name.inspect puts where.inspect [name, binds.fetch(name.to_s) { case where.right when Array then where.right.map(&:val) else where.right.val end }] }] end |
这是调试:
1 2 3 4 5 6 7 | InstructionImage(id: integer, file: string, chef_id: integer, instruction_id: integer, created_at: datetime, updated_at: datetime) #<Arel::Table:0x007f9ec4a9d688 @name="instruction_images", @engine=InstructionImage(id: integer, file: string, chef_id: integer, instruction_id: integer, created_at: datetime, updated_at: datetime), @columns=nil, @aliases=[], @table_alias=nil, @primary_key=nil> "recipe_instruction_id" #<Arel::Nodes::Equality:0x007f9ec4a155a8 @left=#<struct Arel::Attributes::Attribute relation=#<Arel::Table:0x007f9ec4a15f30 @name="instruction_images", @engine=ActiveRecord::Base, @columns=nil, @aliases=[], @table_alias=nil, @primary_key=nil>, name="recipe_instruction_id">, @right="?"> |
为什么叫
谢谢
您应该在RecipeInstruction类中定义foreign_id。
1 2 3 4 5 | class RecipeInstruction < ActiveRecord::Base belongs_to :recipe has_many :images, class_name: 'InstructionImage', autosave: true, foreign_key:"instruction_id" accepts_nested_attributes_for :images end |