2012-07-09 72 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

相关问题