2017-08-19 41 views
0

I私のRailsのseeds.rb 'ファイルに次のコードを持っている:「AssociationTypeMismatch」エラーが表示されるのはなぜですか?

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

「アドレス」モデルは「Addressline」モデルと1対多の関係、およびそれぞれの「belongs_toの」を持っていますと 'has_many'宣言が適切に配置されています。ここでは移行ファイルの内容は次のとおりです。

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 

私はRailsのコンソールを実行すると、私はコードの「acondigitaladdresslineone = ...」の行を指し、次のエラー、受信:

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

私は次の変更を行うことで、エラーを訂正:

# 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" 

私は、エラーの原因は、おそらくトンを明確にする基礎となるデータベースの(この場合はSQLiteのでは)できないことによるものである疑いがあります彼はデータ型に基づく同じフィールド名です。たとえば、「CreateAddresslines」移行ファイルの元のバージョンでは、SQLliteは、これら2つの宣言の結果としてエラーが発生します。

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

コーディングにもつれたときに明白なことを見落とすことは容易です。明らかに、リレーショナルデータベーステーブルは、同じ名前を持つ2つ以上の列を持つことはできません。私は、同じ名前のテーブルの列を、データ型の違いに基づいて曖昧さをなくす機能を持つリレーショナルデータベース管理システムを知らない。

サニティチェックが必要です。これは 'AssociationTypeMismatch'エラーが発生した理由を合理的に前提にしていますか?

ありがとうございます。

答えて

1

t.references :addressは、DBレベルでt.string :addressと競合しないように、address_idという列を作成します。

アクセサーとアソシエーションが宣言されているとき、ActiveRecordに問題が発生します。

ActiveRecordはデータベースからスキーマを読み取り、それを使用して各列のモデルで属性とアクセサメソッドを作成します。これは、クラス宣言ブロック内のコードが評価される前に発生します。

アソシエーションを作成すると、文字列属性用に作成された#addressおよび#address=メソッドを上書きします。あなたがなぜときである

class Addressline 
    belongs_to :address 
end 

Addressline.new(address: 'Foo') 

#address= setterメソッドがaddress_idを設定し、Addressインスタンスを期待しているので、あなたは型エラーを取得します。

解決策は、他の列にあなたの関連付けと同じものを指定しないことです。

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

https://github.com/bbatsov/ruby-style-guide#naming – max

+0

> t.references::ちょうど列の名前を変更アドレスは はい、あなたは正しい...列ADDRESS_IDを作成します。 。それは私が見落とした別のポイントです。 >#address = setterメソッドが > address_idに設定されており、Addressインスタンスが必要であるため、タイプエラーが発生します。興味深い。 ありがとう。 –

関連する問題