通过连接模型中的复选框和额外字段,Rails has_many [英] Rails has_many through form with checkboxes and extra field in the join model

查看:112
本文介绍了通过连接模型中的复选框和额外字段,Rails has_many的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



有三种模式:

  class产品< ActiveRecord :: Base 
validates:name,presence:true

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

accept_nested_attributes_for:分类
结束

分类分类< ActiveRecord :: Base
belongs_to:产品
belongs_to:类别

验证:description,presence:true#注意这里的额外字段
结束

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

我的产品新/编辑表单出现问题。



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



我在复杂表单上看到了美丽的Railscast,habtm复选框等我几乎一直在寻找StackOverflow。但我没有成功。



我发现了一个发布它>描述了几乎和我一样的问题。最后的答案对我来说是有意义的(看起来这是正确的路)。但它实际上并不能很好地工作(即,如果验证失败)。我希望类别始终以相同的顺序显示(在新/编辑表单中;在验证之前/之后)以及复选框,以便在验证失败等情况下保持原有状态。



任何thougts赞赏。
我是Rails的新手(从CakePHP切换),请耐心等待,并尽可能详细地写。请以正确的方式指出我的意见!



谢谢。 :)

解决方案

看起来像我明白了!以下是我得到的:

我的模特:

  class产品< ; ActiveRecord :: Base 
has_many:categorizations,dependent :: destroy
has_many:categories,through::categorizations

accept_nested_attributes_for:categorizations,allow_destroy:true

validates:name,presence:true

def initialized_categorizations#这是关键方法
[] .tap do | o |
Category.allEach do | category |
如果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分类< ActiveRecord :: Base
belongs_to:产品
belongs_to:类别

验证:描述,状态:true

attr_accessor:enable#nice little thingy here
end

表格:

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

<%= f.fields_for:categorizations,@ product.initialized_categorizations do | builder | %GT;
<%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如果cat_attr [:enable]!='1'
结束
结束

...

#其余的都是标准的脚手架代码

end

乍一看它工作得很好。我希望它不会打破..:)



谢谢大家。特别感谢Sandip Ransing参与讨论。我希望它对像我这样的人有用。


I'm trying to solve a pretty common (as I thought) task.

There're three models:

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

My problems begin when it comes to Product new/edit form.

When creating a product I need to check categories (via checkboxes) which it belongs to. I know it can be done by creating checkboxes with name like 'product[category_ids][]'. But I also need to enter a description for each of checked relations which will be stored in the join model (Categorization).

I saw those beautiful Railscasts on complex forms, habtm checkboxes, etc. I've been searching StackOverflow hardly. But I haven't succeeded.

I found one post which describes almost exactly the same problem as mine. And the last answer makes some sense to me (looks like it is the right way to go). But it's not actually working well (i.e. if validation fails). I want categories to be displayed always in the same order (in new/edit forms; before/after validation) and checkboxes to stay where they were if validation fails, etc.

Any thougts appreciated. I'm new to Rails (switching from CakePHP) so please be patient and write as detailed as possible. Please point me in the right way!

Thank you. : )

解决方案

Looks like I figured it out! Here's what I got:

My models:

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

The form:

<%= 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 %>

And the controller:

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

From the first glance it works just fine. I hope it won't break somehow.. :)

Thanks all. Special thanks to Sandip Ransing for participating in the discussion. I hope it will be useful for somebody like me.

这篇关于通过连接模型中的复选框和额外字段,Rails has_many的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