在我的应用程序中,我有一个与 status_updates 模型有很多关系的用户模型。
目前,我的数据库只保存了 1 个用户和零个 status_updates。
奇怪的是,当我在 consol 中搜索 status_updates 或这些对象之间的关系时,确认数据库中的 status_updates 为 nil。
StatusUpdate.count
(0.2ms)  SELECT COUNT(*) FROM "status_updates" 
=> 0 
StatusUpdate.any?
(0.1ms)  SELECT COUNT(*) FROM "status_updates" 
=> false 
user.status_updates.count
(0.2ms)  SELECT COUNT(*) FROM "status_updates" WHERE "status_updates"."user_id" = 1
=> 0 
user.status_updates.any?
(0.2ms)  SELECT COUNT(*) FROM "status_updates" WHERE "status_updates"."user_id" = 1
=> false 
所以,这对我来说很清楚。
但是,当我在我的应用程序中编写以下内容时,会返回一个 status_update 对象!
def end_date             
 if self.status_updates.any? == false
  return self.status_updates.any?
 elsif self.status_updates.any? == true
  return self.status_updates.first
 end
end  
这是我认为的电话
current_user.end_date
这就是返回给视图的内容:
#<StatusUpdate:0x007fa99765d6f8>
如果我将视图中的调用更改为:
current_user.status_updates.first
=> <StatusUpdate:0x007fa99740b5f8>
但是,如果我这样称呼:
current_user.status_updates.count
=> 0
current_user.status_updates.any?
=> true
在我只使用 current_user.status_updates 的视图中,它返回
[#<StatusUpdate id: nil, created_at: nil, updated_at: nil, user_id: 1, current_weight: 0.0, current_bf_pct: 0.0, current_lbm: 0.0, current_fat_weight: 0.0, change_in_weight: nil, change_in_bf_pct: nil, change_in_lbm: nil, change_in_fat_weight: nil, total_weight_change: nil, total_bf_pct_change: nil, total_lbm_change: nil, total_fat_change: nil>]
这里发生了什么?!
用户模型关系
has_many :status_updates, 依赖: :destroy
状态更新模型关系
属于_to:用户
状态更新模型
class StatusUpdate < ActiveRecord::Base
 belongs_to :user
 after_initialize :default_values 
 before_save :sanitize 
 attr_accessible :current_weight,
               :current_bf_pct,
               :current_lbm,
               :current_fat_weight,
               :change_in_weight,
               :change_in_bf_pct,
               :change_in_lbm,
               :change_in_fat_weight,
               :total_weight_change,
               :total_bf_pct_change,
               :total_lbm_change,
               :total_fat_change,
               :created_at
 validates :user_id,            presence: true
 validates :current_bf_pct,     presence: true, numericality: true, length: { minimum: 2, maximum:5 }  
 validates :current_weight,     presence: true, numericality: true, length: { minimum: 2, maximum:5 } 
 validates :current_lbm,        presence: true
 validates :current_fat_weight, presence: true                   
 def sanitize     
 if self.current_bf_pct >= 0.5
   self.current_bf_pct /= 100
    if self.current_bf_pct <= 0.04
      self.current_fb_pct *= 100
    end 
 end
 self.current_fat_weight = self.current_weight * self.current_bf_pct
 self.current_lbm = self.current_weight - self.current_fat_weight
 end  
 def default_values
 if self.created_at == nil 
  self.current_bf_pct       = 0.20 
  self.current_weight       = 0 
  self.current_lbm          = 0 
  self.current_fat_weight   = 0 
  self.change_in_weight     = 0 
  self.change_in_bf_pct     = 0 
  self.change_in_lbm        = 0 
  self.change_in_fat_weight = 0 
  self.total_weight_change  = 0 
  self.total_bf_pct_change  = 0 
  self.total_lbm_change     = 0 
  self.total_fat_change     = 0 
  end
 end
  def previous_status_update
   previous_status_update = user.status_updates.where( "created_at < ? ", self.created_at ).first   
 if previous_status_update == nil
   return self
 else
   previous_status_update
 end
end 
 default_scope order: 'status_updates.created_at DESC'
end
用户模型:
    class User < ActiveRecord::Base
      # Include default devise modules. Others available are:
      # :token_authenticatable, :confirmable,
      # :lockable, :timeoutable and :omniauthable
      devise :database_authenticatable, :registerable,
            :recoverable, :rememberable, :trackable, :validatable
      before_create :sanitize
      has_many :status_updates, dependent: :destroy
      has_many :meals, dependent: :destroy
      has_many :custom_foods, dependent: :destroy
      has_many :meal_foods, through: :meals
      # after_initialize :default_values
      attr_accessor :user_password, :user_password_confirmation, :current_password
      attr_accessible :email,
                      :password,
                      :password_confirmation,
                      :current_password,
                      :goal,
                      :measurement,
                      :bmr_formula,
                      :fat_factor,
                      :protein_factor,
                      :remember_me,
                      :deficit_amnt,
                      :target_bf_pct,
                      :activity_factor,
                      :current_password
      validates :email,                 presence: true
      validates :target_bf_pct,         presence: true, on: :update, length: { minimum: 3, maximum: 4 }
      validates :activity_factor,       presence: true, on: :update
      validates :deficit_amnt,          presence: true, on: :update
      validates :fat_factor,            presence: true, on: :update
      validates :protein_factor,        presence: true, on: :update
      def new?
        self.created_at <= 1.minutes.ago.to_date ? true : false
      end
      def sanitize
        #inputs
        self.activity_factor       = 1.3
        self.deficit_amnt          = 1
        self.target_bf_pct         = 10 
        self.fat_factor            = 0.45
        self.protein_factor        = 1
      end
      def end_date             
        if self.status_updates.any? == false
          #Time.now
          self.status_updates.any?
        elsif self.status_updates.any? == true
          #(self.start_date + self.weeks_to_goal.to_i.weeks).strftime("%m/%d/%Y")
          self.status_updates
        end
      end
      def start_date           
        if self.status_updates.any? == true
          self.status_updates.first.created_at
        end
      end
      def daily_caloric_deficit 
        self.tdee.to_d - self.daily_intake.to_d
      end
      def current_fat_weight   
        BigDecimal(self.latest_status_update.current_fat_weight, 4)
      end
      def current_lbm          
        BigDecimal(self.latest_status_update.current_lbm, 4)
      end
      def current_bf_pct       
        BigDecimal(self.latest_status_update.current_bf_pct * 100, 4)
      end
      def current_weight       
        BigDecimal(self.latest_status_update.current_weight, 4)
      end
      def total_weight         
        self.latest_status_update.current_weight
      end
    #  def lbm                  
    #    self.latest_status_updates.current_lbm
    #  end
      def recent_weight_change 
        BigDecimal(self.latest_status_update.current_weight - self.latest_status_update.previous_status_update.current_weight, 2) 
      end
      def recent_lbm_change   
        BigDecimal(self.latest_status_update.current_lbm - self.latest_status_update.previous_status_update.current_lbm, 2)
      end
      def recent_fat_change
        BigDecimal(self.latest_status_update.current_fat_weight - self.latest_status_update.previous_status_update.current_fat_weight, 3)
      end
      def total_lbm_change
        BigDecimal(self.latest_status_update.current_lbm - self.oldest_status_update.current_lbm, 3)
      end
      def total_fat_change 
        BigDecimal(self.latest_status_update.current_fat_weight - self.oldest_status_update.current_fat_weight, 3)
      end
      def total_weight_change
        BigDecimal(self.latest_status_update.current_weight - self.oldest_status_update.current_weight, 3)
      end
      def last_date
        self.status_updates.last.created_at.strftime("%m/%d/%Y") 
      end
      def beginning_date
        self.status_updates.first.created_at.strftime("%m/%d/%Y") 
      end
      def latest_status_update
        self.status_updates.first  
      end
      def oldest_status_update
        self.status_updates.last
      end
      def bmr
        cur_lbm = self.current_lbm
        cur_lbm *= 0.45
        '%.2f' % (370 + (21.6 * cur_lbm.to_d))
      end
      def target_weight
        tar_bf_pct = self.target_bf_pct /= 100
        '%.2f' %  ((self.total_weight * tar_bf_pct)+ self.current_lbm)
      end 
      def fat_to_burn
        '%.2f' % (self.total_weight.to_d - self.target_weight.to_d)
      end
      def tdee
        '%.2f' % (self.bmr.to_d * self.activity_factor.to_d)
      end
      def deficit_pct
        daily_cal_def = ((self.deficit_amnt.to_f * 3500)/7)
        (daily_cal_def.to_d/self.tdee.to_d)
      end
      def daily_calorie_burn
        '%.2f' % (self.tdee.to_d * self.deficit_pct.to_d)  
      end
      def weekly_calorie_burn_rate
        '%.2f' % (self.daily_calorie_burn.to_d*7) 
      end
      def weeks_to_goal
        '%.2f' %  (self.fat_to_burn.to_d*3500/self.weekly_calorie_burn_rate.to_d) 
      end                  
      def daily_intake
        '%.2f' % (self.tdee.to_d - self.daily_calorie_burn.to_d)
      end                       
      def total_grams_of(macro)
        self.meal_foods.map(¯o).inject(:+)
      end 
      def pct_fat_satisfied
        #how much of a macro is needed?
        fat_needed = self.fat_factor * self.current_lbm
        #how much is in the meal?
        fat_provided = self.total_grams_of(:fat)
        #percent needed
        pct_fulfilled = fat_provided.to_f/fat_needed.to_f
        BigDecimal(pct_fulfilled, 2)*100
      end 
      def pct_protein_satisfied
        #how much protien is needed?
        protein_needed = self.protein_factor * self.current_lbm
        #how much protien is provided?
        protein_provided = total_grams_of(:protien)
        #pct of protien satisfied?
        pct_fulfilled = protein_provided.to_f/protein_needed.to_f
        BigDecimal(pct_fulfilled, 2)*100
      end    
      def pct_carbs_satisfied
        #how many carbs are needed?
        cals_required = self.tdee.to_f - (self.tdee.to_f * self.deficit_pct.to_f)
        fat_cals = total_grams_of(:fat) * 9
        protien_cals = total_grams_of(:protien) * 4
        #how many carbs are provided?
        cals_provided = fat_cals + protien_cals
        cals_balance = cals_required - cals_provided
        carbs_needed = cals_balance/4
        carbs_provided = total_grams_of(:carbs)
        BigDecimal(carbs_provided / carbs_needed, 2) * 100
      end 
    end
我试过重置我的数据库,同样的问题出现了。
回顾一下:
似乎正在初始化 status_update,并且该对象的初始化版本是视图可用的。所有属性都是初始化的,这就是为什么它没有 id 或创建时间的时间戳......因为它从未被创建。
但是,当我尝试从控制台访问它时,我意识到它给了我“零”和所有可预测的值,因为在控制台中它正在寻找关系中已经创建的对象关系。
所以这里更精确的问题是视图返回对象的初始化版本而不是控制台返回什么?
当应用程序在用户模型中遇到一个方法时,它会抛出一个错误,因为当它调用类似的东西时 status_update 不存在
self.status_updates.first