在Rails中更新连接模型关系

时间:2014-07-21 07:33:23

标签: ruby-on-rails ruby-on-rails-4 has-many-through

基本上我有一个ShopCategory和一个带有附加属性的联接模型ShopCategory

class Shop
  has_many :shop_categories
  has_many :categories, through: :shop_categories

class Category
  has_many :shop_categories
  has_many :shops, through: :shop_categories

class ShopCategory
  belongs_to :shop
  belongs_to :category

我有一个商店表格,我想通过它创建或更新商店。

我的第一个想法是创建一个名为:categories的虚拟属性,让模型处理setter和getter,就像这样(简单的伪代码):

def categories=(cats)

  cats.each do |c|
    check if a ShopCategory exists with this shop (self) and that category.
    if doesn't exist, create one, if exists ignore
    for all the categories in self that weren't touched, delete that ShopCategory
  end

end

但我认为这会导致长期问题,因为3个型号的连接而不是控制器

但是,我似乎无法想到在shops_controller中使用创建和更新方法来处理此方法的简单方法

def update
 @shop = Shop.find params[:id]

 cats = params[:shop].delete :categories
 @shop.update_attributes(shop_params)

 ## should I have a category update method here? How would I handle errors? This gets complicated

end

2 个答案:

答案 0 :(得分:0)

听起来你想要一个嵌套模型表,用于编辑商店及其相关的ShopCategories。

基本上,它需要的是在您的商店的表单上,您可以简单地遍历相关的ShopCategories并打印出它们的字段,以便一起编辑它们。只要参数结构正确,Rails就会自动处理所有内容。

https://github.com/nathanvda/cocoon是使嵌套模型表单更容易的宝石。

还有一个关于Railscasts的教程:

http://railscasts.com/episodes/196-nested-model-form-revised

答案 1 :(得分:-1)

<强>集合

我不知道您对Ruby on Rails的体验,但您可能希望查看与{em>集合相关的some of the documentation

您正在查看的是如何填充集合 - 这实际上相对简单:

#app/controllers/shops_controller.rb
Class ShopsController < ApplicationController
   def create
       @shop = Shop.new(shop_params)
       @shop.save
   end

   private

   def shop_params
      params.require(:shop).permit(:your, :attributes, category_ids: [])
   end
end

这将允许您使用以下表格:

#app/views/shops/new.html.erb
<%= form_for @shop do |f| %>
   <% Category.all.each do |category| %>
      <%= f.check_box :category_ids, category.id %>
   <% end %>
<% end %>

-

<强>模块化

在验证uniqueness的馆藏方面,您最好使用数据库或关联级验证:

class Shop
  has_many :categories, -> { uniq }, through: :shop_categories

这实际上只会为您的商店创建唯一的类别,您可以使用上述方法填充该类别。