[英]Rails 4 - Has_many through - StatementInvalid - SQLite3::SQLException: no such column:
I have been strugling on this issue for 4 days and I am wondering whether I am not facing an ActiveRecord bug? 我在这个问题上苦苦挣扎了4天,我想知道我是否没有遇到ActiveRecord错误? I am trying to link a User model to a Callout model.
我正在尝试将用户模型链接到标注模型。
class User < ActiveRecord::Base
has_many :callouts_users
has_many :callouts, through: :callouts_users
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
has_many :posts, inverse_of: :creator
has_many :callouts, as: :calloutable
has_many :profiles, as: :profileable, :validate => true
validates :name, presence: true
validates_uniqueness_of :name, :case_sensitive => false, :message => "This name has already been taken"
end
class Callout < ActiveRecord::Base
has_many :callouts_users
has_many :users, through: :callouts_users
belongs_to :conversation
belongs_to :calloutable, polymorphic: true, class_name: "::Callout", :validate => true
validates :conversation, presence: true
validates :calloutable, presence: true
validates_uniqueness_of :calloutable_id, :scope => [:user_id, :conversation_id, :calloutable_type]
end
class UserCallout < ActiveRecord::Base
belongs_to :user
belongs_to :callout
validates :type, presence: true,
validates :type, :inclusion=> { :in => ["up", "down"] }
end
My migrations are as follows: 我的迁移如下:
class CreateCalloutsUsers < ActiveRecord::Migration
def change
create_table :callouts_users do |t|
t.timestamps null: false
end
end
end
class AddCalloutToCalloutsUsers < ActiveRecord::Migration
def change
add_reference :callouts_users, :callout, index: true
add_foreign_key :callouts_users, :callouts
end
end
class AddUserToCalloutsUsers < ActiveRecord::Migration
def change
add_reference :callouts_users, :user, index: true
add_foreign_key :callouts_users, :users
end
end
and when I try to do something like 当我尝试做类似的事情
@callout = @conversation.callouts.find_by(calloutable: @user)
if(@callout.nil?) @callout = Callout.new(conversation: @conversation, calloutable: @user)
@callout.users << current_user
@callout.save
I immediately have: ActiveRecord::StatementInvalid in CalloutsController#create SQLite3::SQLException: no such column: callouts.user_id: SELECT 1 AS one FROM "callouts" WHERE ("callouts"."calloutable_id" IS NULL AND "callouts"."user_id" IS NULL AND "callouts"."conversation_id" IS NULL AND "callouts"."calloutable_type" IS NULL) LIMIT 1 我立即拥有:CalloutsController#create SQLite3 :: SQLException中的ActiveRecord :: StatementInvalid:没有这样的列:callouts.user_id:在“ callouts” WHERE(“ callouts”。“ calloutable_id”为NULL和“ callouts”中选择1 AS)。 user_id“是NULL AND”标注“。” conversation_id“是NULL AND”标注“。” calloutable_type“是NULL)LIMIT 1
So as if ActiverRecords where looking for a "user_id" column on my callouts table while the user_id is only on the join table side... I am doing something wrong on my model? 好像ActiverRecords在哪里在我的标注表上查找“ user_id”列,而user_id仅在联接表侧...我在模型上做错了吗? Why is my has_many - trough association not recogognized?
为什么我的has_many-槽关联未被识别?
Here is the SQL code generated: 这是生成的SQL代码:
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."name") = LOWER('name10') AND "users"."id" != 10) LIMIT 1 用户存在(0.2ms)在“用户”中以1作为1(LOWER(“ users”。“ name”)= LOWER('name10')AND“ users ..” id“!= 10)LIMIT 1
Callout Exists (0.6ms) SELECT 1 AS one FROM "callouts" WHERE ("callouts"."calloutable_id" IS NULL AND "callouts"."user_id" IS NULL AND "callouts"."conversation_id" = 1 AND "callouts"."calloutable_type" IS NULL) LIMIT 1 存在标注(0.6ms)从“标注”中选择1为1(“标注”。“ calloutable_id”为NULL和“标注”。“ user_id”为NULL和“标注”。“ conversation_id” = 1和“标注”。 “ calloutable_type”为NULL)LIMIT 1
SQLite3::SQLException: no such column: callouts.user_id: SELECT 1 AS one FROM "callouts" WHERE ("callouts"."calloutable_id" IS NULL AND "callouts"."user_id" IS NULL AND "callouts"."conversation_id" = 1 AND "callouts"."calloutable_type" IS NULL) LIMIT 1 SQLite3 :: SQLException:没有这样的列:callouts.user_id:从“ callouts” WHERE(“ callouts”。“ calloutable_id” IS NULL AND“ callouts”。“ user_id” IS NULL AND“ callouts”。“ conversation_id”作为一个1 = 1 AND“ callouts”。“ calloutable_type” IS NULL)LIMIT 1
(0.0ms) rollback transaction (0.0ms)回滚事务
Completed 500 Internal Server Error in 50ms 在50毫秒内完成500个内部服务器错误
ActiveRecord::Schema.define(version: 20150720002524) do
create_table "callouts", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "conversation_id"
t.integer "calloutable_id"
t.string "calloutable_type"
end
add_index "callouts", ["calloutable_type", "calloutable_id"], name: "index_callouts_on_calloutable_type_and_calloutable_id"
add_index "callouts", ["conversation_id"], name: "index_callouts_on_conversation_id"
create_table "callouts_users", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.integer "callout_id"
end
add_index "callouts_users", ["callout_id"], name: "index_callouts_users_on_callout_id"
add_index "callouts_users", ["user_id"], name: "index_callouts_users_on_user_id"
create_table "conversations", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "posts", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "conversation_id"
t.integer "creator_id"
t.text "title"
t.text "content"
end
add_index "posts", ["conversation_id"], name: "index_posts_on_conversation_id"
add_index "posts", ["creator_id"], name: "index_posts_on_creator_id"
create_table "potential_users", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "profiles", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "profileable_id"
t.string "profileable_type"
t.string "description"
end
add_index "profiles", ["description"], name: "index_profiles_on_description", unique: true
add_index "profiles", ["profileable_type", "profileable_id"], name: "index_profiles_on_profileable_type_and_profileable_id"
create_table "users", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.string "name"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
===================================================> I have been strugling on this issue for 4 days and I am wondering whether I am not facing an ActiveRecord bug? ================================================== =>我在这个问题上苦苦挣扎了4天,我想知道我是否没有遇到ActiveRecord错误? I am trying to link a User model to a Callout model.
我正在尝试将用户模型链接到标注模型。
class User < ActiveRecord::Base
has_many :callouts_users
has_many :callouts, through: :callouts_users
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
has_many :posts, inverse_of: :creator
has_many :callouts, as: :calloutable
has_many :profiles, as: :profileable, :validate => true
validates :name, presence: true
validates_uniqueness_of :name, :case_sensitive => false, :message => "This name has already been taken"
end
class Callout < ActiveRecord::Base
has_many :callouts_users
has_many :users, through: :callouts_users
belongs_to :conversation
belongs_to :calloutable, polymorphic: true, class_name: "::Callout", :validate => true
validates :conversation, presence: true
validates :calloutable, presence: true
validates_uniqueness_of :calloutable_id, :scope => [:user_id, :conversation_id, :calloutable_type]
end
class UserCallout < ActiveRecord::Base
belongs_to :user
belongs_to :callout
validates :type, presence: true,
validates :type, :inclusion=> { :in => ["up", "down"] }
end
My migrations are as follows: 我的迁移如下:
class CreateCalloutsUsers < ActiveRecord::Migration
def change
create_table :callouts_users do |t|
t.timestamps null: false
end
end
end
class AddCalloutToCalloutsUsers < ActiveRecord::Migration
def change
add_reference :callouts_users, :callout, index: true
add_foreign_key :callouts_users, :callouts
end
end
class AddUserToCalloutsUsers < ActiveRecord::Migration
def change
add_reference :callouts_users, :user, index: true
add_foreign_key :callouts_users, :users
end
end
and when I try to do something like 当我尝试做类似的事情
@callout = @conversation.callouts.find_by(calloutable: @user)
if(@callout.nil?) @callout = Callout.new(conversation: @conversation, calloutable: @user)
@callout.users << current_user
@callout.save
I immediately have: ActiveRecord::StatementInvalid in CalloutsController#create SQLite3::SQLException: no such column: callouts.user_id: SELECT 1 AS one FROM "callouts" WHERE ("callouts"."calloutable_id" IS NULL AND "callouts"."user_id" IS NULL AND "callouts"."conversation_id" IS NULL AND "callouts"."calloutable_type" IS NULL) LIMIT 1 我立即拥有:CalloutsController#create SQLite3 :: SQLException中的ActiveRecord :: StatementInvalid:没有这样的列:callouts.user_id:在“ callouts” WHERE(“ callouts”。“ calloutable_id”为NULL和“ callouts”中选择1 AS)。 user_id“是NULL AND”标注“。” conversation_id“是NULL AND”标注“。” calloutable_type“是NULL)LIMIT 1
So as if ActiverRecords where looking for a "user_id" column on my callouts table while the user_id is only on the join table side... I am doing something wrong on my model? 好像ActiverRecords在哪里在我的标注表上查找“ user_id”列,而user_id仅在联接表侧...我在模型上做错了吗? Why is my has_many - trough association not recogognized?
为什么我的has_many-槽关联未被识别?
Here is the SQL code generated: 这是生成的SQL代码:
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."name") = LOWER('name10') AND "users"."id" != 10) LIMIT 1 用户存在(0.2ms)在“用户”中以1作为1(LOWER(“ users”。“ name”)= LOWER('name10')AND“ users ..” id“!= 10)LIMIT 1
Callout Exists (0.6ms) SELECT 1 AS one FROM "callouts" WHERE ("callouts"."calloutable_id" IS NULL AND "callouts"."user_id" IS NULL AND "callouts"."conversation_id" = 1 AND "callouts"."calloutable_type" IS NULL) LIMIT 1 存在标注(0.6ms)从“标注”中选择1为1(“标注”。“ calloutable_id”为NULL和“标注”。“ user_id”为NULL和“标注”。“ conversation_id” = 1和“标注”。 “ calloutable_type”为NULL)LIMIT 1
SQLite3::SQLException: no such column: callouts.user_id: SELECT 1 AS one FROM "callouts" WHERE ("callouts"."calloutable_id" IS NULL AND "callouts"."user_id" IS NULL AND "callouts"."conversation_id" = 1 AND "callouts"."calloutable_type" IS NULL) LIMIT 1 SQLite3 :: SQLException:没有这样的列:callouts.user_id:从“ callouts” WHERE(“ callouts”。“ calloutable_id” IS NULL AND“ callouts”。“ user_id” IS NULL AND“ callouts”。“ conversation_id”作为一个1 = 1 AND“ callouts”。“ calloutable_type” IS NULL)LIMIT 1
(0.0ms) rollback transaction (0.0ms)回滚事务
Completed 500 Internal Server Error in 50ms 在50毫秒内完成500个内部服务器错误
ActiveRecord::Schema.define(version: 20150720002524) do
create_table "callouts", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "conversation_id"
t.integer "calloutable_id"
t.string "calloutable_type"
end
add_index "callouts", ["calloutable_type", "calloutable_id"], name: "index_callouts_on_calloutable_type_and_calloutable_id"
add_index "callouts", ["conversation_id"], name: "index_callouts_on_conversation_id"
create_table "callouts_users", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.integer "callout_id"
end
add_index "callouts_users", ["callout_id"], name: "index_callouts_users_on_callout_id"
add_index "callouts_users", ["user_id"], name: "index_callouts_users_on_user_id"
create_table "conversations", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "posts", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "conversation_id"
t.integer "creator_id"
t.text "title"
t.text "content"
end
add_index "posts", ["conversation_id"], name: "index_posts_on_conversation_id"
add_index "posts", ["creator_id"], name: "index_posts_on_creator_id"
create_table "potential_users", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "profiles", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "profileable_id"
t.string "profileable_type"
t.string "description"
end
add_index "profiles", ["description"], name: "index_profiles_on_description", unique: true
add_index "profiles", ["profileable_type", "profileable_id"], name: "index_profiles_on_profileable_type_and_profileable_id"
create_table "users", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.string "name"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
=============================> EDIT ===========================>编辑
Ok, 好,
I have another clue. 我有另一个线索。 I think that the error lies in the User Model but I don't know how to write it.
我认为该错误出在用户模型中,但我不知道如何编写。
To make short: 简而言之:
1.) Different UserS can participate in differents Callouts. 1.)不同的用户可以参加不同的标注。 So User <=> Callout is a "has_many / through" relation.
因此,用户<=>标注是一个“ has_many /通过”关系。 (not HABTM because I need to customize the Join Model).
(不是HABTM,因为我需要自定义联接模型)。 So I can write
@callout.users
所以我可以写
@callout.users
2.) One Callout targets at one Calloutable (Calloutable are either User or PotentialUser). 2.)一个Callout对象指向一个Calloutable(Calloutable是User或PotentialUser)。 But a Calloutable may be targeted by different Callouts.
但是Calloutable可能由不同的Callout作为目标。 So it is a belong_to / has_many Polymorphic relation.
因此,这是一个longate_to / has_many多态关系。 I can write @user.callouts...and also
@callout.users
... 我可以写@ user.callouts ...也可以写
@callout.users
...
But : @callout.users in situation 1) or 2) don't mean the same thing. 但是:在情况1)或2)中的@ callout.users并不意味着同一件事。
Here are the detailled models: 以下是详细的模型:
class Callout < ActiveRecord::Base
has_many :callouts_users
has_many :users, through: :callouts_users
belongs_to :calloutable, polymorphic: true, class_name: "::Callout", :validate => true
validates :calloutable, presence: true
validates_uniqueness_of :calloutable_id, :scope => [:user_id, :conversation_id, :calloutable_type]
belongs_to :conversation
validates :conversation, presence: true
end
class CalloutsUser < ActiveRecord::Base
belongs_to :user
belongs_to :callout
validates_uniqueness_of :user_id, :scope => [:callout_id]
end
class User < ActiveRecord::Base
has_many :callouts_users
has_many :callouts, through: :callouts_users
has_many :callouts, as: :calloutable
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
has_many :posts, inverse_of: :creator
has_many :profiles, as: :profileable, :validate => true
validates :name, presence: true
validates_uniqueness_of :name, :case_sensitive => false, :message => "This name has already been taken"
end
class PotentialUser < ActiveRecord::Base
has_many :callouts, as: :calloutable
has_one :profile, as: :profileable, :validate => true
validates :profile, presence: true
end
Any idea to rewrite the User Model part ? 有什么想法可以重写用户模型部分吗? (the 2 has_many :callouts) I think I just need to make difference to rails between @user.callouts received by the user and @user.callouts made by the user...
(2 has_many:callouts)我想我只需要改变用户收到的@ user.callouts和用户发出的@ user.callouts之间的关系...
I feel as though you've made this harder than it needs to be. 我觉得好像您已经做到了这比需要做的难。 Don't fight the framework, it's here to help!
不要打架,它可以为您提供帮助!
First, for your join table, use the standard Rails naming convention: order the models alphabetically. 首先,对于您的联接表,使用标准的Rails命名约定:按字母顺序对模型进行排序。 If you roll back a bit, rather than create three migrations for one action, why not:
如果您回滚一点,而不是为一个操作创建三个迁移,为什么不这样做:
rails g migration callouts_users callout_id:integer user_id:integer
That coupled with has_and_belongs_to_many
relations in your models and you should be good to go. 再加上模型中具有
has_and_belongs_to_many
关系,那么您应该一切顺利。
It is fixed !! 它是固定的! the problem was in fact that I had written :
问题实际上是我写的:
has_many :callouts_users
has_many :callouts, through: :callouts_users
has_many :callouts, as: :calloutable
So I was defining has_many :callouts,
twice. 所以我定义了
has_many :callouts,
两次。 And of course, Rails didn't know how to understand @callout.users
当然,Rails不知道如何理解
@callout.users
With : 与:
has_many :callouts_users
has_many :callouts, through: :callouts_users, source: "call", class_name: "Call"
has_many :callins, as: :callable, class_name: "Call"`
I works perfectely ! 我工作完美! Thank you for your patience and comprehension for the neewbie I am... :-)
感谢您的耐心和理解,因为我是新人... :-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.