1

私のアプリケーションには、status_updates モデルとの has many 関係を持つユーザー モデルがあります。

現在、私のデータベースには 1 人のユーザーしか保存されておらず、status_updates は保存されていません。

奇妙なのは、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

ステータス更新モデルの関係

所属先:ユーザー


ステータス更新モデル

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(&macro).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、または作成時のタイムスタンプがありません...作成されていないためです。

ただし、コンソールからアクセスしようとすると、「nil」とすべての予測可能な値が返されることに気付きました。これは、コンソールで既に作成されたオブジェクトの関係を探しているためです。

ここでのより正確な質問は、コンソールが返すものではなく、オブジェクトの初期化されたバージョンを返すビューですか?

アプリがユーザーモデル内のメソッドにヒットすると、次のような呼び出し時に status_update が存在しないため、エラーがスローされます

self.status_updates.first
4

2 に答える 2

1

この行:

#<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>]

id: nil、このモデルがまだ保存されていないことを示します。モデルを保存すると、モデルは ID のみを取得します。フレデリックが指摘したように、それが持っているという事実はuser_id: 1、おそらくユーザーを通じてこれを作成したことを示しています。したがって、どこかでこのインスタンスを作成していて、保存していません。

PS、ブール値がfalseかtrueかをチェックするのは、Rubyの形式が悪いと広く考えられています。例えば

これをしないでください:

self.status_updates.any? == false

行う

self.status_updates.any?

いずれにせよ true または false である場合は、 andをチェックとして使用ifしてください。unlessさらに良いことに、自分自身が想定されているので、あなたの場合は次のようにすることができます:

status_updates.any?

PPS の active_record は、new?まさにこのユース ケースのメソッドを定義します。まだ保存されていないレコードはnewtruenew?を返します。このメソッドや、active_record で定義されたその他のものを上書きしないよう強くお勧めします。

于 2013-05-29T20:30:09.960 に答える