したがって、Ryan Bates Railsキャスト(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が未定義であることは明らかです。そのため、ネストされたフォームを介してその値を渡す方法がわかりません。隠しフィールドを使用してみましたが、うまくいきませんでした(以下は、form_for @questions内のネストされたfields_for:answersです):
<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>