Rails中嵌套表单的解决

本文详细介绍了Rails中嵌套表单的实现方法,包括如何配置模型接受嵌套属性、控制器中的参数允许策略以及视图层如何构建嵌套表单。通过具体案例展示了嵌套表单在一对多和一对一关系中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是嵌套表单呢?举个简单的例子吧,比如你有两个表,一个User表,另一个Account表,他们是一对一的关系(也可以一对多等)。现在需要提交一个表单的时候同时提交User,Account对应的字段数据。在Rails中有一种简单的方法解决,分别使用了这些方法

accepts_nested_attributes_for 
attr_accessible
fields_for

下面我们用代码进行说明一下。

class User < ActiveRecord::Base
   has_one :account 

   accepts_nested_attributes_for :account  #注意添加这两行
   attr_accessible  :account_attributes

end
class Account<ActiveRecord::Base
belongs_to :user
class UsersController < ApplicationController
  def new
    @user = User.new
    @user.account.build #不要遗漏
  end

 def create
     @user = User.new(params[:user])
     if @user.save
       ...         
     end
  end
end

users/new.html.erb:

 <% form_for @user do |f| %>
    <%= f.text_field :name %>
    <% f.fields_for :account do |pf| %> #注意这里
      <%= pf.text_field :age %>
    <% end %>
 <% end %>

这是一对一的情况,假设是一对多呢,如User has_many :accounts ; Account belongs_to :user这种情况下只要将对应的account改写成accounts,就ok了

http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

以上是Rails3中,如果在Rails4中使用了Using Strong Parameters ,参考这里

去掉model中的 attr_accessible :account_attributes ,在对应的controller中添加Strong Parameters的方法

http://www.railsexperiments.com/using-strong-parameters-with-nested-forms/


实例1:
coupon.rb中:
accepts_nested_attributes_for :cdkey, allow_destroy: true
作用是添加一对一cdkey表单的嵌套
_form.html.erb中:
div class="ui form">
  <%= form_for [:manage, @coupon], html: {multipart: true} do |f| %>


      <div class="fields">
        <div class="field">
          <%= f.label :coupon_type %>
          <%= f.select :coupon_type, Coupon::CouponType, {include_blank: "select coupon type"}, class: "ui dropdown" %>
        </div>


        <div class="field">
          <%= f.label :total_count, "数量限制" %>
          <%= f.text_field :total_count %>
        </div>
      </div>


      <div class="ui segment">


        <h4 class="ui header">CDKEY</h4>


        <div class="fields">
          <%= f.fields_for :cdkey do |c| %>
              <div class="field">
                <%= c.label :code, "cdkey 设置后可以输入该cdkey兑换优惠券"  %>
                <%= c.text_field :code %>
              </div>


              <div class="field">
                <%= c.label :count, "该cdkey可以兑换的次数"  %>
                <%= c.text_field :count %>
              </div>


              <div class="field">
                <%= c.label :start_at  %>
                <%= c.text_field :start_at, class: "datepicker" %>
              </div>


              <div class="field">
                <%= c.label :end_at  %>
                <%= c.text_field :end_at, class: "datepicker" %>
              </div>


              <div class="field">
                <label for="">Delete</label>
                <div class="ui checkbox">
                  <%= c.check_box :_destroy, style: "display: hidden" %>
                  <%= label_tag "删除"  %>
                </div>
              </div>
          <% end %>
        </div>


      </div>




      <div class="field">
        <%= f.label :name %>
        <%= f.text_field :name %>
      </div>


      <div class="field">
        <%= f.label :description %>
        <%= f.text_area :description, rows: 2 %>
      </div>


      <div class="fields">
        <div class="field">
          <%= f.label :start_time %>
          <%= f.text_field :start_time, class: "datepicker" %>
        </div>
        <div class="field">
          <%= f.label :end_time %>
          <%= f.text_field :end_time, class: "datepicker" %>
        </div>
      </div>


      <div class="fields">
        <div class="field">
          <%= f.label :active_days %>
          <%= f.text_field :active_days %>
        </div>
        <div class="field">
          <%= f.label :expiration_time %>
          <%= f.text_field :expiration_time, class: "datepicker" %>
        </div>
      </div>


      <div class="fields">
        <div class="field">
          <%= f.label :value %>
          <%= f.text_field :value %>
        </div>
        <div class="field">
          <%= f.label :status %>
          <%= f.select :status, Coupon::STATUS, {}, class: "ui dropdown" %>
        </div>
      </div>


      <div class="fields">
        <div class="field">
          <%= f.label :no_prefix %>
          <%= f.text_field :no_prefix %>
        </div>
      </div>


      <div class="ui segment">


        <h4 class="ui header">Can use countries</h4>


        <div class="ui grid">


          <div class="ui wide column">
            <div class="ui checkbox">
              <%= check_box_tag "coupon[countries_limit][]", "all", @coupon.countries_limit.to_a.include?("all"), style: "display: hidden" %>
              <%= label_tag "all" %>
            </div>
          </div>


          <% SupportCountry.all.each do |sc| %>
            <div class="ui wide column">
              <div class="ui checkbox">
                <%= check_box_tag "coupon[countries_limit][]", sc.iso_code, @coupon.countries_limit.to_a.include?(sc.iso_code), style: "display: hidden" %>
                <%= label_tag sc.iso_code  %>
              </div>
            </div>
          <% end %>
        </div>


      </div>


      <div class="field">
        <button class="ui submit blue button" type="submit" name="action">
          Submit
        </button>
      </div>


  <% end %>
</div>

注意:          <%= f.fields_for :cdkey do |c| %>
              <div class="field">
                <%= c.label :code, "cdkey 设置后可以输入该cdkey兑换优惠券"  %>
                <%= c.text_field :code %>
              </div>


              <div class="field">
                <%= c.label :count, "该cdkey可以兑换的次数"  %>
                <%= c.text_field :count %>
              </div>


              <div class="field">
                <%= c.label :start_at  %>
                <%= c.text_field :start_at, class: "datepicker" %>
              </div>


              <div class="field">
                <%= c.label :end_at  %>
                <%= c.text_field :end_at, class: "datepicker" %>
              </div>


              <div class="field">
                <label for="">Delete</label>
                <div class="ui checkbox">
                  <%= c.check_box :_destroy, style: "display: hidden" %>
                  <%= label_tag "删除"  %>
                </div>
              </div>
          <% end %>
这一段为对嵌套表单的提交
coupon_controller.rb中:
  def edit
    @coupon = Coupon.find(params[:id])
    if @coupon.cdkey.present?
      @cdkey  =@coupon.cdkey
    else
      @cdkey = @coupon.build_cdkey
    end
  end

  def update
    @coupon = Coupon.find(params[:id])
    if @coupon.update(coupon_params)
      redirect_to manage_coupons_path
    end
  end

  private
  def coupon_params
    params.require(:coupon).permit(
      :name, :coupon_type, :value, :description, :start_time, :end_time,
      :active_days, :expiration_time, :status, :no_prefix, :total_count, cdkey_attributes: [:id, :code, :start_at, :end_at, :count, :_destroy],
      countries_limit: []
    )
  end

注意:edit中的 @cdkey = @coupon.build_cdkey这句和coupon_params健壮参数中 cdkey_attributes: [:id, :code, :start_at, :end_at, :count, :_destroy],这句
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值