【问题标题】:collection_select content is not showingcollection_select 内容未显示
【发布时间】:2017-12-17 05:03:00
【问题描述】:

我目前正在尝试通过 collection_select 表单显示内容所标识的组织。

问题是在创建新联系人并选择组织后。组织不显示。

到目前为止,我已尝试在网上搜索答案,但没有任何帮助。我也尝试了所有我能想到的代码问题。

这是我的模型:

class Contact < ApplicationRecord
has_many :contact_orgs
has_many :organizations, through: :contact_orgs
accepts_nested_attributes_for :organizations
end

class Organization < ApplicationRecord
has_many :contact_orgs
has_many :contacts, through: :contact_orgs
end

class ContactOrg < ApplicationRecord
belongs_to :contact
belongs_to :organization
accepts_nested_attributes_for :organization
end

这是我的 schema.rb:

create_table "contact_orgs", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "contact_id"
t.integer "organization_id"
t.index ["contact_id"], name: "index_contact_orgs_on_contact_id"
t.index ["organization_id"], name: "index_contact_orgs_on_organization_id"
end

create_table "contacts", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

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

这是我的 contact_controller.rb:

private
def contact_params
params.require(:contact).permit(:first_name, :last_name, 
organizations_attributes: [:name, :industry])
end

def new
@contact = Contact.new
end

def show
@contact = Contact.find(params[:id])
end

def create
@contact = Contact.new(contact_params)
if @contact.save
redirect_to @contact
else
render 'new'
end
end

这是我的contact/new.html.erb:

<%= form_with scope: :contact, url: contact_path, local: true do |form| %>

<p>
<%= form.label :first_name %><br>
<%= form.text_field :first_name %>
</p>

<p>
<%= form.label :last_name %><br>
<%= form.text_field :last_name %>
</p>

<p>
<%= form.label :organization_id, "Organization:" %><br>
<%= form.collection_select :organization_id, Organization.order(:name), :id, :name, {}, {multiple: true} %>
</p>

<p>
<%= form.submit %>
</p>
<% end %>

这是我的contact/show.html.erb:

<p>
<strong>First name:</strong>
<%= @contact.first_name %>
</p>

<p>
<strong>Last Name:</strong>
<%= @contact.last_name %>
</p>
<hr>

<p>
<strong>Organizations:</strong>
<ul>
<% @contact.organizations.each do |organization| %>
<li><%= organization.name %></li>
<% end %>

</ul>
</p>

当我刷新我的 localhost:3000/contact/2 页面时,我的 Rails Server 显示的内容如下。

这是我的 Rails 控制台中的内容:

2.4.1 :001 > Contact.find(2).organizations
Contact Load (0.2ms)  SELECT  "contacts".* FROM "contacts" WHERE "contacts"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
Organization Load (0.2ms)  SELECT  "organizations".* FROM "organizations" INNER JOIN "contact_orgs" ON "organizations"."id" = "contact_orgs"."organization_id" WHERE "contact_orgs"."contact_id" = ? LIMIT ?  [["contact_id", 2], ["LIMIT", 11]]=> #<ActiveRecord::Associations::CollectionProxy []> 

这是我的 routes.rb 文件:

Rails.application.routes.draw do
get 'welcome/index'

resources :contacts, :organizations

root 'welcome#index'
end

提前谢谢你:)

编辑: 通过 Rails c 命令添加了 Contacts#Show 方法和 Contact.find(2).organization。

