【问题标题】:Rails collection_select with many-to-many not creating entry in join tableRails collection_select 多对多不在连接表中创建条目
【发布时间】:2014-06-16 11:08:32
【问题描述】:

我正在开发一款类似于图书馆预订应用的应用。我一直在构建一个嵌套表单来添加一本新书。我得到了适用于一对多关系的表格(一本书的图像等),但我也想选择并将现有作者与那本书联系起来(一本书有很多作者,一个作者有很多书到 贡献表)和一个 collection_select。

提交表单时,它不会在带有 book_id 和 author_id 的连接表中创建条目。 (在创建新作者时,我设法让它使用简单的 text_entry 字段,但是 collection_select 不起作用。在将 reject_if 添加到接受嵌套属性之前,它不断创建一个新作者,其中包含空白的 first_name 和 last_name 并在加入这个空白的新作者的表)

这是我的表单,只包含重要部分

    <%= form_for @book do |f| %>

    <div class="panel panel-default">
        <div class="panel-body">
            <%= f.label :name, "Book title" %>
            <%= f.text_field :name %>
            <%= f.label :description %>
            <%= f.text_area :description, rows: 5 %>
            <%= f.label :year_of_publication %>
            <%= f.text_field :year_of_publication %>
        </div>
    </div>

    <div class="panel panel-default">
        <div class="panel-body">
            <h3>Add authors</h3>
            <h4>Choose from existing authors</h4>
            <%= f.fields_for :authors do |builder| %>
                <%= builder.collection_select( :id, Author.all, :id, :full_name, prompt: "Select from existing authors") %>
            <% end %>
        </div>
    </div>

    <%= f.submit "Submit", class: "btn btn-info" %>
<% end %>

这是当前为 collection_select 呈现的 HTML

<select id="book_authors_attributes_0_id" name="book[authors_attributes][0][id]"><option value="">Select from existing authors</option>
<option value="1">Berman, Jules J.</option>
<option value="2">Writerton, Andy R.</option>
<option value="3">Goldner, Merle</option>
<option value="4">Auer, Cordell</option>
<option value="5">Metz, Dewitt</option>
<option value="6">Leffler, Briana</option>
<option value="7">Trantow, Audra</option>
<option value="8">Murazik, Ebony</option>
<option value="9">Bahringer, Cale</option>
<option value="10">Schmitt, Wiley</option>
<option value="11">Casper, Zoe</option>

这是我的 Book 模型。

class Book < ActiveRecord::Base
# default_scope -> { order('name ASC') }

validates :year_of_publication, presence: true
validates :description, presence: true
validates :name, presence: true

has_many :stock_items,      dependent: :destroy
has_many :libraries,        through: :stock_items
has_many :contributions,    dependent: :destroy 
has_many :authors,          through: :contributions
has_many :bookings,         through: :stock_items

has_many :book_images, dependent: :destroy
accepts_nested_attributes_for :book_images
accepts_nested_attributes_for :authors, :allow_destroy => true, :reject_if => proc {|attributes| attributes['last_name'].blank? }
accepts_nested_attributes_for :libraries
accepts_nested_attributes_for :stock_items
accepts_nested_attributes_for :contributions

validates :name, presence: true
# validate year of pub length to 4
end

还有我的作者模型。

class Author < ActiveRecord::Base
validates :first_name, presence: true
validates :last_name, presence: true

has_many :contributions, dependent: :destroy
has_many :books, through: :contributions

def full_name
    "#{last_name}, #{first_name}"
end

end

贡献模型(连接表)

class Contribution < ActiveRecord::Base
    belongs_to :author
    belongs_to :book

    validates :author_id, presence: true
    validates :book_id, presence: true
end

架构的相关部分

  create_table "authors", force: true do |t|
    t.string   "last_name"
    t.string   "first_name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "contributions", force: true do |t|
    t.integer  "book_id"
    t.integer  "author_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "books", force: true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "year_of_publication"
    t.string   "description"
  end

我在 BooksController 中的 newcreate 操作

def new
@book = Book.new

# Displays empty fields in the new book action view (n.times)
1.times { @book.authors.build }
1.times { @book.book_images.build }
@book.stock_items.build
end

def create

@book = Book.new(book_params)

if @book.save
  redirect_to @book
  flash[:success] = "Book added"
else
  render 'new'
  flash.now[:danger] = "Book NOT added"
end
end

我的 book_params

私人

def book_params
  # Include the nested parameters in the strong parameters as model_name_attributes !!!!!!!!!!
  params.require(:book).permit( :name, 
                                :description, 
                                :year_of_publication, 
                                authors_attributes: [ :first_name, :last_name ], 
                                book_images_attributes: [ :image_url, :book_id ], 
                                libraries_attributes: [ :name ], 
                                stock_item_attributes: [ :book_id, :library_id ], 
                                contribution_attributes: [ :book_id, :author_id ])
end

【问题讨论】:

  • 这行&lt;%= builder.collection_select( :id, Author.all, :id, :full_name, prompt: "Select from existing authors") %&gt;不应该是&lt;%= builder.collection_select(:author_id, Author.all, :id, :full_name, prompt: "Select from existing authors") %&gt;吗?
  • 感谢您的评论!如果我尝试这个,我会在 Books#new 中得到一个 NoMethodError。 undefined method `merge' for :full_name:Symbol 我不确定这是什么意思(我在上面的 Author 模型中定义了 full_name)。再次感谢!
  • 投完form后能发log info吗?
  • 抱歉,我忘记删除你提议的行中的 :id 了。我又试了一遍你说的,现在我为#<0x007f885b6c9590>
  • &lt;&gt;&lt;&gt;

标签: ruby-on-rails ruby-on-rails-4 nested-forms fields-for


【解决方案1】:

如果我理解正确,您应该使用您的 join_table contributions。将您的 fields_for 部分更改为此将使其工作

<div class="panel panel-default">
        <div class="panel-body">
            <h3>Add authors</h3>
            <h4>Choose from existing authors</h4>
            <%= f.fields_for :contributions do |builder| %>
            <%= builder.collection_select(:author_id, Author.all, :id, :full_name, prompt: "Select from existing authors") %>
            <% end %>
        </div>
    </div>

【讨论】:

  • 没错,我之前尝试过但无法使其正常工作,因为这条线已经存在并且花了我整整 2 天的时间:validates :book_id, presence: true 执行 Pavan 在此答案中建议的操作并删除我的书本模型使它起作用。谢谢!
【解决方案2】:

您能否展示您用于多对多关系的所有三个模型

class Physician < ActiveRecord::Base
attr_accessible :name, :title
  has_many :appointments
  has_many :patients, through: :appointments
end

class Appointment < ActiveRecord::Base
 attr_accessible :details, :patient_id, :physician_id
  belongs_to :physician
  belongs_to :patient
end

class Patient < ActiveRecord::Base
  attr_accessible :name , :details
  has_many :appointments
  has_many :physicians, through: :appointments
end

关系定义本身应该有一些问题,这通常可以直接工作

【讨论】:

  • 谢谢,我已经在代码中添加了 Contributions 模型,看看吧。
猜你喜欢
  • 2015-03-23
  • 1970-01-01
  • 2016-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-03-08
  • 2022-01-20
  • 2014-09-12
相关资源
最近更新 更多