Class: CounterCulture::Reconciler::Reconciliation
- Inherits:
-
Object
- Object
- CounterCulture::Reconciler::Reconciliation
- Defined in:
- lib/counter_culture/reconciler.rb
Instance Attribute Summary collapse
-
#counter ⇒ Object
readonly
Returns the value of attribute counter.
-
#options ⇒ Object
readonly
Returns the value of attribute options.
-
#relation_class ⇒ Object
readonly
Returns the value of attribute relation_class.
Instance Method Summary collapse
-
#initialize(counter, changes_holder, options, relation_class) ⇒ Reconciliation
constructor
A new instance of Reconciliation.
- #perform ⇒ Object
Constructor Details
#initialize(counter, changes_holder, options, relation_class) ⇒ Reconciliation
Returns a new instance of Reconciliation.
65 66 67 68 69 |
# File 'lib/counter_culture/reconciler.rb', line 65 def initialize(counter, changes_holder, , relation_class) @counter, @options, = counter, @relation_class = relation_class @changes_holder = changes_holder end |
Instance Attribute Details
#counter ⇒ Object (readonly)
Returns the value of attribute counter.
60 61 62 |
# File 'lib/counter_culture/reconciler.rb', line 60 def counter @counter end |
#options ⇒ Object (readonly)
Returns the value of attribute options.
60 61 62 |
# File 'lib/counter_culture/reconciler.rb', line 60 def @options end |
#relation_class ⇒ Object (readonly)
Returns the value of attribute relation_class.
60 61 62 |
# File 'lib/counter_culture/reconciler.rb', line 60 def relation_class @relation_class end |
Instance Method Details
#perform ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/counter_culture/reconciler.rb', line 71 def perform log "Performing reconciling of #{counter.model}##{counter.relation.to_sentence}." # if we're provided a custom set of column names with conditions, use them; just use the # column name otherwise # which class does this relation ultimately point to? that's where we have to start scope = relation_class counter_column_names = case column_names when Proc if column_names.lambda? && column_names.arity == 0 column_names.call else column_names.call(.fetch(:context, {})) end when Hash column_names else { nil => counter_cache_name } end raise ArgumentError, ":column_names must be a Hash of conditions and column names" unless counter_column_names.is_a?(Hash) if [:column_name] counter_column_names = counter_column_names.select do |_, v| [:column_name].to_s == v.to_s end end # iterate over all the possible counter cache column names counter_column_names.each do |where, column_name| # if the column name is nil, that means those records don't affect # counts; we don't need to do anything in that case. but we allow # specifying that condition regardless to make the syntax less # confusing next unless column_name relation_class_table_name = quote_table_name(relation_class.table_name) # select join column and count (from above) as well as cache column ('column_name') for later comparison counts_query = scope.select( "#{relation_class_table_name}.#{relation_class.primary_key}, " \ "#{relation_class_table_name}.#{relation_reflect(relation).association_primary_key(relation_class)}, " \ "#{count_select} AS count, " \ "MAX(#{relation_class_table_name}.#{column_name}) AS #{column_name}" ) # we need to join together tables until we get back to the table this class itself lives in join_clauses(where).each do |join| counts_query = counts_query.joins(join) end # iterate in batches; otherwise we might run out of memory when there's a lot of # instances and we try to load all their counts at once batch_size = .fetch(:batch_size, CounterCulture.config.batch_size) counts_query = counts_query.where([:where]).group(full_primary_key(relation_class)) find_in_batches_args = { batch_size: batch_size } find_in_batches_args[:start] = [:start] if [:start].present? find_in_batches_args[:finish] = [:finish] if [:finish].present? with_reading_db_connection do counts_query.find_in_batches(**find_in_batches_args).with_index(1) do |records, index| log "Processing batch ##{index}." # now iterate over all the models and see whether their counts are right update_count_for_batch(column_name, records) log "Finished batch ##{index}." end end end log_without_newline "\n" log "Finished reconciling of #{counter.model}##{counter.relation.to_sentence}." end |