Class: SuperSettings::Setting
- Inherits:
-
Object
- Object
- SuperSettings::Setting
- Includes:
- Attributes
- Defined in:
- lib/super_settings/setting.rb
Overview
This is the model for interacting with settings. This class provides methods for finding, validating, and updating settings.
This class does not deal with actually persisting settings to and fetching them from a data store. You need to specify the storage engine you want to use with the storage class method. This gem ships with storage engines for ActiveRecord, Redis, and HTTP (microservice). See the SuperSettings::Storage class for more details.
Defined Under Namespace
Classes: InvalidRecordError
Constant Summary collapse
- LAST_UPDATED_CACHE_KEY =
Cache key used for storing the last updated timestamp.
"SuperSettings.last_updated_at"- STRING =
"string"- INTEGER =
"integer"- FLOAT =
"float"- BOOLEAN =
"boolean"- DATETIME =
"datetime"- ARRAY =
"array"- VALUE_TYPES =
[STRING, INTEGER, FLOAT, BOOLEAN, DATETIME, ARRAY].freeze
- ARRAY_DELIMITER =
/[\n\r]+/.freeze
Class Attribute Summary collapse
-
.after_save_blocks ⇒ Object
readonly
Returns the value of attribute after_save_blocks.
-
.cache ⇒ Object
Set a cache to use for caching values.
-
.storage ⇒ Class
private
The storage class to use for persisting data.
Instance Attribute Summary collapse
-
#changed_by ⇒ Object
The changed_by attribute is used to temporarily store an identifier for the user who made a change to a setting to be stored in the history table.
-
#errors ⇒ Hash<String, Array<String>>
readonly
Return hash of errors generated from the last call to
valid?.
Class Method Summary collapse
-
.active ⇒ Array<Setting>
Get all the current settings.
-
.add_record_to_transaction(record) ⇒ Object
private
Add a record to the current transaction.
-
.after_save {|setting| ... } ⇒ Object
Add a block of code that will be called when a setting is saved.
-
.all ⇒ Array<Setting>
Get all the settings.
-
.bulk_update(params, changed_by = nil) ⇒ Array
Bulk update settings in a single database transaction.
-
.clear_last_updated_cache ⇒ Object
private
Clear the last updated timestamp from the cache.
-
.create!(attributes) ⇒ Setting
Create a new setting with the specified attributes.
-
.find_by_key(key) ⇒ Object
Get a setting by its unique key.
-
.last_updated_at ⇒ Time
Return the maximum updated at value from all the rows.
-
.transaction(&block) ⇒ Object
private
Wrap a block of code in a transaction.
-
.updated_since(time) ⇒ Array<Setting>
Get all settings that have been updated since the specified time stamp.
-
.value_type(value) ⇒ String
Determine the value type from a value.
Instance Method Summary collapse
-
#array? ⇒ Boolean
Return true if the setting has an array value type.
-
#as_json(options = nil) ⇒ Hash
Serialize to a hash that is used for rendering JSON responses.
-
#boolean? ⇒ Boolean
Return true if the setting has a boolean value type.
-
#changes ⇒ Hash<String, Array>
Get hash of attribute changes.
-
#created_at ⇒ Time
Get the time the setting was first created.
-
#created_at=(val) ⇒ Object
Set the time when the setting was created.
-
#datetime? ⇒ Boolean
Return true if the setting has a datetime value type.
-
#delete! ⇒ void
Mark the record as deleted.
-
#deleted=(val) ⇒ Object
Set the deleted flag on the setting.
-
#deleted? ⇒ Boolean
(also: #deleted)
Return true if the setting has been marked as deleted.
-
#description ⇒ String
Get the description for the setting.
-
#description=(val) ⇒ Object
Set the description of the setting.
-
#float? ⇒ Boolean
Return true if the setting has a float value type.
-
#history(limit: nil, offset: 0) ⇒ Array<SuperSettings::History>
Return array of history items reflecting changes made to the setting over time.
-
#initialize(attributes = {}) ⇒ Setting
constructor
A new instance of Setting.
-
#integer? ⇒ Boolean
Return true if the setting has an integer value type.
-
#key ⇒ String
Get the unique key for the setting.
-
#key=(val) ⇒ Object
Set the value of the setting.
-
#persisted? ⇒ Boolean
Return true if the record has been stored in the data storage engine.
-
#save! ⇒ void
Save the setting to the data storage engine.
-
#string? ⇒ Boolean
Return true if the setting has a string value type.
-
#to_json(options = nil) ⇒ String
Serialize to a JSON string.
-
#update!(attributes) ⇒ void
Update the setting attributes and save it.
-
#updated_at ⇒ Time
Get the time the setting was last updated.
-
#updated_at=(val) ⇒ Object
Set the time when the setting was last updated.
-
#valid? ⇒ Boolean
Return true if the record has valid data.
-
#value ⇒ Object
The value of a setting coerced to the appropriate class depending on its value type.
-
#value=(val) ⇒ Object
Set the value of the setting.
-
#value_changed? ⇒ Boolean
Return true if the value of the setting has changed.
-
#value_type ⇒ String
Get the type of value being stored in the setting.
-
#value_type=(val) ⇒ Object
Set the value type of the setting.
Methods included from Attributes
Constructor Details
#initialize(attributes = {}) ⇒ Setting
Returns a new instance of Setting.
309 310 311 312 313 314 315 316 317 318 319 |
# File 'lib/super_settings/setting.rb', line 309 def initialize(attributes = {}) @changes = {} @errors = {} if attributes.is_a?(Storage) @record = attributes else @record = self.class.storage.new self.attributes = attributes self.value_type ||= STRING end end |
Class Attribute Details
.after_save_blocks ⇒ Object (readonly)
Returns the value of attribute after_save_blocks.
52 53 54 |
# File 'lib/super_settings/setting.rb', line 52 def after_save_blocks @after_save_blocks end |
.cache ⇒ Object
Set a cache to use for caching values. This feature is optional. The cache must respond to delete(key) and fetch(key, &block). If you are running in a Rails environment, you can use Rails.cache or any ActiveSupport::Cache::Store object.
47 48 49 |
# File 'lib/super_settings/setting.rb', line 47 def cache @cache end |
.storage ⇒ Class
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns The storage class to use for persisting data.
56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/super_settings/setting.rb', line 56 def storage if @storage == NOT_SET if defined?(ActiveRecord) && defined?(::SuperSettings::Storage::ActiveRecordStorage) ::SuperSettings::Storage::ActiveRecordStorage else raise ArgumentError.new("No storage class defined for #{name}") end else @storage end end |
Instance Attribute Details
#changed_by ⇒ Object
The changed_by attribute is used to temporarily store an identifier for the user who made a change to a setting to be stored in the history table. This value is optional and is cleared after the record is saved.
38 39 40 |
# File 'lib/super_settings/setting.rb', line 38 def changed_by @changed_by end |
#errors ⇒ Hash<String, Array<String>> (readonly)
Return hash of errors generated from the last call to valid?
521 522 523 |
# File 'lib/super_settings/setting.rb', line 521 def errors @errors end |
Class Method Details
.active ⇒ Array<Setting>
Get all the current settings.
102 103 104 105 106 |
# File 'lib/super_settings/setting.rb', line 102 def active storage.with_connection do storage.active.collect { |record| new(record) } end end |
.add_record_to_transaction(record) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Add a record to the current transaction.
233 234 235 236 |
# File 'lib/super_settings/setting.rb', line 233 def add_record_to_transaction(record) changes = Thread.current[:super_settings_transaction] changes << record if changes end |
.after_save {|setting| ... } ⇒ Object
Add a block of code that will be called when a setting is saved. The block will be called with a Setting object. The object will have been saved, but the ‘changes` hash will still be set indicating what was changed. You can define multiple after_save blocks.
73 74 75 |
# File 'lib/super_settings/setting.rb', line 73 def after_save(&block) after_save_blocks << block end |
.all ⇒ Array<Setting>
Get all the settings. This will even return settings that have been marked as deleted. If you just want current settings, then call #active instead.
93 94 95 96 97 |
# File 'lib/super_settings/setting.rb', line 93 def all storage.with_connection do storage.all.collect { |record| new(record) } end end |
.bulk_update(params, changed_by = nil) ⇒ Array
Bulk update settings in a single database transaction. No changes will be saved if there are any invalid records.
164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/super_settings/setting.rb', line 164 def bulk_update(params, changed_by = nil) all_valid, settings = update_settings(params, changed_by) if all_valid storage.with_connection do transaction do |_changes| settings.each do |setting| setting.save! end end end clear_last_updated_cache end [all_valid, settings] end |
.clear_last_updated_cache ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Clear the last updated timestamp from the cache.
202 203 204 |
# File 'lib/super_settings/setting.rb', line 202 def clear_last_updated_cache cache&.delete(Setting::LAST_UPDATED_CACHE_KEY) end |
.create!(attributes) ⇒ Setting
Create a new setting with the specified attributes.
81 82 83 84 85 86 87 |
# File 'lib/super_settings/setting.rb', line 81 def create!(attributes) setting = new(attributes) storage.with_connection do setting.save! end setting end |
.find_by_key(key) ⇒ Object
Get a setting by its unique key.
122 123 124 125 126 127 |
# File 'lib/super_settings/setting.rb', line 122 def find_by_key(key) record = storage.with_connection { storage.find_by_key(key) } if record new(record) end end |
.last_updated_at ⇒ Time
Return the maximum updated at value from all the rows. This is used in the caching scheme to determine if data needs to be reloaded from the database.
133 134 135 136 137 |
# File 'lib/super_settings/setting.rb', line 133 def last_updated_at fetch_from_cache(LAST_UPDATED_CACHE_KEY) do storage.with_connection { storage.last_updated_at } end end |
.transaction(&block) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Wrap a block of code in a transaction.
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/super_settings/setting.rb', line 209 def transaction(&block) changes = Thread.current[:super_settings_transaction] return yield if changes changes = [] Thread.current[:super_settings_transaction] = changes begin @storage.transaction(&block) clear_last_updated_cache changes.each do |setting| setting.send(:call_after_save_callbacks) setting.send(:clear_changes) end ensure Thread.current[:super_settings_transaction] = nil end end |
.updated_since(time) ⇒ Array<Setting>
Get all settings that have been updated since the specified time stamp.
112 113 114 115 116 117 |
# File 'lib/super_settings/setting.rb', line 112 def updated_since(time) time = SuperSettings::Coerce.time(time) storage.with_connection do storage.updated_since(time).collect { |record| new(record) } end end |
.value_type(value) ⇒ String
Determine the value type from a value.
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/super_settings/setting.rb', line 182 def value_type(value) case value when Integer INTEGER when Numeric FLOAT when TrueClass, FalseClass BOOLEAN when Time, Date DATETIME when Array ARRAY else STRING end end |
Instance Method Details
#array? ⇒ Boolean
Return true if the setting has an array value type.
475 476 477 |
# File 'lib/super_settings/setting.rb', line 475 def array? value_type == ARRAY end |
#as_json(options = nil) ⇒ Hash
Serialize to a hash that is used for rendering JSON responses.
552 553 554 555 556 557 558 559 560 561 562 563 |
# File 'lib/super_settings/setting.rb', line 552 def as_json( = nil) attributes = { key: key, value: value, value_type: value_type, description: description, created_at: created_at&.utc&.iso8601(6), updated_at: updated_at&.utc&.iso8601(6) } attributes[:deleted] = true if deleted? attributes end |
#boolean? ⇒ Boolean
Return true if the setting has a boolean value type.
463 464 465 |
# File 'lib/super_settings/setting.rb', line 463 def boolean? value_type == BOOLEAN end |
#changes ⇒ Hash<String, Array>
Get hash of attribute changes. The hash keys are the names of attributes that have changed and the values are an array with [old value, new value]. The keys will be one of key, raw_value, value_type, description, deleted, created_at, or updated_at.
578 579 580 |
# File 'lib/super_settings/setting.rb', line 578 def changes @changes.dup end |
#created_at ⇒ Time
Get the time the setting was first created.
412 413 414 |
# File 'lib/super_settings/setting.rb', line 412 def created_at @record.created_at end |
#created_at=(val) ⇒ Object
Set the time when the setting was created.
419 420 421 422 423 |
# File 'lib/super_settings/setting.rb', line 419 def created_at=(val) val = TimePrecision.new(val).time will_change!(:created_at, val) unless created_at == val @record.created_at = val end |
#datetime? ⇒ Boolean
Return true if the setting has a datetime value type.
469 470 471 |
# File 'lib/super_settings/setting.rb', line 469 def datetime? value_type == DATETIME end |
#delete! ⇒ void
This method returns an undefined value.
Mark the record as deleted. The record will not actually be deleted since it’s still needed for caching purposes, but it will no longer be returned by queries.
527 528 529 |
# File 'lib/super_settings/setting.rb', line 527 def delete! update!(deleted: true) end |
#deleted=(val) ⇒ Object
Set the deleted flag on the setting. Deleted settings are not visible but are not actually removed from the data store.
403 404 405 406 407 |
# File 'lib/super_settings/setting.rb', line 403 def deleted=(val) val = Coerce.boolean(val) will_change!(:deleted, val) unless deleted? == val @record.deleted = val end |
#deleted? ⇒ Boolean Also known as: deleted
Return true if the setting has been marked as deleted.
393 394 395 |
# File 'lib/super_settings/setting.rb', line 393 def deleted? @record.deleted? end |
#description ⇒ String
Get the description for the setting.
376 377 378 |
# File 'lib/super_settings/setting.rb', line 376 def description @record.description end |
#description=(val) ⇒ Object
Set the description of the setting.
383 384 385 386 387 388 |
# File 'lib/super_settings/setting.rb', line 383 def description=(val) val = val&.to_s val = nil if val&.empty? will_change!(:description, val) unless description == val @record.description = val end |
#float? ⇒ Boolean
Return true if the setting has a float value type.
457 458 459 |
# File 'lib/super_settings/setting.rb', line 457 def float? value_type == FLOAT end |
#history(limit: nil, offset: 0) ⇒ Array<SuperSettings::History>
Return array of history items reflecting changes made to the setting over time. Items should be returned in reverse chronological order so that the most recent changes are first.
544 545 546 |
# File 'lib/super_settings/setting.rb', line 544 def history(limit: nil, offset: 0) @record.history(limit: limit, offset: offset) end |
#integer? ⇒ Boolean
Return true if the setting has an integer value type.
451 452 453 |
# File 'lib/super_settings/setting.rb', line 451 def integer? value_type == INTEGER end |
#key ⇒ String
Get the unique key for the setting.
324 325 326 |
# File 'lib/super_settings/setting.rb', line 324 def key @record.key end |
#key=(val) ⇒ Object
Set the value of the setting. The value will be coerced to a string for storage.
331 332 333 334 335 |
# File 'lib/super_settings/setting.rb', line 331 def key=(val) val = val&.to_s will_change!(:key, val) unless key == val @record.key = val end |
#persisted? ⇒ Boolean
Return true if the record has been stored in the data storage engine.
506 507 508 |
# File 'lib/super_settings/setting.rb', line 506 def persisted? @record.persisted? end |
#save! ⇒ void
This method returns an undefined value.
Save the setting to the data storage engine.
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 |
# File 'lib/super_settings/setting.rb', line 482 def save! unless valid? raise InvalidRecordError.new(errors.values.join("; ")) end = Time.now self.created_at ||= self.updated_at = if updated_at.nil? || !changed?(:updated_at) return if @changes.empty? self.class.storage.with_connection do self.class.transaction do record_value_change @record.save! self.class.add_record_to_transaction(self) end end nil end |
#string? ⇒ Boolean
Return true if the setting has a string value type.
444 445 446 |
# File 'lib/super_settings/setting.rb', line 444 def string? value_type == STRING end |
#to_json(options = nil) ⇒ String
Serialize to a JSON string.
569 570 571 |
# File 'lib/super_settings/setting.rb', line 569 def to_json( = nil) as_json.to_json() end |
#update!(attributes) ⇒ void
This method returns an undefined value.
Update the setting attributes and save it.
535 536 537 538 |
# File 'lib/super_settings/setting.rb', line 535 def update!(attributes) self.attributes = attributes save! end |
#updated_at ⇒ Time
Get the time the setting was last updated.
428 429 430 |
# File 'lib/super_settings/setting.rb', line 428 def updated_at @record.updated_at end |
#updated_at=(val) ⇒ Object
Set the time when the setting was last updated.
435 436 437 438 439 |
# File 'lib/super_settings/setting.rb', line 435 def updated_at=(val) val = TimePrecision.new(val).time will_change!(:updated_at, val) unless updated_at == val @record.updated_at = val end |
#valid? ⇒ Boolean
Return true if the record has valid data.
513 514 515 516 |
# File 'lib/super_settings/setting.rb', line 513 def valid? validate! @errors.empty? end |
#value ⇒ Object
The value of a setting coerced to the appropriate class depending on its value type.
340 341 342 343 344 345 346 |
# File 'lib/super_settings/setting.rb', line 340 def value if deleted? nil else coerce(raw_value) end end |
#value=(val) ⇒ Object
Set the value of the setting.
351 352 353 354 355 |
# File 'lib/super_settings/setting.rb', line 351 def value=(val) val = serialize(val) unless val.is_a?(Array) val = val.join("\n") if val.is_a?(Array) self.raw_value = val end |
#value_changed? ⇒ Boolean
Return true if the value of the setting has changed. In addition to changing the value, this will be triggered if the key changed or if the setting was marked as deleted.
586 587 588 |
# File 'lib/super_settings/setting.rb', line 586 def value_changed? (@changes.keys & %w[key raw_value deleted]).any? end |
#value_type ⇒ String
Get the type of value being stored in the setting.
360 361 362 |
# File 'lib/super_settings/setting.rb', line 360 def value_type @record.value_type end |
#value_type=(val) ⇒ Object
Set the value type of the setting.
367 368 369 370 371 |
# File 'lib/super_settings/setting.rb', line 367 def value_type=(val) val = val&.to_s will_change!(:value_type, val) unless value_type == val @record.value_type = val end |