在 Rails 中定义两个模型之间的多个(相似)关系
Defining Multiple (similar) relationships between two models in Rails
我一直在 SO 上尝试排列其他(非常)相似的答案,但还没有点击它,我觉得我很接近。
我想以两种不同的方式将用户模型与类别模型相关联,具体取决于用户希望为每个类别使用的通知渠道(文本或电子邮件)。用户可以有多个类别,反之亦然。
期望的结果:
>>@user.textcategories
=> #<ActiveRecord::Associations::CollectionProxy []>
类别。
>> @user.emailcategories
=> #<ActiveRecord::Associations::CollectionProxy []>
个类别。
>> @user.emailcategories << Category.first
>> @user.textcategories << Category.third
等
当前代码:
class User < ActiveRecord::Base
has_many :emailcategories
has_many :categories, through: :emailcategories
has_many :textcategories
has_many :categories, through: :textcategories
end
class Category < ActiveRecord::Base
has_many :emailcategories
has_many :users, through: :emailcategories
has_many :textcategories
has_many :users, through: :textcategories
end
class Emailcategory < ActiveRecord::Base
belongs_to :user
belongs_to :category
end
class Textcategory < ActiveRecord::Base
belongs_to :user
belongs_to :category
end
migration/schema:
create_table "emailcategories" do |t|
t.integer :user_id
t.integer :category_id
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "textcategories" do |t|
t.integer :user_id
t.integer :category_id
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table :users do |t|
t.string :name
end
create_table :categories do |t|
t.string :name
end
当前错误信息:
>> @user.emailcategories << Category.first
ActiveRecord::AssociationTypeMismatch:应为电子邮件类别(#70239513207200),得到类别(#70239513077640)
Github 克隆并尝试:https://github.com/Grantimus9/TestRels
谢谢!
你做错了。你应该做如下:
@user.emailcategories.create! category: Category.first
@user.textcategories.create! category: Category.third
以上答案对于您现有的代码是正确的。但是,如果要使用 <<
语法,则应在连接 table 上使用 STI。 (我也认为这是一个更简洁的解决方案,尽管这可能是个人偏好。)
# db/schema.rb
create_table "categories", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "category_users", force: :cascade do |t|
t.integer "category_id"
t.integer "user_id"
t.string "type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
# app/models/user.rb
class User < ActiveRecord::Base
has_many :email_category_users
has_many :email_categories, through: :email_category_users, source: :category
has_many :text_category_users
has_many :text_categories, through: :text_category_users, source: :category
# If you also need to get all categories on a user
has_many :category_users
has_many :categories, through: :category_users
end
# app/models/category_user.rb
class CategoryUser < ActiveRecord::Base
belongs_to :user
belongs_to :category
end
# app/models/email_category_user.rb
class EmailCategoryUser < CategoryUser
end
# app/models/text_category_user.rb
class TextCategoryUser < CategoryUser
end
# app/models/category.rb
class Category < ActiveRecord::Base
has_many :category_users
has_many :users, through: :category_users
end
此解决方案允许您使用 OP 中概述的所有语法用于 creating/accessing 类别(尽管它是 @user.text_categories
等,请注意下划线)
我一直在 SO 上尝试排列其他(非常)相似的答案,但还没有点击它,我觉得我很接近。
我想以两种不同的方式将用户模型与类别模型相关联,具体取决于用户希望为每个类别使用的通知渠道(文本或电子邮件)。用户可以有多个类别,反之亦然。
期望的结果:
>>@user.textcategories
=> #<ActiveRecord::Associations::CollectionProxy []>
类别。
>> @user.emailcategories
=> #<ActiveRecord::Associations::CollectionProxy []>
个类别。
>> @user.emailcategories << Category.first
>> @user.textcategories << Category.third
等
当前代码:
class User < ActiveRecord::Base
has_many :emailcategories
has_many :categories, through: :emailcategories
has_many :textcategories
has_many :categories, through: :textcategories
end
class Category < ActiveRecord::Base
has_many :emailcategories
has_many :users, through: :emailcategories
has_many :textcategories
has_many :users, through: :textcategories
end
class Emailcategory < ActiveRecord::Base
belongs_to :user
belongs_to :category
end
class Textcategory < ActiveRecord::Base
belongs_to :user
belongs_to :category
end
migration/schema:
create_table "emailcategories" do |t|
t.integer :user_id
t.integer :category_id
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "textcategories" do |t|
t.integer :user_id
t.integer :category_id
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table :users do |t|
t.string :name
end
create_table :categories do |t|
t.string :name
end
当前错误信息:
>> @user.emailcategories << Category.first
ActiveRecord::AssociationTypeMismatch:应为电子邮件类别(#70239513207200),得到类别(#70239513077640)
Github 克隆并尝试:https://github.com/Grantimus9/TestRels
谢谢!
你做错了。你应该做如下:
@user.emailcategories.create! category: Category.first
@user.textcategories.create! category: Category.third
以上答案对于您现有的代码是正确的。但是,如果要使用 <<
语法,则应在连接 table 上使用 STI。 (我也认为这是一个更简洁的解决方案,尽管这可能是个人偏好。)
# db/schema.rb
create_table "categories", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "category_users", force: :cascade do |t|
t.integer "category_id"
t.integer "user_id"
t.string "type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
# app/models/user.rb
class User < ActiveRecord::Base
has_many :email_category_users
has_many :email_categories, through: :email_category_users, source: :category
has_many :text_category_users
has_many :text_categories, through: :text_category_users, source: :category
# If you also need to get all categories on a user
has_many :category_users
has_many :categories, through: :category_users
end
# app/models/category_user.rb
class CategoryUser < ActiveRecord::Base
belongs_to :user
belongs_to :category
end
# app/models/email_category_user.rb
class EmailCategoryUser < CategoryUser
end
# app/models/text_category_user.rb
class TextCategoryUser < CategoryUser
end
# app/models/category.rb
class Category < ActiveRecord::Base
has_many :category_users
has_many :users, through: :category_users
end
此解决方案允许您使用 OP 中概述的所有语法用于 creating/accessing 类别(尽管它是 @user.text_categories
等,请注意下划线)