ruby-on-rails – Rails has_many通过窗体与复选框和连接模型中的额外字段

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – Rails has_many通过窗体与复选框和连接模型中的额外字段前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在努力解决一个很常见的问题(正如我所想)的任务.

有三种型号:

class Product < ActiveRecord::Base  
  validates :name,presence: true

  has_many :categorizations
  has_many :categories,:through => :categorizations

  accepts_nested_attributes_for :categorizations
end

class Categorization < ActiveRecord::Base
  belongs_to :product
  belongs_to :category

  validates :description,presence: true # note the additional field here
end

class Category < ActiveRecord::Base
  validates :name,presence: true
end

我的问题开始于产品新/编辑表单.

创建产品时,我需要检查它所属的类别(通过复选框).我知道可以通过创建名称为“product [category_ids] []”的复选框来完成.但是,我还需要为每个被关联的关联输入一个描述,这些关系将存储在连接模型(Categorization)中.

我看到那些美丽的Railscasts在复杂的形式,habtm复选框等.我一直在搜索StackOverflow几乎没有.但我没有成功.

我发现一个post描述了与我的几乎完全相同的问题.最后一个答案对我来说很有意义(看起来是正确的方式).但是实际上并不能很好地工作(即如果验证失败).我希望类别总是以相同的顺序显示(在新的/编辑表单中,验证之前/之后)和复选框,以保持在验证失败的地方等等.

任何人都赞赏
我是Rails的新手(从CakePHP切换),所以请耐心等待,尽可能详细地写下.请指点正确的方法

谢谢. :)

解决方法

看起来我想出来了!这是我得到的:

我的型号:

class Product < ActiveRecord::Base
  has_many :categorizations,dependent: :destroy
  has_many :categories,through: :categorizations

  accepts_nested_attributes_for :categorizations,allow_destroy: true

  validates :name,presence: true

  def initialized_categorizations # this is the key method
    [].tap do |o|
      Category.all.each do |category|
        if c = categorizations.find { |c| c.category_id == category.id }
          o << c.tap { |c| c.enable ||= true }
        else
          o << Categorization.new(category: category)
        end
      end
    end
  end

end

class Category < ActiveRecord::Base
  has_many :categorizations,dependent: :destroy
  has_many :products,through: :categorizations

  validates :name,presence: true
end

class Categorization < ActiveRecord::Base
  belongs_to :product
  belongs_to :category

  validates :description,presence: true

  attr_accessor :enable # nice little thingy here
end

表格:

<%= form_for(@product) do |f| %>
  ...
  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>

  <%= f.fields_for :categorizations,@product.initialized_categorizations do |builder| %>
    <% category = builder.object.category %>
    <%= builder.hidden_field :category_id %>

    <div class="field">
      <%= builder.label :enable,category.name %>
      <%= builder.check_Box :enable %>
    </div>

    <div class="field">
      <%= builder.label :description %><br />
      <%= builder.text_field :description %>
    </div>
  <% end %>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

控制器:

class ProductsController < ApplicationController

  before_filter :process_categorizations_attrs,only: [:create,:update]

  def process_categorizations_attrs
    params[:product][:categorizations_attributes].values.each do |cat_attr|
      cat_attr[:_destroy] = true if cat_attr[:enable] != '1'
    end
  end

  ...

  # all the rest is a standard scaffolded code

end

从第一眼看,它的工作很好.我希望它不会打破某种方式..

猜你在找的Ruby相关文章