Rails:在bootstrap模式中为belongs_to关联创建form_for

时间:2016-09-26 20:55:21

标签: jquery ruby-on-rails twitter-bootstrap model-view-controller associations

在我的rails应用程序中,我在Costs / Cost_Dependencies之间有一个has_many / belongs_to关联

用户可以制作新的费用,然后通过索引操作查看,没什么特别的。但是我尝试添加在创建成本后为成本创建Cost_dependency的功能。我有所有的部分,我只需要在bootstrap模式中执行帮助(为了提高效率)。

在我网站的“索引”视图中,用户会看到所有费用的表格: costs_table

在依赖项列下,我希望用户能够单击+按钮和弹出窗体的模式。

到目前为止,我所拥有的是: 我的路线给了我这个:

cost_cost_dependencies    GET   /costs/:cost_id/cost_dependencies(.:format)          cost_dependencies#index
                          POST   /costs/:cost_id/cost_dependencies(.:format)          cost_dependencies#create
new_cost_cost_dependency  GET    /costs/:cost_id/cost_dependencies/new(.:format)      cost_dependencies#new
edit_cost_cost_dependency GET    /costs/:cost_id/cost_dependencies/:id/edit(.:format) cost_dependencies#edit
cost_cost_dependency      GET    /costs/:cost_id/cost_dependencies/:id(.:format)      cost_dependencies#show
                          PATCH  /costs/:cost_id/cost_dependencies/:id(.:format)      cost_dependencies#update
                          PUT    /costs/:cost_id/cost_dependencies/:id(.:format)      cost_dependencies#update
                          DELETE /costs/:cost_id/cost_dependencies/:id(.:format)      cost_dependencies#destroy

所以我显然有能力通过成本来创造这个东西。 (如果可以,我试图避免为cost_dependencies设置单独的控制器,但如果没有,请告诉我。)

在费用索引视图中,我有以下几个部分:

<div class="btn-group" style="margin:0; height:100%; float: center !important">
    <%= link_to '<i class="glyphicon glyphicon-eye-open"></i>'.html_safe, "/costs/#{cost.id}/cost_dependencies", class: 'btn btn-warning' %>
    <%= link_to '<i class="glyphicon glyphicon-plus"></i>'.html_safe, "/costs/#{cost.id}/cost_dependencies/new", {:remote => true, 'data-toggle' =>  "modal", 'data-target' => '#modal-window',  :class => 'btn btn-success'} %>    
</div>

<div id="modal-window" class="modal fade" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <%= render 'costs/new_cost_dependency' %>   
        </div>
    </div>
</div>

我确实计划实现一个用于查看依赖项的模式,但我认为回答这个问题对我有帮助。

然后是部分中的模态体:

<div class="modal-body">
    <%= form_for @cost_dependency, :html => {:class => "form-group"} do |f| %>
    Blah Blah form stuff looking like <%= f.label ... %> and <%= f.text_field ... %>
   <% end %>
</div>

我坚持的部分是如何通过控制器中的database_association实例化表单中的@cost_dependency变量,因为我一直在接收

First argument in form cannot contain nil or be empty

尝试重新加载页面时出错。

任何帮助实现这一目标都会非常有帮助。 非常感谢你

修改:这是我的成本控制器:

def index
  @costs = Cost.all
  respond_to do |format|
    format.html # index.html.erb
    format.json { render json: @costs }
  end
end

def show
end

def new
  @cost = Cost.new
  @new = true

  respond_to do |format|
    format.html # new.html.erb
    format.json { render json: @cost }
  end
end

def edit
  @edit = true
  @cost = Cost.find(params[:id])
end

def create

  @cost = Cost.new(cost_params)

  if Cost.exists?(:category => @cost.category, :option => @cost.option)
    redirect_to action: 'update', id: Cost.where(:category => @cost.category, :option => @cost.option).first.id
  else
    respond_to do |format|
      if @cost.save
        format.html { redirect_to action: 'index', status: 303, notice: [true, 'Cost was successfully created.'] }
        format.json { render json: @cost, status: :created, location: @cost }
      else
        format.html { render action: "new" }
        format.json { render json: @cost.errors, status: :unprocessable_entity }
      end
    end
  end
