Ruby on rails ActiveRecord::Controllercreate on下拉列表中的AssociationTypeMismatch为Rails自联接选择

Ruby on rails ActiveRecord::Controllercreate on下拉列表中的AssociationTypeMismatch为Rails自联接选择,ruby-on-rails,ruby,activerecord,self-join,Ruby On Rails,Ruby,Activerecord,Self Join,我在Rails 5中的自连接中遇到一个ActiveRecord::AssociationTypeMismatch错误,我不知道如何修复 这是一个简单的rails应用程序,用户可以在其中分享David Bowie等艺术家对Lou Reed等其他艺术家的引用。因此,引用可能如下所示: 引述 主题:大卫·鲍伊 内容:他是一位大师。 演讲者:卢·里德 我有一个报价模型和一个艺术家模型,主题和演讲者被定义为艺术家模型上的自连接 以下是模型: class Artist < ApplicationRec

我在Rails 5中的自连接中遇到一个ActiveRecord::AssociationTypeMismatch错误,我不知道如何修复

这是一个简单的rails应用程序,用户可以在其中分享David Bowie等艺术家对Lou Reed等其他艺术家的引用。因此,引用可能如下所示:

引述 主题:大卫·鲍伊 内容:他是一位大师。 演讲者:卢·里德

我有一个报价模型和一个艺术家模型,主题和演讲者被定义为艺术家模型上的自连接

以下是模型:

class Artist < ApplicationRecord
  default_scope -> { 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 < ApplicationRecord
  default_scope -> { 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
以下是我的报价控制器的相关代码:

  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
params.require(:quote).permit(:content, :source, :topic_id, :artist_id)
以及新报价表中艺术家报价主题的下拉列表:

<%= f.collection_select :topic, Artist.all, :id, :name %>
错误消息将突出显示创建操作中的第一行: @quote=当前_user.quotes.buildquote_参数


我给我的爱人下的定义是错的吗?导致此错误的create操作有何错误。在对其进行了大量研究并尝试了各种解决方案之后,我似乎无法找到答案。

尝试使用以下方法更改您的选择:

<%= f.collection_select :topic_id, Artist.all, :id, :name %>
您可以在rails c中将对象作为关联的参数传递:

Rails将执行rest,但您不能通过http请求传递对象,而是应该传递对象的id

更新

我不知道您想如何将Quote与speakerArtist和topicArtist绑定在一起,只在quotes表上有艺术家id列?似乎应该有不同的列来存储这些连接。然后您就可以使用列的名称作为select的名称。

-

你的报价和艺术家模型看起来不错。然而,您的模式是错误的。它应该是这样的:

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
注意演讲者id和主题id,而不是艺术家id

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

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

def quote_params
  params.require(:quote).permit(:content, :source, :topic, :artist_id)
end
因为你的参数看起来像:

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}
致:


如果这是问题所在,我将进行更新解释。

谢谢,实际上在研究问题后首先尝试了此操作,并在浏览器中不断出现此错误未定义的方法主题\u id',您的意思是什么?主题“”-在控制台中,我得到了ActiveModel::MissingAttributeError:无法写入未知属性主题\u id``似乎我做错了什么。Re:更新-它是基于jvillian在这里推荐的内容--我觉得引用可能属于艺术家,而艺术家有很多引用,然后我可以在建立连接的模型,有点像rails指南中给出的示例-。但这很可能就是问题所在&我没有正确理解自连接。我想你弄错了。在这个例子中,有一些员工。但一个员工可以是另一个员工的经理,但无论如何,他们都是员工。要实现它们之间的连接,可以使用自连接。但在你的情况下,你想连接不同的模型,报价和艺术家。你想有两个链接,所以每个链接都应该有一列。好吧,这是有意义的,所以我应该在我的艺术家表上添加列,称为speaker\u id&topic\u id。我现在明白了吗?你必须将speaker\u id和topic\u id添加到quotes表中,这样quote就可以知道是谁说的,关于谁的。然后你就可以在你的报价模型上使用belishto:topic,class\u name:'Artist'和belishto:speaker,class\u name:'Artist'谢谢,我正在解决这个问题,但是现在有一个新的错误。堆栈跟踪-我对gist.updated gist进行了评论。抱歉,我复制了错误消息中的完整跟踪。另外,参数现在是参数。要求:quote.permit:content,:source,:topic_id,:speaker_id,:artist_id,但现在似乎不需要artist_id了?jvillian非常感谢您的帮助。我通过从我的引号迁移中删除foreign_key:true来实现这一点。以前我有t参考:演讲者,外键:真和t参考:主题,外键:真。通过移除外键:是的,它工作得很好。我不必更改验证以获得要提交的表单,但我必须将验证更改为scope::topic_id和scope::speaker_id,以便他们按照预期实际验证表单。在这个过程中,我学到了很多东西,没有你的帮助,我不可能达到目的。我必须将我的f.select:related_model更改为f.select:related_model_id。
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}