Rails:模型无法保存缓存列.counts

时间:2016-04-07 17:57:20

标签: ruby-on-rails activerecord

好的,这让我非常难过。我有一个模型PhoneNumbers,它有一个整数列sent_messages_count。我使用后台任务将此列用作计数器缓存,但是,此列的不准确性似乎更为基础。

以下是我想做的事情:

phone_number.sent_messages_count = phone_number.sent_messages.count

请注意,我将表列设置为关联计数。下划线与期间。

请参阅我的控制台会话...(我已经做了一些清理工作以使其更简洁)。

# Find the phone number
[1] pry(main)> pn = PhoneNumber.find 38
  PhoneNumber Load (1.0ms)  SELECT  "phone_numbers".* FROM "phone_numbers" WHERE "phone_numbers"."id" = $1 LIMIT 1  [["id", 38]]
=> #<PhoneNumber:0x007f97902f6d70
 id: 38,
 updated_at: Thu, 07 Apr 2016 12:34:17 CDT -05:00,
 sent_messages_count: 12>

# Change the field to a new value
[2] pry(main)> pn.sent_messages_count = 100000
=> 100000

# Save it! It succeeds!
[3] pry(main)> pn.save
   (0.2ms)  BEGIN
  SQL (1.0ms)  UPDATE "phone_numbers" SET "sent_messages_count" = $1, "updated_at" = $2 WHERE "phone_numbers"."id" = $3  [["sent_messages_count", 100000], ["updated_at", "2016-04-07 17:37:41.826069"], ["id", 38]]
   (14.2ms)  COMMIT
=> true

# Reload it, and the saved value persists
[4] pry(main)> pn = PhoneNumber.find 38
  PhoneNumber Load (6.2ms)  SELECT  "phone_numbers".* FROM "phone_numbers" WHERE "phone_numbers"."id" = $1 LIMIT 1  [["id", 38]]
=> #<PhoneNumber:0x007f9790dc47e8
 id: 38,
 updated_at: Thu, 07 Apr 2016 12:37:41 CDT -05:00,
 sent_messages_count: 100000>

# Now, let's get the association count. It's 49.
[5] pry(main)> pn.sent_messages.count
   (1.6ms)  SELECT COUNT(*) FROM "messages" WHERE "messages"."from_id" = $1  [["from_id", 38]]
=> 49

# Setting column to association count
[6] pry(main)> pn.sent_messages_count = pn.sent_messages.count
   (0.6ms)  SELECT COUNT(*) FROM "messages" WHERE "messages"."from_id" = $1  [["from_id", 38]]
=> 49

# Look, the attribute has the counted value
[7] pry(main)> pn.sent_messages_count
=> 49

# And the in-memory instance had that value (I know, it's redundant)
[8] pry(main)> pn
=> #<PhoneNumber:0x007f9790dc47e8
 id: 38,
 updated_at: Thu, 07 Apr 2016 12:37:41 CDT -05:00,
 sent_messages_count: 49>

# Yep, we've changed!
[9] pry(main)> pn.changed?
=> true

# And we're valid!
[10] pry(main)> pn.valid?
  PhoneNumber Exists (0.8ms)  SELECT  1 AS one FROM "phone_numbers" WHERE ("phone_numbers"."number" = 'REDACTED' AND "phone_numbers"."id" != 38 AND "phone_numbers"."account_id" = 2) LIMIT 1
=> true

# And we're saving! ... but why is only updated_at changing?
[11] pry(main)> pn.save
   (0.2ms)  BEGIN
  SQL (0.7ms)  UPDATE "phone_numbers" SET "updated_at" = $1 WHERE "phone_numbers"."id" = $2  [["updated_at", "2016-04-07 17:39:07.200473"], ["id", 38]]
   (5.8ms)  COMMIT
=> true

# But our in-memory pn thinks it's 49
[12] pry(main)> pn
=> #<PhoneNumber:0x007f9790dc47e8
 id: 38,
 updated_at: Thu, 07 Apr 2016 12:39:07 CDT -05:00, 
 sent_messages_count: 49>

# But reloading makes me terribly sad. :(
[13] pry(main)> pn = PhoneNumber.find 38
  PhoneNumber Load (6.1ms)  SELECT  "phone_numbers".* FROM "phone_numbers" WHERE "phone_numbers"."id" = $1 LIMIT 1  [["id", 38]]
=> #<PhoneNumber:0x007f97912dc820
 id: 38,
 updated_at: Thu, 07 Apr 2016 12:39:07 CDT -05:00,
 sent_messages_count: 100000>

对我来说不清楚的原因是为什么将属性设置为计算的整数,而不是文字整数导致不保存列。< / p> 狂野和悲伤。有人能帮帮我吗?

更新

包括模型和我的架构。我省略了一些课程方法,所以这不会成为有史以来最长的问题。

模型/ phone_number.rb

include ActionView::Helpers::NumberHelper

class PhoneNumber < ActiveRecord::Base
  has_many :callable_phone_numbers
  has_many :students,
           through: :callable_phone_numbers,
           source: :callable,
           source_type: 'Student', inverse_of: :phone_numbers
  has_many :teachers,
           through: :callable_phone_numbers,
           source: :callable,
           source_type: 'Teacher'
  belongs_to :account
  has_many :sent_messages,
           class_name: 'Message',
           foreign_key: 'from_id',
           inverse_of: :from_phone_number
  has_many :received_messages,
           class_name: 'Message',
           foreign_key: 'to_id',
           inverse_of: :to_phone_number

  phony_normalize :number, default_country_code: 'US'
  validates_plausible_phone :number, presence: true
  validates :label, presence: true
  validates :account_id, presence: true
  validates :number, uniqueness: { scope: :account_id, message: "should only happen once per account" }, unless: :skip_uniqueness_validation
  attr_accessor :skip_uniqueness_validation

  # ... a bunch of scopes ...

  def messages
    Message.where("from_id = ? OR to_id = ?", id, id)
  end

  # ... some other class methods ...

  def most_recent_sent_message
    sent_messages.order("created_at DESC").take
  end

  def most_recent_received_message
    received_messages.order("created_at DESC").take
  end

  def update_caches!
    self.last_sent_message_at = self.most_recent_sent_message.try(:created_at)
    self.last_received_message_at = self.most_recent_received_message.try(:created_at)
    self.sent_messages_count = self.sent_messages.count
    self.received_messages_count = self.received_messages.count
    self.save
  end
end

schema.rb

  create_table "phone_numbers", force: :cascade do |t|
    t.string   "number"
    t.datetime "created_at",                              null: false
    t.datetime "updated_at",                              null: false
    t.string   "label"
    t.boolean  "assigned"
    t.integer  "account_id"
    t.integer  "sent_messages_count"
    t.integer  "received_messages_count"
    t.datetime "last_sent_message_at"
    t.datetime "last_received_message_at"
    t.string   "carrier_name"
    t.string   "carrier_type"
    t.datetime "carrier_updated_at"
    t.string   "home_language",            default: "en"
    t.boolean  "disconnected"
  end

0 个答案:

没有答案