Rails biểu mẫu lồng nhau với has_many: thông qua, làm thế nào để chỉnh sửa các thuộc tính của mô hình tham gia?


103

Làm cách nào để bạn chỉnh sửa các thuộc tính của mô hình kết hợp khi sử dụng accept_nested_attributes_for?

Tôi có 3 mô hình: Chủ đề và Bài viết do Người liên kết tham gia

class Topic < ActiveRecord::Base
  has_many :linkers
  has_many :articles, :through => :linkers, :foreign_key => :article_id
  accepts_nested_attributes_for :articles
end
class Article < ActiveRecord::Base
  has_many :linkers
  has_many :topics, :through => :linkers, :foreign_key => :topic_id
end
class Linker < ActiveRecord::Base
  #this is the join model, has extra attributes like "relevance"
  belongs_to :topic
  belongs_to :article
end

Vì vậy, khi tôi xây dựng bài viết trong hành động "mới" của bộ điều khiển chủ đề ...

@topic.articles.build

... và tạo biểu mẫu lồng nhau trong topic / new.html.erb ...

<% form_for(@topic) do |topic_form| %>
  ...fields...
  <% topic_form.fields_for :articles do |article_form| %>
    ...fields...

... Rails tự động tạo trình liên kết, điều này thật tuyệt. Bây giờ cho câu hỏi của tôi: Mô hình Trình liên kết của tôi cũng có các thuộc tính mà tôi muốn có thể thay đổi thông qua biểu mẫu "chủ đề mới". Nhưng trình liên kết mà Rails tự động tạo có giá trị nil cho tất cả các thuộc tính của nó ngoại trừ topic_id và article_id. Làm cách nào để đặt các trường cho các thuộc tính trình liên kết khác đó vào biểu mẫu "chủ đề mới" để chúng không xuất hiện?


3
Tôi đang cố gắng làm điều tương tự như bạn, chỉ trong một hành động mới / tạo ... Tôi tự hỏi liệu bạn có thể chia sẻ các hành động của bộ điều khiển của mình không. Tôi muốn tạo một Userthông qua Accountbằng cách sử dụng a Relationshipas a linker... nhưng tôi không thể tìm ra hành động mới và tạo có nghĩa là như thế nào ... bạn có phiền không?
Mohamad

Câu trả lời:


90

Tìm ra câu trả lời. Bí quyết là:

@topic.linkers.build.build_article

Điều đó xây dựng các trình liên kết, sau đó xây dựng bài viết cho từng trình liên kết. Vì vậy, trong các mô hình:
topic.rb cần accepts_nested_attributes_for :linkers
linker.rb cầnaccepts_nested_attributes_for :article

Sau đó ở dạng:

<%= form_for(@topic) do |topic_form| %>
  ...fields...
  <%= topic_form.fields_for :linkers do |linker_form| %>
    ...linker fields...
    <%= linker_form.fields_for :article do |article_form| %>
      ...article fields...

13
Hãy cho tôi biết nếu điều này hữu ích
Arcolye

13
Rails 3 update: các form_for và field_for cần <% =%> thay vì <%%> nếu bạn đang sử dụng Rails 3.
Arcolye

Tôi sẽ thêm mã backticks xung quanh hai dòng accept_nested_attributes_for mà bạn đã thêm. Tôi đã bỏ lỡ thông tin đó nhiều lần trong khi chỉ quét mã - khi tôi đọc kỹ, tôi đã nắm bắt được chi tiết bị bỏ sót đó và nó đã giải quyết được vấn đề của tôi. Cảm ơn!
TJ Schuck

2
thành thật mà nói, đây là loại ví dụ đầy đủ mà các hướng dẫn của rubyonrails.org cần.
ahnbizcad

Hình ảnh rõ ràng thực sự đi một chặng đường dài, TJ Schuck.
ahnbizcad

6

Khi biểu mẫu được tạo bởi Rails được gửi đến Rails controller#action, paramssẽ có cấu trúc tương tự như sau (một số thuộc tính được tạo thành được thêm vào):

params = {
  "topic" => {
    "name"                => "Ruby on Rails' Nested Attributes",
    "linkers_attributes"  => {
      "0" => {
        "is_active"           => false,
        "article_attributes"  => {
          "title"       => "Deeply Nested Attributes",
          "description" => "How Ruby on Rails implements nested attributes."
        }
      }
    }
  }
}

Chú ý làm thế nào linkers_attributesthực sự là một số không được lập chỉ mục Hashvới Stringcác khóa, và không phải là một Array? Điều này là do các khóa trường biểu mẫu được gửi đến máy chủ trông giống như sau:

topic[name]
topic[linkers_attributes][0][is_active]
topic[linkers_attributes][0][article_attributes][title]

Việc tạo bản ghi bây giờ đơn giản như sau:

TopicController < ApplicationController
  def create
    @topic = Topic.create!(params[:topic])
  end
end

Tôi không chắc, nhưng tôi nghĩ rằng điều đó đã được giả định cùng vớiaccepts_nested_attributes_for
Arcolye

2
@Arcolye - Tìm kiếm thông tin này trên internet cho một hiệp hội như thế này thật là khó khăn vào thời điểm đó - có lẽ ngày hôm đó google-fu của tôi đã tắt. Ít nhất tôi muốn ghi lại nó ở đây vì tôi với tư cách là đồng nghiệp của mình và tôi chỉ giả sử rằng các đường ray đã chuyển đổi linked_attributes thành một mảng, thay vì một băm được lập chỉ mục bằng 0. Hy vọng rằng mẩu tin này sẽ giúp ích cho ai đó trong tương lai :)
Daniel Doezema,

3

GOTCHA nhanh khi sử dụng has_one trong giải pháp của bạn. Tôi sẽ chỉ sao chép, dán câu trả lời do người dùng KandadaBoggu đưa ra trong chủ đề này .


Các buildchữ ký phương pháp là khác nhau cho has_onehas_manyhiệp hội.

class User < ActiveRecord::Base
  has_one :profile
  has_many :messages
end

Cú pháp xây dựng cho has_manyliên kết:

user.messages.build

Cú pháp xây dựng cho has_oneliên kết:

user.build_profile  # this will work

user.profile.build  # this will throw error

Đọc tài liệuhas_one liên kết để biết thêm chi tiết.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.