Ruby on rails Rails中的多个连接表
我是编程和rails新手,有一点我不完全理解。 我正在使用创建一个应用程序Ruby on rails Rails中的多个连接表,ruby-on-rails,forms,model,jointable,Ruby On Rails,Forms,Model,Jointable,我是编程和rails新手,有一点我不完全理解。 我正在使用创建一个应用程序 product has_many categories category has_many products 如果我理解正确,我需要创建一个联接表products\u categories,该表具有product\u id&一个category\u id。首先,我还需要这张桌子的模型吗?如果是,我猜会是这样: class CategoryProduct < ActiveRecord::Base belong
product has_many categories
category has_many products
如果我理解正确,我需要创建一个联接表products\u categories,该表具有product\u id
&一个category\u id
。首先,我还需要这张桌子的模型吗?如果是,我猜会是这样:
class CategoryProduct < ActiveRecord::Base
belongs_to :category
belongs_to :product
end
这是我的产品实例的一个简单表单。我想我现在需要一个类别产品的表格?
如果我希望用户在创建产品时能够向产品添加他想要的任意多个类别,那么我必须如何改变这一点
这是我的category_产品表迁移文件:
类CreateTableCategoriesProducts def change
create_table :categories_products do |t|
t.references :product, index: true
t.references :category, index: true
end
add_foreign_key :categories_products, :categories
add_foreign_key :categories_products, :products
end
end
我使用以下迁移文件重命名了上一个表:
class RenameTableCategoriesProducts < ActiveRecord::Migration
def self.up
rename_table :categories_products, :category_products
end
def self.down
rename_table :category_products, :categories_products
end
end
代码在此中断:
= t.association :categories, as: :check_boxes
因此,我想我的关联仍然不太正确您还必须将CategoryProduct添加到每个模型中:
class Product < ActiveRecord::Base
has_many :category_products
has_many :categories, through: :category_product
在产品的表单中,并将:category_id=>[]
添加到产品控制器中允许的参数列表中
如果您喜欢复选框而不是多选列表,您可以这样做
t.association :categories, as: check_boxes
最后一件事,要以人类可读的格式显示类别,您需要在类别模型中定义一个to_s
方法,即。e、 :
class Category < ActiveRecord::Base
...
def to_s
name
end
end
类别
在Rails中,有两种方法可以处理多对多关系:
你和你属于很多人吗
在没有干预模型的情况下建立多对多关系
class Category < ActiveRecord::Base
has_and_belongs_to_many :products
end
class Product < ActiveRecord::Base
has_and_belongs_to_many :categories
end
顺序似乎无关紧要
你通过以下途径获得了很多好处:
正如您已经猜到的,使用中间模型
class CategoryProduct < ActiveRecord::Base
belongs_to :product
belongs_to :category
end
class Category < ActiveRecord::Base
has_many :category_products
has_many :products, through: :category_products
end
class Product < ActiveRecord::Base
has_many :category_products
has_many :categories, through: :category_products
end
这是由于rails基于表名推断模型类的方式造成的。使用categories\u products
将使rails查找Category::CategoriesProduct
,因为复数词被解释为模块。然而,这实际上只是一种惰性命名约定,通常有一个名词可以更好地描述a和B之间的关系(例如分类)
表单和控制器中的多对多。
正如IvanSelivanov已经提到的,SimpleForm具有用于创建选择、复选框等的帮助器方法
但是,您可能需要使用label\u method选项,而不是覆盖模型中的.to\s
方法
f.assocation :categories, as: :checkboxes, label_method: :name
重写.to_s
会使调试更加困难,在某些情况下会产生令人困惑的测试错误消息
要将控制器中的参数列入白名单,请执行以下操作:
class ProductsController < ApplicationController
def create
@product = Product.new(product_params)
if @product.save
redirect_to @product
else
render :new
end
end
def product_params
params.require(:product)
.permit(:name, :categories_ids, ...)
end
end
class ProductsController
我按照你说的做了,但是当我将t.association:category添加到我的产品/new.html.slim表单时;我得到以下错误:Association:category not foundt.Association:categories
@max现在我得到了nil的未定义方法“klass”:NilClass@IvanSelivanov我也不明白为什么在你的协会里你写的有很多:类别产品
,为什么不:categories\u products
?@Dave这是因为我认为这是CategoryProduct的正确复数形式。您是否将has\u和\u belient\u to \u many
更改为has\u many
?如果您发布相应的代码(错误消息中通常有行号),则更容易判断错误的含义。有关如何修复联接表的表名,请参阅。感谢您的回答,我知道我的产品简单表单中出现错误。当点击行:=t.association:categories,as::复选框时,代码以简单形式中断。可能是因为我在迁移文件中命名表的方式::categories\u products
应该是categories\u products
如果我遵循youNP,是的,我猜这就是问题所在。但是一个很好的技巧是要比“获取错误”更具体一点-如果包含错误消息,帮助会容易得多。nope事件在更改表名后,我仍然会在第16行的简单表单中为nil:NilClass`获取undefined method
klass'=t.association:categories,as::复选框`添加debug@product.categories
会给您带来什么?
class Category < ActiveRecord::Base
...
def to_s
name
end
end
class Category < ActiveRecord::Base
has_and_belongs_to_many :products
end
class Product < ActiveRecord::Base
has_and_belongs_to_many :categories
end
Category + Product = products_categories
class CategoryProduct < ActiveRecord::Base
belongs_to :product
belongs_to :category
end
class Category < ActiveRecord::Base
has_many :category_products
has_many :products, through: :category_products
end
class Product < ActiveRecord::Base
has_many :category_products
has_many :categories, through: :category_products
end
model 1(singular) + model 2(plural)
Product + Category = category_products
f.assocation :categories, as: :checkboxes, label_method: :name
class ProductsController < ApplicationController
def create
@product = Product.new(product_params)
if @product.save
redirect_to @product
else
render :new
end
end
def product_params
params.require(:product)
.permit(:name, :categories_ids, ...)
end
end