Form_for使用Ransack生成的列表的每个项目

时间:2014-06-29 17:55:10

标签: ruby-on-rails forms ruby-on-rails-4 ransack

用户流程:

  1. 用户POSTS表单,指明他们有哪些项目
  2. 用户可以看到他们在您拥有ItemName(刚刚提交的属性)和描述(之前没有要求的属性)的列中提交的项目列表
  3. 在这个项目列表中,我现在想让用户有机会修改描述,如果他们想要
  4. 额外的事情是视图中呈现的项目列表可由Ransack gem排序。所以问题是,在下面的表单代码片段中, update操作需要调用哪个变量,如果@inventories是Ransack所需的变量,以使列表在操作中可排序'新'吗

    @inventories.each do |inventory|
    form_for inventory do |f|
    f.text_field ...
    

    现在表单和所有内容都正确加载,但提交的说明并没有在任何地方获得PATCH。

    更多背景和完整代码:

    控制器代码:

    def new
      #initializes the parent object needed to create the initial inventory of items
      @signup_parent = Signup.find_by_email(session[:signup_email])
    
      #required by Ransack gem to display results
      @q = @signup_parent.inventories.ransack(params[:q])
      @inventories = @q.result.includes(:signup)
    end
    
    def create
      @signup_parent = Signup.find_by_email(session[:signup_email])
      items_to_be_saved = []
      #at some point array is populated with list of items user selects in form
      @signup_parent.inventories.create items_to_be_saved
    end
    
    def update
      #since the form_fors are generated by an each do that simultaneously creates forms and generates list of existing items, I figured I'd need to follow the same convention as the 'new' action
      @signup_parent = Signup.find_by_email(session[:signup_email])
      @q = @signup_parent.inventories.ransack(params[:q])
      @inventories = @q.result.includes(:signup)
      redirect_to :action => 'new'
    end
    

    查看代码:

    <% if @signup_parent.inventories.count > 0 %>
    
    <div class="table-responsive">
      <table class="table table-condensed table-hover">
        <thead>
          <tr>
            <th><%= sort_link(@q, :item_name, "Item") %></th>
            <th>Description</th>
            <th colspan="5"></th>
          </tr>
        </thead>
    
        <tbody>
          <% @inventories.each do |inventory| %>
            <tr>
              <td><%= inventory.item_name %></td>
              <td>
                <% if inventory.description.blank? %>
                  <%= form_for inventory, url: {action: 'update'}, :html => {:class => "form-inline"} do |f| %> 
                    <div class="form-group col-xs-9">
                      <%= f.text_field :description, class: "form-control", placeholder: "Add description" %>
                    </div>
                    <div class="form-group col-xs-3">
                      <%= f.submit "Update", class: "btn btn-default btn-large btn-block" %>
                    </div>
                  <% end %>
                <% else %>
                  <%= inventory.description %>
                <% end %>
              </td>
              <td>
                <% if inventory.description.present? %>
                  <%= button_to %>
                  <!-- no clue, separate question (but feel free to solve!) need this button to, 1) ideal solution: "reactivate" form with the description so that users can edit what they've put in, 2) hacky solution: delete the description entirely so that users will have to re-enter it in the form that renders once description is blank again -->
                <% end %>
                <%= button_to 'Remove', inventory, method: :delete, class: "btn btn-default btn-large btn-block" %>
              </td>
            </tr>
          <% end %>
        </tbody>
      </table>
    </div>
    
    <% else %>
    
    <!-- if they don't have any items, they see the create form -->
    
    <% end %>
    

    路线

    resources :inventories, only: [:new, :create, :destroy]
    patch 'inventories', to: 'inventories#update'
    

1 个答案:

答案 0 :(得分:0)

如果它对其他人有帮助:

路线代码

resources :inventories, only: [:new, :create, :destroy]
patch 'inventories/:id/edit', to: 'inventories#update', as: 'edit_inventory'
patch 'inventories/:id/destroy_description', to: 'inventories#destroy_description', as: 'destroy_description'  

控制器代码

def update
  @inventory = Inventory.find(params[:id])
  @inventory.update_attributes(inventory_update_params)
  if request.referer.include? 'admin'
    redirect_to :action => 'index'
  else
    redirect_to :action => 'new'
  end
end

def destroy_description
  @inventory = Inventory.find(params[:id])
  @inventory.update_attributes(description: "")
  if request.referer.include? 'admin'
    redirect_to :action => 'index'
  else
    redirect_to :action => 'new'
  end
end

查看代码

<tbody>
  <% @inventories.each do |inventory| %>
    <tr>
      <td><%= inventory.signup.email %></td>
      <td><%= inventory.item_name %></td>
      <td>
        <% if inventory.description.blank? %>
          <%= form_for inventory, url: edit_inventory_path(inventory), method: :patch, :html => {:class => "form-inline", :autocomplete => "off"} do |f| %> 
            <div class="form-group col-xs-10" style="padding:1px;">
              <%= f.text_field :description, class: "form-control", placeholder: "Add a link or description" %>
            </div>
            <div class="form-group col-xs-2" style="padding:1px;">
              <%= f.submit "Add", class: "btn btn-default btn-default btn-block" %>
            </div>
          <% end %>
        <% else %>
          <%= inventory.description %>
        <% end %>
      </td>
      <td>
        <% if inventory.description.present? %>
          <div class="col-xs-6" style="padding:1px; ">
            <%= button_to 'New description', destroy_description_path(inventory), method: :patch, class: "btn btn-default btn-default btn-block" %>
          </div>
        <% end %>
          <div class="col-xs-6" style="padding:1px; ">
            <%= button_to 'Remove item', inventory, method: :delete, class: "btn btn-default btn-default btn-block", data: { confirm: 'Once removed, borrowers will no longer be able to see you have this item. To remove an item temporarily (i.e., for a personal trip), please notify us via email' } %>
          </div>
      </td>
    </tr>
  <% end %>
</tbody>