Rails 3.2:尝试通过嵌套表单传递User字段

时间:2012-06-08 13:55:50

标签: ruby-on-rails ruby nested-forms

所以基于Ryan Bates轨道演员(http://railscasts.com/episodes/196-nested-model-form-revised)我正在创建一个嵌套表单。我试图开始工作的rails应用程序的一部分理想情况如下:

  • 让当前用户提出问题
  • 然后提供该问题的答案

我设法让一切正常,但是当我在填写完所有内容后尝试提交表单时,我不断收到以下错误:

undefined method `meter_id' for nil:NilClass

app/models/answer.rb:13:in `associate_with_meter_id'
app/controllers/questions_controller.rb:13:in `create'

我相信我知道什么是错的,但我不知道如何解决它。 meter_id返回一个未定义的值,因为它没有传递正确的值。以下是将meter_id(答案)与meter_id(用户)相关联的方法:

def associate_with_meter_id
    self.meter_id = user.meter_id
end

以下是我的用户模型的一部分

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me,
                  :home_size_sf, :meter_id, :avg_monthly_kwh, :discovery_score,
                  :questions_attributes, :answers_attributes


  has_many :data_records, :foreign_key => :meter_id, :primary_key => :meter_id, :class_name => "DataRecord"

  has_many :questions
  has_many :answers

  accepts_nested_attributes_for :questions, :answers

以下是问题模型

class Question < ActiveRecord::Base
    attr_accessible :description, :taxonomy, :user_id, :answers_attributes
  belongs_to :user
  has_many :answers
  accepts_nested_attributes_for :answers
  validates :description, presence: { :on => :create }
  validates :taxonomy, presence: { :on => :create }
  def relevance_score
    rand
  end
end

以下是问题控制器

class QuestionsController < ApplicationController
  respond_to :html, :json

  def index
    @question = current_user.questions.new
    @questions = current_user.questions.all
  end

  def create
    @question = current_user.questions.new(params[:question])
    if !params[:update_button]
      if @question.valid?
        if params[:next_button] || !@question.save
          render 'index'
        elsif !params[:next_button] && params[:submit_button] && @question.save
          flash[:success] = "Your question and answer have been saved."
          respond_with @question, :location => questions_path
        end
      else
        render 'index'
      end
    else
      render 'index'
    end
  end

  def next
    @question = current_user.unanswered.first
    @answer = Answer.new(:question => @question, :user => current_user)
    respond_to do |format|
      format.js
    end
  end
end

回答模型

class Answer < ActiveRecord::Base
  attr_accessible :value, :user_id, :meter_id, :question_id
  belongs_to :user
  belongs_to :question

  validates :value, presence: true, :numericality => true

  before_save :associate_with_meter_id



  def associate_with_meter_id
    self.meter_id = user.meter_id **(<-- line 13 from the error message)**
  end

end

回答控制器

class AnswersController < ApplicationController
  respond_to :html, :json

  def index
    @answers = current_user.answers
  end

  def create
    @answer = current_user.answers.create(params[:answer])
    if @answer.save
      flash[:notice] = "Thanks for for answer. Please continue with your input...."
      respond_with @answer, :location => root_url
    end
  end

end

数据库架构

ActiveRecord::Schema.define(:version => 20120210184340) do

  create_table "answers", :force => true do |t|
    t.integer  "meter_id"
    t.integer  "user_id"
    t.integer  "question_id"
    t.float    "value"
    t.float    "what_if_value"
    t.datetime "created_at",    :null => false
    t.datetime "updated_at",    :null => false
  end

  create_table "data_records", :force => true do |t|
    t.datetime "timestamp"
    t.float    "value"
    t.integer  "meter_id"
    t.string   "status_code"
  end

  create_table "questions", :force => true do |t|
    t.string   "description"
    t.string   "taxonomy"
    t.string   "coeff"
    t.float    "rsquare",     :default => 0.0
    t.string   "rank"
    t.string   "responses"
    t.string   "skips"
    t.string   "avganswer"
    t.float    "pval",        :default => 0.0
    t.float    "quality",     :default => 0.0
    t.integer  "user_id"
    t.datetime "created_at",                   :null => false
    t.datetime "updated_at",                   :null => false
  end

  create_table "setup_constants", :force => true do |t|
    t.float "exp_model",      :default => 0.0
    t.float "exp_pval_const", :default => 0.0
  end

  create_table "users", :force => true do |t|
    t.integer  "meter_id"
    t.float    "home_size_sf",           :default => 1000.0
    t.text     "notifications"
    t.float    "avg_monthly_kwh"
    t.float    "ee_score"
    t.string   "email",                  :default => "",     :null => false
    t.string   "encrypted_password",     :default => "",     :null => false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          :default => 0
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.datetime "created_at",                                 :null => false
    t.datetime "updated_at",                                 :null => false
  end

  add_index "users", ["email"], :name => "index_users_on_email", :unique => true
  add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true

end

注意:

在答案模型(上图)中,行:

self.meter_id = user.meter_id

将答案模型的meter_id与用户模型的meter_id相关联。我相信这就是问题所在。我尝试将上面一行更改为:

self.meter_id = 2

然后一切正常,所以很明显user.meter_id是未定义的,所以我不确定如何通过嵌套表单传递该值?我尝试使用隐藏字段,但没有运气(以下是嵌套的fields_for:答案,在form_for @questions中):

<fieldset>
    <%= f.label "Yes" %>
  <%= f.radio_button :value, 1 %>
  <%= f.label "No" %>
  <%= f.radio_button :value, 0 %>
  <%= f.hidden_field :user_id %>
  <%= f.hidden_field :question_id %>
  <%= f.hidden_field :meter_id %>
</fieldset>

1 个答案:

答案 0 :(得分:1)

首先,出于安全原因,您不希望在视图中传递当前用户。相反,您希望从控制器执行此操作。

一个起点(假设你有current_user):

@answer = current_user.answers.create(params[:answer].merge(:user => current_user))

从那以后,由您决定如何将用户传递给答案模型。但是,你可以使用它:

self.meter_id = question.user.meter_id

假设这是合适的。