【问题标题】:rails nested form for many to many not working as expected多对多的轨道嵌套形式无法按预期工作
【发布时间】:2016-09-01 05:36:46
【问题描述】:

我有 3 个模型,

这些模型之间的关系是多对多的关系。

单位模型

  has_many :unitrentperiods, inverse_of: :unit
  has_many :rentperiods, :through => :unitrentperiods

 accepts_nested_attributes_for :unitrentperiods

单元租期模型

   belongs_to :unit
   belongs_to :rentperiod

租期模型

   has_many :unitrentperiods, inverse_of: :rentperiod
   has_many :units, :through => :unitrentperiods

我有一个单位表格,我可以在其中创建一个新单位或编辑一个单位。 我想让我的单位表格不仅能够管理我的单位,而且还能够管理我的“单位租期”,所以可以说我有 2 个租期,比如

"6 months"
"12 months"

我希望我的单位表格也显示那些带有价格输入的租期,所以当我保存我的单位表格时,我还根据数据库中的租期保存 2 个 unitrentperiod,我认为这是这样做的:

   <style>
  .divCB {
    margin-right: 10px
  }
</style>










<%= form_for(@unit) do |f| %>
  <% if @unit.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@unit.errors.count, "error") %> prohibited this unit from being saved:</h2>

      <ul>
      <% @unit.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>


