Rails 5 has_and_belongs_to_many 表格

Rails 5 has_and_belongs_to_many form

我有一个带有客户端和站点模型的小应用程序。我想在显示页面的模态中创建一个新站点,但出现错误。

请在下面找到架构、控制器、模型和错误。

架构

create_table "clients", force: :cascade do |t|
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "clients_sites", id: false, force: :cascade do |t|
    t.bigint "client_id", null: false
    t.bigint "site_id", null: false
  end

create_table "sites", force: :cascade do |t|
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

我想从我的客户端创建一个站点#show page

<div class="page-header">
  <%= link_to clients_path, class: 'btn btn-default' do %>
    <span class="glyphicon glyphicon-list-alt"></span>
    All Clients
  <% end %>
  <%= link_to edit_client_path(@client), class: 'btn btn-primary' do %>
    <span class="glyphicon glyphicon-pencil"></span>
    Edit
  <% end %>
  <h1>Show client</h1>
</div>

<dl class="dl-horizontal">
  <dt>Name:</dt>
  <dd><%= @client.name %></dd>

</dl>


<div class="row">
  <div class="col-sm-6">
    <h1>Sites</h1>
  </div>

  <div class="col-sm-6 text-right">
    <!-- Button trigger modal -->
    <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
      Add New Site
    </button>

    <!-- Modal -->
    <div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
              <span aria-hidden="true">&times;</span>
            </button>
          </div>
          <div class="modal-body">
            <%= form_for [@client, @site] do |f| %>
              <%= form.label :name %>
              <%= form.text_field :name, class: 'form-control' %>
              <%= form.submit class: 'btn btn-primary' %>
            <% end %>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
            <button type="button" class="btn btn-primary">Save changes</button>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

<div class="table-responsive">
  <table class="table table-striped table-bordered table-hover">
    <thead>
    <tr>

      <th>Name</th>



    </tr>
    </thead>

    <tbody>
    <% @client.sites.each do |site| %>
      <%= content_tag :tr, id: dom_id(site), class: dom_class(site) do %>

        <td><%= link_to site.name, site %></td>




      <% end %>
    <% end %>
    </tbody>
  </table>
</div>

客户端控制器

  def show
    @client = Client.find(params[:id])
    @site = Site.new
  end

app/models/client.rb

class Client < ApplicationRecord
  has_and_belongs_to_many :sites
end

app/models/site.rb

class Site < ApplicationRecord
  has_and_belongs_to_many :clients
end

当我点击页面时出现以下错误

ActionView::Template::Error (undefined method `client_sites_path' for #<#<Class:0x00007f9329282490>:0x00007f9329279890>
Did you mean?  clients_path
               edit_site_path):
    39:             </button>
    40:           </div>
    41:           <div class="modal-body">
    42:             <%= form_for [@client, @site] do |f| %>
    43:               <%= form.label :name %>
    44:               <%= form.text_field :name, class: 'form-control' %>
    45:               <%= form.submit class: 'btn btn-primary' %>

app/views/clients/show.html.erb:42:in `_app_views_clients_show_html_erb___1421137287308647677_70135013712680'

编辑

路线

 sites GET    /sites(.:format)                                                                         sites#index
                           POST   /sites(.:format)                                                                         sites#create
                  new_site GET    /sites/new(.:format)                                                                     sites#new
                 edit_site GET    /sites/:id/edit(.:format)                                                                sites#edit
                      site GET    /sites/:id(.:format)                                                                     sites#show
                           PATCH  /sites/:id(.:format)                                                                     sites#update
                           PUT    /sites/:id(.:format)                                                                     sites#update
                           DELETE /sites/:id(.:format)                                                                     sites#destroy
                   clients GET    /clients(.:format)                                                                       clients#index
                           POST   /clients(.:format)                                                                       clients#create
                new_client GET    /clients/new(.:format)                                                                   clients#new
               edit_client GET    /clients/:id/edit(.:format)                                                              clients#edit
                    client GET    /clients/:id(.:format)                                                                   clients#show
                           PATCH  /clients/:id(.:format)                                                                   clients#update
                           PUT    /clients/:id(.:format)                                                                   clients#update
                           DELETE /clients/:id(.:format)                                                                   clients#destroy

Rails.application.routes.draw do
  resources :sites
  resources :clients

当您将模型数组作为 form_for 助手的参数传递时,rails 会尝试为该关系 (client_sites_path) 寻找路径。

您需要定义该路线。检查 rails 路由指南、嵌套资源部分和使用 url_for 助手的路径 https://guides.rubyonrails.org/routing.html#creating-paths-and-urls-from-objects

将站点资源嵌套在客户端资源中:

resources :clients do
  resources :sites
end

并检查你的新路由,现在你应该在 rake routes 的输出上看到一条 client_sites 路由,并且 [@client, @site] 应该可以工作。

ActionView::Template::Error (undefined method `client_sites_path' for Class:0x00007f9329282490>:0x00007f9329279890 Did you mean? clients_path edit_site_path):

错误表明没有名为 client_sites_path 的可用路径助手。确实如此,因为您没有以这种方式定义路线。根据您对 @arieljuod post 的评论,我了解到您想将 sites 保存到 clients。下面的代码将帮助你实现你想要的

<%= form_for @site do |f| %>
  <%= form.label :name %>
  <%= form.text_field :name, class: 'form-control' %>
  <%= form.select :client_ids, options_from_collection_for_select(Client.all, :id, :name), :prompt => "Select Clients", :multiple => true %>
  <%= form.submit class: 'btn btn-primary' %>
<% end %>

这段代码片段

<%= form.select :client_ids, options_from_collection_for_select(Client.all, :id, :name), :prompt => "Select Clients", :multiple => true %>

创建一个 下拉菜单,您可以在其中 select 一个或多个客户 添加到将一起提交的站点使用 params 进入 sites#create 操作。

此外,您还应该通过将其添加到 site_params 方法来确保 白名单 client_ids: []。通过这样做,Rails 在幕后使用这个 client_ids 值来为 clients_sites table 生成条目。从而完成sitesclients的创建。