2012-07-09 69 views
0

這是一個實際的工作示例,我已經細分並簡化了以前的帖子中包含更多詳細信息的兩位成員的請求。這些代碼是爲了解決持久性問題而提取和重寫的:近乎兩天的nil:NilChass中未定義的方法「profile」。RAILS:未定義的方法`profile'爲零:嵌套模型和回調中的NilClass

我使用gem「faker」和SQLite數據庫瀏覽器省略了控制器和視圖,並專注於建模問題。

最初的問題出現在Goal.rb中,錯誤消息指出:「未定義的方法`配置文件'爲零:NilClass」。根據SQLite數據庫瀏覽器,用戶和配置文件記錄已成功創建。

問題在於Goal.rb模型下的「user.profile.lbm_lbs」行。我不明白爲什麼user.profile不存在,即使user.profile已經通過admin.profile = Profile.create!(name ...)創建sample_data.rake(gem faker)appling bundle exec rake db:populate

以前的鏈接我張貼: RAILS: How to make new collection.build in a callback?

BffmModel::Application.routes.draw do 
    resources :users do 
    resource :profile 
    resource :goal 
    resource :tdee 
    resources :progress_charts 
    end 
end 

# == Schema Information 
# 
# Table name: users 
# 
# id    :integer   not null, primary key 
# email   :string(255) 
# password_digest :string(255) 
# created_at  :datetime  not null 
# updated_at  :datetime  not null 
# remember_token :string(255) 
# 

class User < ActiveRecord::Base 
    attr_accessible :email, :email_confirmation, :password, :password_confirmation 

    has_secure_password 
    has_one :profile 
    has_one :goal 
    has_one :tdee 
    has_many :progress_charts 

    before_save { |user| user.email = email.downcase } 
    before_save :create_remember_token 

    VALID_EMAIL_REGEX = /\A[\w+\-.][email protected][a-z\d\-.]+\.[a-z]+\z/i 

    validates :email, :confirmation => true, :presence => true, 
         length: { maximum: 50 }, 
         format: { with: VALID_EMAIL_REGEX }, 
         uniqueness: { case_sensitive: false } 

    validates :email_confirmation, :presence => true 
    validates :password, length: { minimum: 6 } 
    validates :password_confirmation, presence: true 

    private 

     def create_remember_token 
      self.remember_token = SecureRandom.urlsafe_base64 
     end 
end 

# == Schema Information 
# 
# Table name: profiles 
# 
# id    :integer   not null, primary key 
# name    :string(255) 
# surname   :string(255) 
# gender   :string(255) 
# date_of_birth :date 
# body_weight_lbs :integer 
# height_in_feets :integer 
# height_in_inches :integer 
# bf_pct   :decimal(5, 2) 
# bf_lbs   :decimal(5, 2) 
# lbm_lbs   :decimal(5, 2) 
# user_id   :integer 
# created_at  :datetime  not null 
# updated_at  :datetime  not null 
# 

class Profile < ActiveRecord::Base 
    attr_accessible :name, :surname, :gender, :date_of_birth, :body_weight_lbs, 
        :bf_pct, :height_in_feets, :height_in_inches 
    belongs_to :user 

    before_save :set_gender 
    before_save :calculate_body_fat_lbs 
    before_save :calculate_lean_body_mass_lbs 

    private 

     def set_gender 
      if self.gender == "1" 
       self.gender = "Male" 
      elsif self.gender == "2" 
       self.gender = "Female" 
      end 
     end 

     def calculate_body_fat_lbs 
      self.bf_lbs = (self.bf_pct/100) * self.body_weight_lbs 
      self.bf_lbs = self.bf_lbs.round(0) 
     end 

     def calculate_lean_body_mass_lbs 
      self.lbm_lbs = self.body_weight_lbs - self.bf_lbs 
     end 
end 

# == Schema Information 
# 
# Table name: goals 
# 
# id     :integer   not null, primary key 
# desired_bf_pct  :decimal(,) 
# goal_type    :string(255) 
# ideal_body_weight_lbs :decimal(5, 2) 
# ideal_bfm_lbs   :decimal(5, 2) 
# fat_to_lose_lbs  :decimal(5, 2) 
# lbm_to_gain_lbs  :decimal(5, 2) 
# user_id    :integer 
# created_at   :datetime  not null 
# updated_at   :datetime  not null 
# 

class Goal < ActiveRecord::Base 
    attr_accessible :desired_bf_pct, :goal_type 

    belongs_to :user 

    before_save :set_goal 
    before_save :calculate_ideal_body_weight_lbs 

    private 

    def set_goal 
     if self.goal_type == "1" 
     self.goal_type = "Lose Fat" 
     elsif self.goal_type == "2" 
     self.goal_type = "Gain Muscles" 
     end 
    end 

    def calculate_ideal_body_weight_lbs 

     self.ideal_body_weight_lbs = user.profile.lbm_lbs/(1 - (self.desired_bf_pct/100)) 
     self.ideal_body_weight_lbs = self.ideal_body_weight_lbs.round(0) 
    end 
end 

/lib/tasks/sample_data.rake作爲測試數據

namespace :db do 
    desc "Fill database with sample data" 
    task populate: :environment do 
    admin = User.create!(email: "[email protected]", 
         email_confirmation: "[email protected]", 
         password: "foobar", 
         password_confirmation: "foobar") 

    admin.profile = Profile.create!(name: "Michael", 
            surname: "Colins", 
            gender: "Male", 
            date_of_birth: "1975-03-05", 
            body_weight_lbs: 200, 
            bf_pct: 25.5, 
            height_in_feets: 5, 
            height_in_inches: 11) 

    admin.goal = Goal.create!( desired_bf_pct: 12, 
           goal_type: "Lose Fat") 

    admin.tdee = Tdee.create!(tdee_calc_type: "Harris-Benedict", 
        activity_lvl: "BMR x 1.2") 
    end 
end 

謝謝。

回答

3
admin.goal = Goal.create!( desired_bf_pct: 12, 
          goal_type: "Lose Fat") 

這條線在這裏絆倒你。

Goal.create!( desired_bf_pct: 12, 
       goal_type: "Lose Fat") 

這部分將創建一個新的Goal。在此步驟中,未設置關係:user。這意味着在Goal中的user方法將返回nil。由於nil沒有方法profile,因此在保存Goal之前調用的方法calculate_ideal_body_weight_lbs內不能調用user.profile。使用代碼,您必須明確設置:user關係。

Goal.create!( desired_bf_pct: 12, 
       goal_type: "Lose Fat", 
       user: admin) 
+0

在「失去脂肪」之後加上逗號,並且在attr_accessible中加入':user',否則會導致安全質量分配錯誤。 – smileyUser 2012-07-10 16:39:57

+0

你說的都對。現在添加逗號。 – deefour 2012-07-10 16:52:04

0

顯然user爲零。你的問題聽起來像你不知道這一點。也許你沒有登錄,或者你不明白user方法的作用。

+0

是的,你可以這麼說。我有3個月的rails體驗我假設user.profile因爲belongs_to:user而工作。這不正確不是嗎? – smileyUser 2012-07-09 01:03:05

+0

如何將「用戶」與幾個對象例如配置文件填充到模型中? – smileyUser 2012-07-09 01:29:49

相關問題