2010-07-17 4 views
10

레일스를 배웠고 약간의 문제가있었습니다.여러 counter_cache in Rails 모델

class List < ActiveRecord::Base 
    has_many :tasks 
    has_many :undone_tasks, :class_name => 'Task', 
          :foreign_key => 'task_id', 
          :conditions => 'done = false' 
    # ... some validations 
end 

표에 대한 List 모델은 열을 tasks_counterundone_tasks_counter 있습니다 모델처럼 보일 그래서 나는, 작업 목록으로 죽은 간단한 응용 프로그램을 쓰고 있어요. 이러한 코드와

class Task < ActiveRecord::Base 
    belongs_to :list, :counter_cache => true 
    # .. some validations 
end 

List 인스턴스에 대한 attr_readonly :tasks_counter있다 그러나 나는뿐만 아니라 실행 취소 작업을위한 카운터를 가지고 싶습니다. Rails가 여러 카운터를 자동으로 캐시하는 방법이 있습니까?

지금까지 을 증감하는 TasksObserver을 만들었지 만 더 간단한 방법이있을 수 있습니다.

+0

결국 그것을 알아 냈습니까? –

답변

19

맞춤 카운터 캐시 열을 사용해 보셨습니까? 여기 상무부 : 실제로 테스트하지 : http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

그것은 당신이 아니라 두 번 예를 들어

belongs_to :list, :counter_cache => true  # will setup tasks_count 
belongs_to :list, :counter_cache => :undone_tasks_count 

주를 호출 할 수있다 counter_cache 옵션에 열 이름을 전달할 수 있음을 시사한다.

+2

실제로 작동했습니다. 그런 깨끗한 해결책 덕분에 오랫동안 SO 계정을 사용하지 않았습니다! –

+1

방금 ​​시도한 결과 두 번째 캐시가 두 번 증가하고 첫 번째 캐시가 전혀 증가하지 않았습니다. 작년에 무언가가 바뀐 것 같아요? – Steven

+0

@ 스티브 네 말이 맞아. Rails API에 따르면 이제 열 이름을 지정할 수 있으므로 추가 단계가 필요하지 않습니다. –

-1

나는 이것을위한 "자동적 인"방법을 모른다. 옵서버는 이것으로 좋을 것 같지만 모델에서 콜백을 사용하는 것을 선호합니다 (before_save, after_save).

0

ez 방법.

1) 제 1 카운터 - 그것은 사용자 정의 조건에 카운터를 처리 할 수있는 대부분의 아마 당신이 counter_culture 보석이 필요합니다

AnotherModelHere 

    belongs_to :user, counter_cache: :first_friends_count 


    after_create :provide_correct_create_counter_2 
    after_destroy :provide_correct_destroy_counter_2 

    def provide_correct_create_counter_2 
     User.increment_counter(:second_friends_count, another_user.id) 
    end 

    def provide_correct_destroy_counter_2 
     User.decrement_counter(:second_friends_count, another_user.id) 
    end 
-1

을 자동으로

2) 수동으로 "올바른"할 것 생성 및 삭제뿐만 아니라 업데이트도 카운터 값을 업데이트합니다.

class CreateContainers < ActiveRecord::Migration[5.0] 
    create_table :containers, comment: 'Our awesome containers' do |t| 
    t.integer :items_count,  default: 0, null: false, comment: 'Caching counter for total items' 
    t.integer :loaded_items_count, default: 0, null: false, comment: 'Caching counter for loaded items' 
    end 
end 

class Container < ApplicationRecord 
    has_many :items, inverse_of: :container 
    has_many :loaded_items, -> { where.not(loaded_at: nil) }, 
      class_name: 'Item', 
      counter_cache: :loaded_items_count 
      # Notice that you can specify custom counter cache column name 
      # in has_many definition and AR will use it! 
end 

class Item < ApplicationRecord 
    belongs_to :container, inverse_of: :items, counter_cache: true 
    counter_culture :container, column_name: proc { |model| model.loaded_at.present? ? 'loaded_items_count' : nil } 
    # But this column value will be handled by counter_culture gem 
end