开发者

Rails 3 - Nested Forms and Default Values

I am trying to create form that contains another model in rails. I have accomplished this with using accepts_nested_attibutes and it is working great. The problem is I开发者_StackOverflow中文版 have an additional field in that table that records the User Name for each comment and I am not sure on how to insert that information when a new comment is being created. The username is being supplied by the Application Controller using the "current_user" method.

Regards,

Kyle

Comment Model

    class Comment < ActiveRecord::Base
     belongs_to :post
     before_save :set_username

    private
     def set_username
      self.created_by = current_user
     end
    end

Application Controller (This is just a Sandbox app so I just put a string in the method)

class ApplicationController < ActionController::Base
  protect_from_forgery
  helper_method :current_user

  def current_user
    "FName LName"
  end

end

Show View

<p id="notice"><%= notice %></p>
<p>
  <b>Title:</b>
  <%= @post.title %>
</p>
<div id="show_comments"><%= render 'comments' %></div>
<div id="add_comments">
    Add Comment
    <%= form_for @post, :url => {:action => 'update', :id => @post.id}, :html => { :'data-type' => 'html', :id => 'create_comment_form' } do |f| %>
        <%= f.fields_for :comments, @new_comment do |comment_fields| %>
            <%= comment_fields.text_area :content %>
        <%end%>
      <div class="validation-error"></div>
      <%= f.submit %>
    <% end %>
</div>

Post Controller

  def update
    @post = Post.find(params[:id])
    respond_to do |format|
      if @post.update_attributes(params[:post])
        @comments = @post.comments.all
        format.html { redirect_to({:action => :show, :id => @post.id}, :notice => 'Post was successfully created.') }
        format.xml  { render :xml => @post, :status => :created, :location => @post }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @post.errors, :status => :unprocessable_entity }
      end
    end
  end


I was originally thinking you could just set it as a default or a before_save in the model. But models don't have access to current_user. So it's probably best to just set the current user in the controller. It's not as DRY as putting it in the model but it's less hackey and potentially problematic this way.

def update
  @post = Post.find(params[:id])
  @post.attributes = params[:post]
  @post.comments.each do |comment|
    comment.created_by = current_user if comment.new_record?
  end
  respond_to do |format|
    if @post.save
      @comments = @post.comments.all
      format.html { redirect_to({:action => :show, :id => @post.id}, :notice => 'Post was successfully created.') }
      format.xml  { render :xml => @post, :status => :created, :location => @post }
    else
      format.html { render :action => "new" }
      format.xml  { render :xml => @post.errors, :status => :unprocessable_entity }
    end
  end
end


Just want to point out that it is possible to access current_user in the model scope. In this case I don think it is necessary, as the solution from @aNoble should work. So if is possible to set the current_user from the controller, I would prefer that.

In short, we add a method to the User class

class User < ActiveRecord::Base
  cattr_accessor :current_user

  def self.current_user
    @current_user ||= User.new("dummy-user")
  end
  ...
end

and in your application controllor, we add a before_filter that sets it. Make sure to call this filter after your authentication is done.

class ApplicationController < ActionController::Base

  before_filter { |c| User.current_user = current_user }

end

And, then inside your Comment-model you could just do something like

class Comment

  before_create :set_user

  def set_user
    created_by = User.current_user unless created_by
  end
end

(so I only set the created_by if it was not yet set, and only upon creation of a new comment).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