rails嵌套表单,多对多不能按预期工作

时间:2016-09-01 05:36:47

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

我有3个型号,

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

单位模型

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

 accepts_nested_attributes_for :unitrentperiods

unitrentperiod模型

   belongs_to :unit
   belongs_to :rentperiod

租期模型

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

我有一个单位表格,我可以在这里创建一个新单位或编辑单位。 我想让我的单位形式不仅能够管理我的单位,而且能够管理我的" unitrentperiod"同样,假设我有2个租期,如

"6 months"
"12 months"

我希望我的单位表格能够显示那些租金期间还有价格输入,所以当我保存单位表格时,我还会根据数据库中的租期来保存2个单位期限,我在我的观点中这样做了:

   <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
不知怎的,它不起作用。我错过了什么?需要一些指导才能使它发挥作用。

1 个答案:

答案 0 :(得分:0)

At first you don't accept nested attributes, add

accept_nested_attributes_for :unitrentperiods

right below has_many :unitrentperiods

Also, you might need to configure strong parameters to allow that nested attributes parameter (or attr_accessible if you are on Rails 3).

Gotcha here: you have to allow unitrentperiods_attributes, not just unitrentperiods.