添加了 routes.rb

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    由于您使用的是连接表 (ContactOrg),因此您在创建 Contact 时确实是在尝试创建新的 ContactOrg 记录,而不是将其分配给 Organization,这就是您的代码读取方式.

    编辑

    虽然我上面的第一个陈述仍然有一点(一点)优点(您实际上是在创建一个连接记录),但您绝对可以让 rails 帮助您,并且您的原始答案非常接近。这里的代码只在有更新的地方,我试图突出显示变化。

    app/models/contact.rb

    class Contact < ApplicationRecord
      has_many :contact_orgs
      has_many :organizations, through: :contact_orgs
    
      accepts_nested_attributes_for :organizations # you were correct here
    end
    

    app/views/contact/new.html.erb

    <%= form_with model: :contact, local: true do |form| %>
      # use :model here so you can ultimately use this form for both new and edit.
      # The model method will infer the correct path
    
      ... contact fields here as you have them ...
    
      <p>
        <%= form.collection_select :organization_ids, Organization.order(:name), :id, :name, {}, {multiple: true} %>
        # the attribute for organization_id should be plural because you're accepting multiple
      <p>
    
      <p>
        <%= form.submit %>
      </p>
    <% end %>
    

    app/controllers/contacts_controller.rb

    class ContactsController < ApplicationController
    
    
      ... new, show, and create as you have them ...
    
       private # private methods should go after all public methods 
    
       def contact_params
         params.require(:contact).permit(:first_name, :last_name, organization_ids: [])
         # again, the attribute you're passing in is called organization_ids, and you give it an empty array
       end
    end
    

    【讨论】:

    • 我按照您的说明进行了适当的更改,但联系人的组织仍然没有显示在我的显示视图中。我想知道它是否在 views/contact/show.html.erb 文件(在上面)中。
    • 我刚刚注意到表单顶部的网址设置为contacts_index_path。这让我觉得你的表单实际上并没有击中你的创建动作(因为它击中了索引动作)。我用创建操作的路径更新了我的答案(您可以通过rake routes 进行确认,它应该类似于POST contacts#create
    • 好的,我认为您已经开始使用它了,因为一旦我尝试创建一个新联系人,我就会收到一个 ActionController::UrlGenerationError,上面写着 No route matches {:action=&gt;"show", :controller=&gt;"contact"}, missing required keys: [:id]。我不确定这到底在说什么,也不知道如何解决它。
    • 太棒了!回到rake routes,应该有一条类似GET contacts/:id contacts#show的路线。 :id 部分将引用您正在通过的 contact 的 id (@contact)。它会在您点击显示页面时出现,您要么没有传入@contact,要么您的@contact 实际上不是保存的对象,因此id 为零。
    • 您可以在控制台中找到您新创建的联系人吗?另外,我并不是要在我的回答中放弃您的 show 操作,我希望这实际上仍然在您的代码中。
    【解决方案2】:

    您的 contract_controller 没有初始化 show.html.erb 中使用的 @contact,因为没有任何 show 方法可以做到这一点。

    尝试添加contact_controller

    def show
      @contact = Contact.find(param[:id])
    end
    

    PS:当你调用 show 方法时,一定要传递给它一个contact.id

    希望对你有所帮助。

    【讨论】:

    • 哦,不。我有一个显示方法。 @contact 在我的显示视图中工作。不工作的部分是以&lt;% @contact.organizations.each do |organization| %&gt;开头的部分。
    【解决方案3】:

    有两个问题:

    1. 您无法将组织保存到您的合同中。 您可以通过 Contact.find(2).organizations 查看您的 rails c。
    2. 我们从不使用在私有方法中编写 new 和 create。

    您的私有方法不应包含任何凝乳。

    在您的 app/controllers/contacts_controller.rb

    中
    private
    
    def contact_params
      params.require(:contact).permit(
        :first_name, 
        :last_name, 
        organizations_attributes: [
          :name, 
          :industry
        ]
     )
    end
    

    在您的app/views/contact/new.html.erb

    中
    <%= form_with scope: :contact, url: contact_index_path, local: true do |form| %>
    
      <p>
        <%= form.label :first_name %><br>
        <%= form.text_field :first_name %>
      </p>
    
      <p>
        <%= form.label :last_name %><br>
        <%= form.text_field :last_name %>
      </p>
    
      <p>
        <%= form.fields_for :organizations do |o| %>
          <%= o.label :organization %><br>
          <%= o.collection_select(:organization_id, Organization.all,
                              :id, :org_name,
                              {:prompt => 'Please select the organization'}) %>
      </p>
    
      <p>
        <%= form.submit %>
      </p>
    <% end %>
    

    【讨论】:

    • 好的,我试过了,它似乎保存了 organization_id 但它仍然没有显示到我的 views/contact/show.html.erb文件。
    • 你有什么 Contract.find(2).organizations 。
    • 拍得好,所以我再次检查了 Contact(2).organizations,它似乎没有像我曾经想象的那样保存。好的,我更新了我的代码。查看我的控制器部分和控制台部分。
    • 将你的私有方法放在控制器的底部并创建一个新合约,然后转到该合约的显示页面。它会起作用
    • 不,我明白,但组织没有显示
    猜你喜欢
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-14
    • 1970-01-01
    • 2013-06-25
    • 2021-02-03
    • 2017-02-13
    相关资源
    最近更新 更多