<% end %>


  <div class="page-header">
      <div class="row">
          <div class="col-md-7">
              <h1 class="h2 page-title">Manage Unit</h1>
              <div class="text-muted page-desc"></div>
          </div>
          <div class="col-md-5 charts">
              <div class="row">

              </div>
          </div>
      </div>
  </div>
  <!-- Breadcrumb -->
  <ol class="breadcrumb">

      <li class="active">Manage Unit</li>
      <!-- Breadcrumb Menu-->

  </ol>

 <div class="container-fluid">
      <div class="animated fadeIn">

          <!--/.row-->
          <div class="row">
              <div class="col-md-6">
                  <div class="card">
                      <div class="card-header">
                          <strong>Unit Form</strong>
                      </div>

                      <%= form_for @unit, html: {class: "form-horizontal"} do |f| %>
                        <div class="card-block">




                                <div class="form-group row">
                                    <%= f.label 'Apartement', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">
                                        <%= collection_select(:unit, :apt_id, @apts, :id, :apt_name, {:prompt => "Please select an Apartement"}, {:id => 'apartements_select', :class => "select", :style => "width:240px"}) %> 


                                    </div>
                                </div>

                                <div class="form-group row">
                                    <%= f.label 'Tower', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">


                                         <%= collection_select(:unit, :tower_id, @towers, :id, :tower_name, {:prompt   => "Select a Tower"}, {:id => 'towers_select', :class => "select", :style => "width:240px"}) %> 
                                    </div>
                                </div>

                                <div class="form-group row">
                                    <%= f.label 'Unit number', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">

                                         <%= f.text_field :unitno, class: "form-control" %>

                                    </div>
                                </div>

                                 <div class="form-group row">
                                    <%= f.label 'Unit size', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">

                                         <%= f.text_field :unitsize, class: "form-control" %>

                                    </div>
                                </div>

                                <div class="form-group row">
                                    <%= f.label 'Unit view', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">

                                          <%= f.select :unitview, options_for_select(@unit_views.collect { |s| [s[0].humanize, s[0]] }, selected: @unit.unitview), {} , class: "form-control" %>

                                    </div>
                                </div>

                                <div class="form-group row">
                                    <%= f.label 'Room Type', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">


                                          <%= collection_select(:unit, :room_type_id, @roomtypes, :id, :room_type_desc, {:prompt => false},  class: "form-control") %> 

                                    </div>
                                </div>

                                <div class="form-group row">
                                    <%= f.label 'Unit floor', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">

                                           <%= f.text_field :unitfloor, class: "form-control" %>
                                    </div>
                                </div>


                                <div class="form-group row">
                                    <%= f.label 'Unit description', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">

                                           <%= f.text_field :unitdesc, class: "form-control" %>
                                    </div>
                                </div>

                                <div class="form-group row">
                                    <%= f.label 'Total bed', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">

                                           <%= f.text_field :totalbedroom, class: "form-control" %>
                                    </div>
                                </div>


                                <div class="form-group row">
                                    <%= f.label 'Furnish', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">

                                          <%= f.select :furnish, options_for_select(@furnish_types.collect { |s| [s[0].humanize, s[0]] }, selected: @unit.furnish), {} , class: "form-control" %>

                                    </div>
                                </div> 


                                <div class="form-group row">
                                    <%= f.label 'For sell', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">

                                          <%= f.select :isforsell, options_for_select( [ ['No', 0], ['Yes', 1] ], selected: @unit.isforsell), {} , class: "form-control" %>
                                    </div>
                                </div> 

                                <div class="form-group row">
                                    <%= f.label 'Sell price', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">

                                           <%= f.text_field :sellprice, class: "form-control" %>
                                    </div>
                                </div>

                                <div class="form-group row">
                                    <%= f.label 'For rent', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">

                                          <%= f.select :isforrent, options_for_select( [ ['No', 0], ['Yes', 1] ], selected: @unit.isforrent), {} , class: "form-control" %>
                                    </div>
                                </div>

                                <div class="form-group row">
                                    <%= f.label 'Rent price', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">
                                         <table>
                                            <% @rentperiods.each do |rentperiod| -%>

                                            <tr>
                                              <td><%= rentperiod.rentmonth %> Month</td> 
                                              <td>
                                                    <%= fields_for(@unitrentperiods) do |elem| %>
                                                         <%= elem.text_field :rentprice, class: 'col-md-4 form-control' %> IDR
                                                         <%= elem.hidden_field :rentperiod_id,  :value => rentperiod.id %>


                                                    <% end %>
                                              </td>
                                            </tr>
                                            <% end -%>

                                          </table>




                                    </div>
                                </div>

                                <div class="form-group row">
                                    <%= f.label 'Unit status', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">

                                         <%= f.select :unitstatus, options_for_select(@unit_statuses.collect { |s| [s[0].humanize, s[0]] }, selected: @unit.unitstatus), {} , class: "form-control" %>

                                    </div>
                                </div>  


                                <div class="form-group row">
                                    <%= f.label 'Photo Template', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">


                                         <%= f.select :template_id, options_for_select(@templates.collect { |s| [s[:type], s[:id]] }, selected: @unit.template_id), {} , class: "form-control" %>

                                    </div>
                                </div>

                                <div class="form-group row">
                                    <%= f.label 'Floor plan', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">

                                        <div id="divFloorplan">


                                        </div>
                                    </div>
                                </div>

                                <div class="form-group row">
                                    <%= f.label 'Unit plan', class: 'col-md-4 form-control-label' %>
                                    <div class="col-md-8">

                                        <div id="divUnitplan">


                                        </div>
                                    </div>
                                </div>






                        </div>
                        <div class="card-footer">
                            <button type="submit" class="btn btn-sm btn-primary"><i class="fa fa-dot-circle-o"></i> Submit</button>      
                        </div>
                      <% end %>
                  </div>

              </div>
              <!--/col-->
          </div>
          <!--/.row-->
      </div>
 </div>


 <script>
     $(document).ready(function() 
     {
          $('.select').select2();

          $('#apartements_select').change(function() {

                 $.ajax({
                          url: "/units/gettowers",
                          data: {
                            apt_id : $('#apartements_select').val()
                          },
                          dataType: "script"
                        });


                  $.ajax({
                          url: "/units/getfloorplans",
                          data: {
                            apt_id : $('#apartements_select').val()
                          },
                          dataType: "script"
                        });

                  $.ajax({
                          url: "/units/getunitplans",
                          data: {
                            apt_id : $('#apartements_select').val()
                          },
                          dataType: "script"
                        });





          });

    });
 </script>

