用户可以创建不同类型的帖子。我建立了一个多态关系。
发布
class Post < ActiveRecord::Base
attr_accessible :user_id, :address
belongs_to :postable, polymorphic: true, dependent: :destroy
belongs_to :user
validates_presence_of :user_id, :postable_id, :postable_type
end
NeighborhoodPost
class NeighborhoodPost < ActiveRecord::Base
has_one :user, through: :post
has_one :post, as: :postable, autosave: true, validate: false
attr_accessible :content, :title, :post_attributes
accepts_nested_attributes_for :post
end
NeighborhoodPostsController
def create
params[:neighborhood_post][:post_attributes][:user_id] = current_user.id
@neighborhood_post = NeighborhoodPost.new(params[:neighborhood_post])
if @neighborhood_post.save
redirect_to root_url, notice: 'NeighborhoodPost was successfully created.'
else
render action: "new"
end
end
邻里发布表格
= f.fields_for :post do |post_builder|
.control-group
= post_builder.label :address, 'Adres', class: 'control-label'
.controls
= post_builder.text_field :address, placeholder: "Adres voor locatie"
这实际上有效。但是,我不喜欢在create动作中编辑params。当我尝试执行以下操作时:
@neighborhood_post = current_user.neighborhood_posts.create(params[:neighborhood_post])
...它实际上创建了两个帖子。一个设置了user_id,其中地址为零,其中user_id为nil,地址填充数据。怎么来的!
答案 0 :(得分:1)
当您构建post
时,我假设您执行以下操作:
@neighborhood_post = NeighborhoodPost.new
@neighborhood_post.build_post
你只需要更进一步:
@neighborhood_post.build_post( user_id: current_user.id )
然后以你的形式:
= f.fields_for :post do |post_builder|
= post_builder.hidden_field :user_id
此方法的缺点是您必须 -ahem - 信任用户输入,或以某种方式验证帖子是否具有有效的user_id(== current_user.id)。因此,如果您不想信任用户输入,我想另一种方法是执行以下操作:
class NeigborhoodPost < ActiveRecord::Base
def self.new_from_user( user, params = {}, options = {}, &block )
new( params, options, &block ).tap do |new_post|
new_post.post.user_id = user.id if new_post.post.present?
end
end
end
然后在create
行动中
@neighborhood_post = NeighborhoodPost.new_from_user( user, params[:neighboorhood_post] )
另一种选择是反转流程:Post
将accepts_nested_attributes_for :postable
,您将使用current_user.posts.new( params[:post] )
创建帖子。 YMMV