2010-07-17 16 views
10

Sto imparando Rails e ho avuto un piccolo problema. Sto scrivendo morto semplice applicazione con le liste di compiti, in modo simile a modelli che:Counter_cache multiplo nel modello 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 

Tabella per List modello ha colonne tasks_counter e undone_tasks_counter.

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

Con tale codice non c'è attr_readonly :tasks_counter per List casi, ma mi piacerebbe avere un contatore per le attività annullate pure. C'è un modo per avere più counter cache automaticamente da Rails.

Finora, sono riuscito a creare TasksObserver che aumenta o diminuisce Task#undone_tasks_counter, ma forse c'è un modo più semplice.

+0

lo hai capito alla fine? –

risposta

19

Hai provato con una colonna personalizzata contro-cache? Il dottore qui: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

Essa suggerisce che è possibile passare un nome-colonna all'opzione counter_cache, che si può ben essere in grado di chiamare due volte per esempio

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

Nota: in realtà non testato.

+2

Ha funzionato davvero. Non ho usato l'account SO per un bel po 'di tempo, grazie per una soluzione così pulita! –

+1

Ho appena provato questo e il risultato è stato il secondo incremento della cache due volte e il primo non del tutto. Immagino che qualcosa sia cambiato nell'ultimo anno? – Steven

+0

@Steven hai ragione. Secondo l'API Rails, ora puoi semplicemente specificare il nome della colonna, risparmiando così un ulteriore passaggio. –

-1

Non sono a conoscenza di alcun metodo "automagico" per questo. Gli osservatori sembrano a posto per questo, ma personalmente preferisco usare le callback nel modello (before_save, after_save).

0

ez way.

1) primo contatore - farà automaticamente

2) manualmente "corretto"

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

Molto probabilmente avrete bisogno counter_culture gemma, in quanto in grado di gestire i contatori con condizioni personalizzate e aggiornerà il valore del contatore non solo per creare e distruggere, ma anche per gli aggiornamenti:

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 
Problemi correlati