所以基于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>
答案 0 :(得分:1)
首先,出于安全原因,您不希望在视图中传递当前用户。相反,您希望从控制器执行此操作。
一个起点(假设你有current_user):
@answer = current_user.answers.create(params[:answer].merge(:user => current_user))
从那以后,由您决定如何将用户传递给答案模型。但是,你可以使用它:
self.meter_id = question.user.meter_id
假设这是合适的。