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

好吧,这让我非常难过。 我有一个模型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]] => # # 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]] => # # 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 => # # 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 => # # 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]] => # 

不清楚的是为什么将属性设置为计算的整数而不是文字整数导致不保存列。

野性和悲伤。 有人能帮帮我吗?

更新

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

车型/ 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