Module: Hoodoo::ActiveRecord::Dated::ClassMethods

Defined in:
lib/hoodoo/active/active_record/dated.rb

Overview

Collection of class methods that get defined on an including class via Hoodoo::ActiveRecord::Dated::included.

Instance Method Summary collapse

Instance Method Details

#dated(context, unquoted_column_names: nil) ⇒ Object

Return an ActiveRecord::Relation containing the model instances which are effective at context.request.dated_at. If this value is nil the current time in UTC is used.

If historic dating hasn’t been enabled via a call to #dating_enabled, then the default ‘all’ scope is returned instead.

context

Hoodoo::Services::Context instance describing a call context. This is typically a value passed to one of the Hoodoo::Services::Implementation instance methods that a resource subclass implements.

Additional named parameters are:

unquoted_column_names

(Optional) An Array of Strings giving one or more column names to use for the query. If omitted, all model attribtues are used as columns. If the “id” column is not included in the Array, it will be added anyway as this column is mandatory. The effect is equivalent to an Array given in the ActiveRecord select method.



223
224
225
226
# File 'lib/hoodoo/active/active_record/dated.rb', line 223

def dated( context, unquoted_column_names: nil )
  date_time = context.request.dated_at || Time.now
  return self.dated_at( date_time, unquoted_column_names: unquoted_column_names )
end

#dated_at(date_time = Time.now, unquoted_column_names: nil) ⇒ Object

Return an ActiveRecord::Relation scoping a query to include only model instances that are relevant/effective at the specified date_time.

If historic dating hasn’t been enabled via a call to #dating_enabled, then the default ‘all’ scope is returned instead.

date_time

(Optional) A Time or DateTime instance, or a String that can be converted to a DateTime instance, for which the “effective dated” scope is to be constructed.

Additional named parameters are:

unquoted_column_names

(Optional) An Array of Strings giving one or more column names to use for the query. If omitted, all model attribtues are used as columns. If the “id” column is not included in the Array, it will be added anyway as this column is mandatory. The effect is equivalent to an Array given in the ActiveRecord select method.



249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/hoodoo/active/active_record/dated.rb', line 249

def dated_at( date_time = Time.now, unquoted_column_names: nil )

  dating_table_name = dated_with_table_name()
  return all() if dating_table_name.nil? # "Model.all" -> returns anonymous scope

  # Rationalise and convert the date time to UTC.

  date_time      = Hoodoo::Utilities.rationalise_datetime( date_time ).utc
  safe_date_time = self.connection.quoted_date( date_time )

  # Create strings that specify the required attributes escaped and
  # joined by commas for use in a SQL query, for both main and history
  # tables.

  safe_name_string = self.quoted_column_name_string(
    unquoted_column_names: unquoted_column_names
  )

  safe_history_name_string = self.quoted_column_name_string_for_history(
    unquoted_column_names: unquoted_column_names
  )

  # A query that combines historical and current records which are
  # effective at the specified date time.

  nested_query = %{
    (
      SELECT #{ safe_name_string } FROM (
        SELECT #{ safe_name_string },"updated_at" AS "effective_start",NULL AS "effective_end"
        FROM #{ self.table_name }
        UNION ALL
        SELECT #{ safe_history_name_string },"effective_start","effective_end"
        FROM #{ dating_table_name }
      ) AS u
      WHERE "effective_start" <= '#{ safe_date_time }' AND ("effective_end" > '#{ safe_date_time }' OR "effective_end" IS NULL)
    ) AS #{ self.table_name }
  }

  # Form a query which uses ActiveRecord to list a dated or current
  # record.

  return from( nested_query )
end

#dated_historical_and_current(unquoted_column_names: nil) ⇒ Object

Return an ActiveRecord::Relation scoping a query that would include all historical and current model instances.

If historic dating hasn’t been enabled via a call to #dating_enabled, then the default ‘all’ scope is returned instead.

Named parameters are:

unquoted_column_names

(Optional) An Array of Strings giving one or more column names to use for the query. If omitted, all model attributes are used as columns. If the “id” column is not included in the Array, it will be added anyway as this column is mandatory. The effect is equivalent to an Array given in the ActiveRecord select method.



310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/hoodoo/active/active_record/dated.rb', line 310

def dated_historical_and_current( unquoted_column_names: nil )

  dating_table_name = dated_with_table_name()
  return all() if dating_table_name.nil? # "Model.all" -> returns anonymous scope

  # Create strings that specify the required attributes escaped and
  # joined by commas for use in a SQL query, for both main and history
  # tables.

  safe_name_string = self.quoted_column_name_string(
    unquoted_column_names: unquoted_column_names
  )

  safe_history_name_string = self.quoted_column_name_string_for_history(
    unquoted_column_names: unquoted_column_names
  )

  # A query that combines historical and current records.

  nested_query = %{
    (
      SELECT #{ safe_name_string }
      FROM #{ self.table_name }
      UNION ALL
      SELECT #{ safe_history_name_string }
      FROM #{ dating_table_name }
    ) AS #{ self.table_name }
  }

  # Form a query which uses ActiveRecord to list current and dated
  # records.

  return from( nested_query )
end

#dated_withObject

Returns the anonymous ActiveRecord::Base instance used for this model’s history entries, or nil if historic dating has not been enabled via a prior call to #dating_enabled.



349
350
351
# File 'lib/hoodoo/active/active_record/dated.rb', line 349

def dated_with
  return self.nz_co_loyalty_hoodoo_dated_with
end

#dated_with_table_nameObject

Get the symbolised name of the history table for model. This defaults to the name of the model’s table concatenated with _history_entries. If the table name is :posts, the history table would be :posts_history_entries.

If historic dating hasn’t been enabled via a call to #dating_enabled, returns nil.



361
362
363
364
# File 'lib/hoodoo/active/active_record/dated.rb', line 361

def dated_with_table_name
  instance = self.dated_with()
  instance.nil? ? nil : instance.table_name
end

#dating_enabled(history_table_name: self.table_name + '_history_entries') ⇒ Object

Activate historic dating for this model.

See the module documentation for Hoodoo::ActiveRecord::Dated for full information on dating, table requirements, default table names and so forth.

Named parameters are:

history_table_name

Optional String or Symbol name of the table which stores the history entries for this model. If omitted, defaults to the value described by the documentation for Hoodoo::ActiveRecord::Dated.



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/hoodoo/active/active_record/dated.rb', line 166

def dating_enabled( history_table_name: self.table_name + '_history_entries' )

  # Define an anonymous model for the history entries.

  history_klass = Class.new( ::ActiveRecord::Base ) do
    self.primary_key = :id
    self.table_name  = history_table_name
  end

  # Record the anonymous model class in a namespaced class attribute
  # for reference in the rest of the dating code via #dated_with().

  self.nz_co_loyalty_hoodoo_dated_with = history_klass

  # Enable the monkey patch to the Finder module's '#acquire_in' class
  # method, if need be.

  if self.include?( Hoodoo::ActiveRecord::Finder )
    Hoodoo::Monkey.register(
      target_unit:      self,
      extension_module: Hoodoo::Monkey::Patch::ActiveRecordDatedFinderAdditions
    )

    Hoodoo::Monkey.enable( extension_module: Hoodoo::Monkey::Patch::ActiveRecordDatedFinderAdditions )
  end
end

#dating_enabled?Boolean

If a prior call has been made to #dating_enabled then this method returns true, else false.

Returns:

  • (Boolean)


196
197
198
# File 'lib/hoodoo/active/active_record/dated.rb', line 196

def dating_enabled?
  return self.dated_with().present?
end