Rails 3-вложенные формы и значения по умолчанию



Я пытаюсь создать форму, которая содержит другую модель в rails. Я сделал это с помощью accepts_nested_attibutes, и это работает отлично. Проблема в том, что у меня есть дополнительное поле в этой таблице, которое записывает имя пользователя для каждого комментария, и я не уверен, как вставить эту информацию, когда создается новый комментарий. Имя пользователя предоставляется контроллером приложения с помощью команды " current_user" метод.

С уважением,
Кайл

Модель Комментария

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

    private
     def set_username
      self.created_by = current_user
     end
    end

Application Controller (это просто песочница, поэтому я просто вставляю строку в метод)

class ApplicationController < ActionController::Base
  protect_from_forgery
  helper_method :current_user

  def current_user
    "FName LName"
  end

end

Показать Вид

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

Почтовый Контроллер

  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
2 4

2 ответа:

Я изначально думал, что вы можете просто установить его в качестве значения по умолчанию или before_save в модели. Но модели не имеют доступа к current_user. Поэтому, вероятно, лучше всего просто установить текущего пользователя в контроллере. Это не так сухо, как положить его в модель, но это менее халтурно и потенциально проблематично таким образом.

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

Просто хочу отметить, что можно получить доступ к current_user в области модели. В данном случае я не думаю, что это необходимо, так как решение от @aNoble должно работать. Поэтому, если есть возможность установить current_user из контроллера, я бы предпочел это.

Короче говоря, мы добавляем метод к классу User
class User < ActiveRecord::Base
  cattr_accessor :current_user

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

И в вашем контроллере приложения мы добавляем before_filter, который задает его. Обязательно вызовите этот фильтр после завершения аутентификации.

class ApplicationController < ActionController::Base

  before_filter { |c| User.current_user = current_user }

end

А затем внутри вашего Comment - модель вы могли бы просто сделать что-то вроде

class Comment

  before_create :set_user

  def set_user
    created_by = User.current_user unless created_by
  end
end

(поэтому я устанавливаю только created_by, если он еще не был установлен, и только при создании нового комментария).