end

def update
  @cost = Cost.find(params[:id])

  respond_to do |format|
    if @cost.update_attributes(cost_params)
      format.html { redirect_to action: 'index', status: 303, notice: [true, 'Cost was successfully updated.'] }
      format.json { head :no_content }
    else
      format.html { render action: "edit" }
      format.json { render json: @cost.errors, status: :unprocessable_entity }
    end
  end
end

所以我意识到我的@cost_dependency变量不在这里。如果我把它换成新的,它就不会被调用,因为我们当前正在进行index操作。所以这方面的帮助也会有所帮助。

自从我发布此问题以来,我确实创建了一个具有类似功能的CostDependency控制器。

编辑2:所以我一直在尝试新事物而且我已经进一步了解,但再次陷入困境。

我有一个新的索引页面:

<tbody>
  <% @costs.each do |cost| %>
    <tr>
      <td style="vertical-align:middle !important"><%= cost.category %></td>
        <td style="vertical-align:middle !important"><%= cost.option %></td>
          <td style="vertical-align:middle !important"><%= '$'+cost.per_job.to_s %></td>
          <td style="vertical-align:middle !important"><%= '$'+cost.per_page.to_s %></td>
          <td style="vertical-align:middle !important">
            <div class="btn-group" style="margin:0; height:100%; float: center !important">
              <%if Cost.where(:id => cost.id)[0].cost_dependencies.empty? %>
                <span class="btn btn-danger" data-toggle="popover" data-trigger="hover" data-placement="top" data-html="true" data-content="<h5 style='color: black;'>No Dependencies for this Cost</h5>"><i class="glyphicon glyphicon-eye-close"></i></span>
              <% else %>
                <%= link_to '<i class="glyphicon glyphicon-eye-open"></i>'.html_safe, "", {:remote => true, 'data-toggle' => "modal", 'data-target' => '#modal-window', :class => 'btn btn-warning', :cost => cost.id} %>
              <% end %>
                <%= link_to '<i class="glyphicon glyphicon-plus"></i>'.html_safe, "", {:remote => true, 'data-toggle' => "modal", 'data-target' => '#modal-new-dependency', :cost => cost.id, :class => 'btn btn-success'} %>   
            </div>
          </td>
          <td style="vertical-align:middle !important">
            <div class="btn-group" style="margin:0; height:100%; float: center !important">
              <%= link_to '<i class="glyphicon glyphicon-pencil"></i>'.html_safe, "/costs/#{cost.id}/edit", class: 'btn btn-info'%>
              <%= link_to '<i class="glyphicon glyphicon-trash"></i>'.html_safe, cost, method: :delete, data: { confirm: 'Are you sure?' },  class: 'btn btn-danger' %> 
            </div>      
          </td>
    </tr>
    <div id="modal-window" class="modal fade" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <%= render 'costs/dependency_index', :cost => Cost.where(:id => cost.id)[0] %>   
        </div>
      </div>
    </div>
    <div id="modal-new-dependency" class="modal fade" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <%= render 'costs/new_cost_dependency', :cost => Cost.where(:id => cost.id)[0] %>   
        </div>
      </div>
    </div>
  <% end %>
</tbody>

这不会引发错误,但是当我点击+时,我只收到第一个费用,在这种情况下Size - 8.5" x 11"我的日志就像是在尝试选择所有这些,这有点意义,因为它在.each循环中。

但如果我将其删除,我会undefined variable出现cost.id错误,因为它不在范围之外存在

1 个答案:

答案 0 :(得分:0)

好的,我想出了这头野兽。当我回答时坚持我。

ajax是你最好的朋友。

所以:首先,将link_to(加号)方法的new更改为按钮:

<button class="btn btn-success" data-toggle="modal" data-target="#new-dependency-modal-window" id="newdependency">
    <%= hidden_field_tag "cost_id", cost.id %>
    <span class="glyphicon glyphicon-plus"></span>
