0

A user can create different kinds of posts. I setup a polymorphic relation.

Post

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

Neighborhood post form

= 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"

This actually works. However, I don't like editing params in the create action. When I try to do the following:

@neighborhood_post = current_user.neighborhood_posts.create(params[:neighborhood_post])

...it actually creates two posts. One with a user_id set and where address is nil one where user_id is nil and address is filled with data. How come!

4

1 に答える 1

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

この方法の欠点は、ユーザー入力を信頼するか、投稿に有効な 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] )

さらに別のオプションは、プロセスを逆にすることです: Postwouldaccepts_nested_attributes_for :postableで投稿を作成しますcurrent_user.posts.new( params[:post] )。YMMV

于 2013-06-05T10:53:47.847 に答える