Rails 4 プロジェクトがあり、MTI を使用しています。これはフォーラム アプリであり、トピックから継承するいくつかのモデル (アナウンスメントやプライベート メッセージなど) に加えて、コアのトピック モデルがあります。
すべての仕組みは次のとおりです。
models/topic.rb - これは基本モデルです
class Topic < ActiveRecord::Base
acts_as_taggable
default_scope order('created_at DESC')
#string title
belongs_to :discussable, polymorphic: true, dependent: :destroy
belongs_to :author, class_name: User
has_many :posts, inverse_of: :topic, order: :created_at
has_many :viewings
has_many :viewers, class_name: User, through: :viewings, uniq: true
has_many :watchings
has_many :watchers, class_name: User, through: :watchings, uniq: true
accepts_nested_attributes_for :posts, allow_destroy: true
validates :title, presence: true
validates :author_id, presence: true
def base
self
end
end
models/announcement.rb
# this is a "child" class -- acts_as_topic sets that up, see next snippet
class Announcement < ActiveRecord::Base
acts_as_topic
default_scope includes(:topic).order('topics.created_at DESC')
#datetime :displays_at
validates :expires_at, timeliness: { after: lambda { self.displays_at }, allow_nil: true }
end
config/initializers/discussable.rb
module Discussable
def self.included(base)
base.has_one :topic, as: :discussable, autosave: true
base.validate :topic_must_be_valid
base.alias_method_chain :topic, :autobuild
end
def topic_with_autobuild
topic_without_autobuild || build_topic
end
def method_missing(meth, *args, &blk)
topic.send(meth, *args, &blk)
rescue NoMethodError
super
end
protected
def topic_must_be_valid
unless topic.valid?
topic.errors.each do |attr, message|
errors.add(attr, message)
end
end
end
end
class ActiveRecord::Base
def self.acts_as_topic
include Discussable
end
end
そして移行:
class CreateTopics < ActiveRecord::Migration
def change
create_table :topics do |t|
t.string :title, null: false
t.references :author, null: false
t.references :discussable
t.string :discussable_type
t.integer :posts_count, null: false, default: 0
t.timestamps
end
end
end
class CreateAnnouncements < ActiveRecord::Migration
def change
create_table :announcements do |t|
t.datetime :displays_at
t.datetime :expires_at
end
end
end
ビュー/お知らせ/new.html.erb
<%= form_for @announcement do |f| %>
<%= f.text_field :title, placeholder: 'Title' %><br />
<%= f.fields_for :posts do |post_f| %>
<%= post_f.text_area :content %>
<%= post_f.hidden_field :author_id, value: current_user.id %><br />
<% end %>
<%= f.text_field :tag_list, placeholder: 'Tags' %><br />
<%= f.text_field :displays_at, placeholder: 'Display At' %><br />
<%= f.text_field :expires_at, placeholder: 'Expire At' %><br />
<%= f.hidden_field :author_id %><br />
<%= f.submit %>
<% end %>
アナウンス#作成アクションは簡単です - それは単にパラメータから新しいアナウンスを作成し、それを保存しようとします。
このセットアップにはエラーはなく、すべてが完全に機能しているように見えます。
問題は、 Announces#create がお知らせを作成し、投稿のネストされた属性を完全に無視することです。
acts_as_topic
アナウンスメント モデルとトピック モデルの間に has_one 関係を実際に作成するだけで、Discussable モジュールはアナウンスメント is_a トピックのように見せかけるので、それは理にかなっています。
私の質問は次のとおりです。アナウンス モデルの ActiveRecord イニシャライザの内部が、実際にはトピック モデルとの関連付けである、投稿のネストされた属性を受け入れるようにするにはどうすればよいでしょうか?