</button> 

喜欢这个。请注意,/cost/:id/cost_dependencies/new之后没有任何链接可以在以后发挥作用。

低于最终div(在文件末尾),为模态的存在添加此代码

<div id="new-dependency-modal-window" class="modal fade" role="dialog" aria-labelledby="myNewDependencyModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document" id="new_cost_dependency_modal" style="width: 85%">

    </div>
</div>

接下来,为Cost Dependencies创建一个控制器,并添加常规方法:

class CostDependenciesController < ApplicationController

  def new
    @cost = Cost.find(params[:cost_id])
    @cost_dependency = CostDependency.new
    respond_to do |format|
        format.html # new.html.erb
        format.json { render json: @cost_dependency }
    end
  end

  def edit
    @edit = true
    @cost = Cost.find(params[:cost_id])
    @cost_dependency = @cost.cost_dependencies.find(params[:id])
  end

  def index

  end

  def create
    @cost = Cost.find(params[:cost_id])
    @cost_dependency = @cost.cost_dependencies.new(cost_dependencies_params)
    respond_to do |format|
      if @cost_dependency.save
        format.html { redirect_to controller: 'costs', action: 'index', status: 303, notice: [true, 'Cost Dependency was successfully created.'] }
        format.json { render json: @cost_dependency, status: :created, location: @cost }
      else
        format.html { render action: "new" }
        format.json { render json: @cost_dependency.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    @cost = Cost.find(params[:cost_id])
    @cost_dependency = @cost.cost_dependencies.find(params[:id])

    respond_to do |format|
      if @cost_dependency.update_attributes(cost_dependencies_params)
        format.html { redirect_to controller: 'costs', action: 'index', status: 303, notice: [true, 'Cost was successfully updated.'] }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @cost.errors, status: :unprocessable_entity }
      end
    end
  end

def destroy
  @cost = Cost.find(params[:cost_id])
  @cost_dependency = @cost.cost_dependencies.find(params[:id])
  @cost_dependency.destroy

  respond_to do |format|
    format.html { redirect_to controller: 'costs', action: 'index', status: 303, alert: [true, 'Cost Dependency has been deleted.'] }
    format.json { head :no_content }
  end
end


private
  def cost_dependencies_params
    params.require(:cost_dependency).permit(:cost_id, :dependency_category, :dependency_option, :per_job, :per_page)
  end

end

请注意每个方法中@cost = Cost.find(params[:cost_id])如何为您提供正确的Cost,您可以调用@cost.cost_dependencies.new方法。这就是按钮标记内的hidden_​​field标记的原因,使jQuery可以找到参数。

从这里开始,目标是使用ajax调用从jQuery调用新方法,然后我们将获取内容并将其推送到模态中。

$(document).on "turbolinks:load", ->
    $('button[id="newdependency"]').click ->
        cost_id = $(this).find('#cost_id').val()
        $.ajax({
            url: 'costs/'+cost_id+'/cost_dependencies/new',
            type: 'GET',
            data: {cost_id: cost_id},
            dataType: 'html',
            success: (data) -> 
                dependencyform = $($.parseHTML(data)).find("#new_dependency_modal")
                $('#new_cost_dependency_modal').html(dependencyform)
        })

所以我们执行一旦点击了newdependency id的按钮,我们就会从页面加载中获取html(这将是整个页面,导航栏和所有内容。但我们标记了我们想要的内容(请参阅new_dependency_modal),以便我们find()。我们会将该html设置在我们当前仍在的页面上的模式div内。

注意: this在这里很重要,否则它会抓取它在页面上找到的第一个cost_id,这不会很好,所以我们将范围本地化。

为了清楚起见,这是我的new.html.erb页面被调用。

<div class="modal-content" id="new_dependency_modal">

  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    <h2 style="color: #49afcd" class="center-block westmontTextMuseo3">New Cost Dependency for - <%= @cost.category+" - "+@cost.option %></h2>
  </div>
  <div class=modal-body>
    <%= render 'form' %>
  </div>
</div>

表单只是创建新cost_dependency的表单。