ActiveRecord::AssociationTypeMismatch 在控制器中#create on dropdown select 用于 Rails 自连接
ActiveRecord::AssociationTypeMismatch in Controller#create on dropdown select for a Rails self join
我在加入 Rails 5 时遇到 ActiveRecord::AssociationTypeMismatch 错误,我不知道如何解决。
这是一个简单的 rails 应用程序,用户可以在其中分享一位艺术家(如 David Bowie)关于另一位艺术家(如 Lou Reed)的名言。因此,引用可能如下所示:
引用
主题:大卫·鲍伊
内容:"He was a master."
演讲者:娄·里德
我有一个引用模型和一个艺术家模型,主题和演讲者被定义为艺术家模型上的自连接。
以下是模型:
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
这是数据库架构:
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
以及新报价表上报价主题(艺术家)的下拉菜单:
<%= f.collection_select :topic, Artist.all, :id, :name %>
下拉菜单看起来不错,似乎正在正确创建关联,但是当我提交表单时出现以下错误:
Artist(#70317289606580) expected, got "15" which is an instance of String(#70317259521760)
并且错误消息突出显示了创建操作中的第一行:
@quote = current_user.quotes.build(quote_params)
我是不是定义了错误的参数?我的创建操作有什么问题导致此错误。在研究了一堆并尝试了各种解决方案后,我似乎无法弄清楚。
尝试将您的 select 更改为:
<%= 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会休息,但是你不能通过http请求传递一个对象,而是你应该传递一个对象的id。
已更新
我很困惑你想如何将报价与仅在 quotes
table 上具有 artist_id
列的演讲者(艺术家)和主题(艺术家)绑定?看来您应该有不同的列来存储这些连接。然后您就可以使用列的名称作为 select 的名称。
李-
您的 Quote
和 Artist
模型看起来不错。但是,您的架构是错误的。它应该看起来像:
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
注意 speaker_id
和 topic_id
而不是 artist_id
。
我需要查看您的堆栈跟踪以了解您设置其他内容的方式可能有什么问题。
顺便说一句,你修复了你的参数白名单了吗?这是错误的:
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}
收件人:
validates :speaker_id, uniqueness: {scope: :topic_id}
validates :topic_id, uniqueness: {scope: :speaker_id}
如果这是问题,我会更新解释。
我在加入 Rails 5 时遇到 ActiveRecord::AssociationTypeMismatch 错误,我不知道如何解决。
这是一个简单的 rails 应用程序,用户可以在其中分享一位艺术家(如 David Bowie)关于另一位艺术家(如 Lou Reed)的名言。因此,引用可能如下所示:
引用 主题:大卫·鲍伊 内容:"He was a master." 演讲者:娄·里德
我有一个引用模型和一个艺术家模型,主题和演讲者被定义为艺术家模型上的自连接。
以下是模型:
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
这是数据库架构:
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
以及新报价表上报价主题(艺术家)的下拉菜单:
<%= f.collection_select :topic, Artist.all, :id, :name %>
下拉菜单看起来不错,似乎正在正确创建关联,但是当我提交表单时出现以下错误:
Artist(#70317289606580) expected, got "15" which is an instance of String(#70317259521760)
并且错误消息突出显示了创建操作中的第一行: @quote = current_user.quotes.build(quote_params)
我是不是定义了错误的参数?我的创建操作有什么问题导致此错误。在研究了一堆并尝试了各种解决方案后,我似乎无法弄清楚。
尝试将您的 select 更改为:
<%= 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会休息,但是你不能通过http请求传递一个对象,而是你应该传递一个对象的id。
已更新
我很困惑你想如何将报价与仅在 quotes
table 上具有 artist_id
列的演讲者(艺术家)和主题(艺术家)绑定?看来您应该有不同的列来存储这些连接。然后您就可以使用列的名称作为 select 的名称。
李-
您的 Quote
和 Artist
模型看起来不错。但是,您的架构是错误的。它应该看起来像:
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
注意 speaker_id
和 topic_id
而不是 artist_id
。
我需要查看您的堆栈跟踪以了解您设置其他内容的方式可能有什么问题。
顺便说一句,你修复了你的参数白名单了吗?这是错误的:
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}
收件人:
validates :speaker_id, uniqueness: {scope: :topic_id}
validates :topic_id, uniqueness: {scope: :speaker_id}
如果这是问题,我会更新解释。