简体   繁体   中英

Why am I getting an 'AssociationTypeMismatch' Error?

I have the following code in my Rails 'seeds.rb' file:

acondigitaladdresslineone = Addressline.create!(address_id: acondigitaladdress.id, address: "Sørkedalsveien 273", address_line_position: 0)

The 'Address' model has a one-to-many relation with the 'Addressline' model, and the respective 'belongs_to' and 'has_many' declarations are properly in place. Here is the content of the migration files:

class CreateAddresses < ActiveRecord::Migration[5.0]
  def change
    create_table :addresses do |t|
      t.references :towncity, foreign_key: true
      t.references :stateregion, foreign_key: true, null: true
      t.references :postalcode, foreign_key: true

      t.timestamps
    end
  end
end

class CreateAddresslines < ActiveRecord::Migration[5.0]
  def change
    create_table :addresslines do |t|
      t.references :address, foreign_key: true
      t.string :address
      t.integer :address_line_position

      t.timestamps
    end
  end
end

When I run the Rails Console, I receive the following error, which refers to the "acondigitaladdresslineone = ..." line of code:

ActiveRecord::AssociationTypeMismatch: Address(#8269560) expected, got String(#6922340)

I corrected the error by making the following changes:

# From the 'CreateAddresslines' migration file

    # Original code
    t.string :address

    # Revised code
    t.string :address_name

# From the 'acondigitaladdresslineone' variable declaration line

    # Original code
    address: "Sørkedalsveien 273"

    # Revised code
    address_name: "Sørkedalsveien 273"

I suspect the cause of the error possibly is due the underlying database's (in this case SQLite) inability to disambiguate the same field name based upon datatype. For example, in the original version of the 'CreateAddresslines' migration file, SQLlite raises an error as a result of these two declarations:

t.references :address, foreign_key: true
t.string :address

It is easy to overlook the obvious when entangled in coding. Clearly, a relational database table cannot have two or more columns with the same name. I am unaware of any relational database management system having a capability to disambiguate same-named table columns based upon differences in their datatypes.

I need a sanity check. Is this a reasonable assumption why the 'AssociationTypeMismatch' error was raised?

Thank you.

t.references :address will create the column address_id so there should be no conflict with t.string :address on the DB level.

The problem occurs in ActiveRecord when accessors and associations are declared.

ActiveRecord reads the schema from the database and uses it to create attributes and accessor methods in your models for each column. This happens before any of the code in the class declaration block is evaluated.

When you then create an association you are overwriting the #address and #address= methods created for the string attribute.

class Addressline
  belongs_to :address 
end

Which is why when you do:

Addressline.new(address: 'Foo')

You get a type error since the #address= setter method is setting address_id and expects an Address instance.

The solution is as you might have surmised is to not name other columns the same thing as your associations. Just rename the column:

class FixColumnName < ActiveRecord::Migration
  def self.change
    # call it whatever you want, but not address!
    rename_column :addresslines, :address, :value
  end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM