Controller中的ActiveRecord :: AssociationTypeMismatch#在下拉列表中创建Rails自联接

我在Rails 5中自我加入时遇到ActiveRecord :: AssociationTypeMismatch错误,我无法弄清楚如何修复。

这是一个简单的rails应用程序,用户可以分享艺术家(如David Bowie)关于另一位艺术家(如Lou Reed)的引用。 所以,引用可能如下所示:

引用主题:David Bowie内容:“他是一位大师。” 演讲者:Lou Reed

我有一个Quote模型和一个Artist模型,主题和演讲者被定义为Artist模型上的自联接。

以下是模型:

class Artist  { order(name: :asc) } belongs_to :user has_many :spoken_quotes, class_name: "Quote", foreign_key: :speaker_id has_many :topic_quotes, class_name: "Quote", foreign_key: :topic_id validates :user_id, presence: true validates :name, presence: true, length: { maximum: 60 }, uniqueness: { case_sensitive: false } end class Quote  { order(created_at: :desc) } belongs_to :user belongs_to :speaker, class_name: "Artist" belongs_to :topic, class_name: "Artist" validates :speaker, uniqueness: {scope: :topic} validates :topic, uniqueness: {scope: :speaker} validates :user_id, presence: true validates :content, presence: true, length: { maximum: 1200 } validates :source, presence: true, length: { maximum: 60 } end 

这是数据库模式:

 create_table "artists", force: :cascade do |t| t.string "name" t.integer "user_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["user_id", "created_at"], name: "index_artists_on_user_id_and_created_at" t.index ["user_id"], name: "index_artists_on_user_id" end create_table "quotes", force: :cascade do |t| t.integer "user_id" t.integer "artist_id" t.text "content" t.string "source" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["artist_id", "created_at"], name: "index_quotes_on_artist_id_and_created_at" t.index ["artist_id"], name: "index_quotes_on_artist_id" t.index ["user_id", "created_at"], name: "index_quotes_on_user_id_and_created_at" t.index ["user_id"], name: "index_quotes_on_user_id" end 

这是我的报价控制器中的相关代码:

  def create @quote = current_user.quotes.build(quote_params) if @quote.save flash[:success] = "Quote created!" redirect_to root_url else @feed_items = [] render 'static_pages/home' end end def quote_params params.require(:quote).permit(:content, :source, :topic, :artist_id) end 

以及新报价单上的报价主题(这是艺术家)的下拉列表:

  

下拉列表看起来很好,似乎正确地创建了关联,但是当我提交表单时,我收到以下错误:

 Artist(#70317289606580) expected, got "15" which is an instance of String(#70317259521760) 

并且错误消息突出显示了create操作中的第一行:@quote = current_user.quotes.build(quote_params)

我定义我的params错了吗? 我的创建操作导致此错误有什么问题。 在研究了一堆并尝试各种解决方案后,我似乎无法弄明白。

李 –

您的QuoteArtist模型看起来不错。 但是,您的架构是错误的。 它应该看起来像:

 create_table "artists", force: :cascade do |t| t.integer "user_id" t.string "name" t.datetime "created_at", null: false t.datetime "updated_at", null: false end create_table "quotes", force: :cascade do |t| t.integer "user_id" t.integer "speaker_id" t.integer "topic_id" t.text "content" t.string "source" t.datetime "created_at", null: false t.datetime "updated_at", null: false end 

请注意topic_idtopic_id而不是artist_id

我需要看看你的堆栈跟踪,看看你如何设置其他东西可能有什么问题。

顺便说一下,你修复了你的params白名单吗? 这是错的:

 def quote_params params.require(:quote).permit(:content, :source, :topic, :artist_id) end 

因为你的params看起来像:

 Parameters: {"utf8"=>"✓", "authenticity_token"=>"7xXgP3T1ZyxVhnr9TtBxeuYSRLBiuX01JSkQ4m4rN9pBS1W0iW6TJtsS7KyvunpCIZFiFltmdEwZGIYqsnxbyw==", "quote"=>{"topic_id"=>"2", "speaker_id"=>"1", "content"=>"asdfadsf", "source"=>"http://fuzz.com"}, "commit"=>"Post"} 

它应该是:

 def quote_params params.require(:quote).permit(:content, :source, :topic_id, :speaker_id) end 

在黑暗中拍摄,尝试改变:

 validates :speaker, uniqueness: {scope: :topic} validates :topic, uniqueness: {scope: :speaker} 

至:

 validates :speaker_id, uniqueness: {scope: :topic_id} validates :topic_id, uniqueness: {scope: :speaker_id} 

如果这是问题,我会更新解释。

尝试更改您的选择:

 <%= f.collection_select :topic_id, Artist.all, :id, :name %> 

并在您的控制器上允许topic_id

 params.require(:quote).permit(:content, :source, :topic_id, :artist_id) 

您可以将对象作为rails c belongs_to关联的参数传递:

 Quote.new(topic: Artist.first) 

并且Rails会rest,但你不能通过http请求传递一个对象,而是你应该传递一个对象的id。

更新

我很困惑你怎么想引用引号与扬声器(艺术家)和主题(艺术家)只有quotes表上的artist_id列? 您似乎应该有不同的列来存储这些连接。 然后,您将能够使用列的名称来选择名称。