控制器

    class UnitsController < ApplicationController
  before_action :set_unit, only: [:show, :edit, :update, :destroy]

  # GET /units
  # GET /units.json
  def index
    @units = Unit.paginate(page: params[:page])
  end

  # GET /units/1
  # GET /units/1.json
  def show
  end

  def gettowers
    # updates towers based on apartement selection
    tower = Tower.where(:apt_id => params[:apt_id])
    # map to name and id for use in our options_for_select
    @towers = tower.map{|a| [a.tower_name, a.id]}.insert(0, "Select a Tower")
  end

  def getfloorplans
    floorplans = Floorplan.where(:apt_id => params[:apt_id]).select("id, floorplanphoto")
    @imgs = floorplans
  end

  def getunitplans
    unitplans = Unitplan.where(:apt_id => params[:apt_id]).select("id, unitplanphoto")

    @imgs = unitplans
  end

  def preparedata
    #master tables
    @apts = Apt.all
    @towers = Tower.all
    @roomtypes = RoomType.all
    @rentperiods = Rentperiod.all

    array = []
    Template.all.each do |t|
       hash = { :type => t.room_type.room_type_desc, :id => t.id }
       array.push(hash)
    end

    @templates = array

    #enum from model
    @unit_views = Unit.unitviews
    @furnish_types = Unit.furnishes
    @unit_statuses = Unit.unitstatuses
  end

  # GET /units/new
  def new
      @unit = Unit.new
      @unitrentperiods = @unit.unitrentperiods.build

      preparedata



      # @rentperiods.each do |r| 
      #   @unit.unitrentperiods.build
      # end
  end

  # GET /units/1/edit
  def edit
    #@unitrentperiods =  @unit.unitrentperiods
    @unitrentperiods = @unit.unitrentperiods.build
    preparedata
  end

  # POST /units
  # POST /units.json
  def create
    @unit = Unit.new(unit_params)

    respond_to do |format|
      if @unit.save
        format.html { redirect_to @unit, notice: 'Unit was successfully created.' }
        format.json { render :show, status: :created, location: @unit }
      else
        format.html { render :new }
        format.json { render json: @unit.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /units/1
  # PATCH/PUT /units/1.json
  def update
    respond_to do |format|
      if @unit.update(unit_params)
        format.html { redirect_to @unit, notice: 'Unit was successfully updated.' }
        format.json { render :show, status: :ok, location: @unit }
      else
        format.html { render :edit }
        format.json { render json: @unit.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /units/1
  # DELETE /units/1.json
  def destroy
    @unit.destroy
    respond_to do |format|
      format.html { redirect_to units_url, notice: 'Unit was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_unit
      @unit = Unit.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def unit_params
      params.require(:unit).permit(:apt_id, :tower_id, :unitno, :unitsize, :unitview, 
                                   :room_type_id, :unitfloor, 
                                   :unitdesc, :isforsell, :sellprice, :isforrent, :furnish, :totalbedroom, 
                                   :unitstatus, :template_id, :floorplan_id, :unitplan_id,
                                   unitrentperiods_attributes: [:rentprice, :rentperiod_id])
    end
end

不知何故它不起作用。我错过了什么?需要一些指导才能让它发挥作用。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 nested-forms nested-attributes


    【解决方案1】:

    一开始不接受嵌套属性,添加

    accept_nested_attributes_for :unitrentperiods
    

    就在has_many :unitrentperiods下方

    此外,您可能需要配置强参数以允许嵌套的属性参数(或 attr_accessible,如果您使用的是 Rails 3)。

    这里有个问题:你必须允许unitrentperiods_attributes,而不仅仅是unitrentperiods

    【讨论】:

    • 谢谢,我用控制器强参数和接受嵌套属性的模型更新了我的问题,但仍然没有运气。
    • 到目前为止看起来是正确的...update 操作可能有问题?提供一个控制器操作和整个form_for 以获得更好的清晰度
    猜你喜欢
    • 2015-02-20
    • 2018-10-13
    • 1970-01-01
    • 2020-02-04
    • 1970-01-01
    • 1970-01-01
    • 2011-12-13
    • 2020-01-01
    • 1970-01-01
    相关资源
    最近更新 更多