Class: Mobility::Attributes
Overview
Defines accessor methods to include on model class. Inspired by Traco’s Traco::Attributes
class.
Normally this class will be created through class methods defined using Translates accessor methods, and need not be created directly. However, the class is central to how Mobility hooks into models to add accessors and other methods, and should be useful as a reference when understanding and designing backends.
Including Attributes in a Class
Since Attributes is a subclass of Module
, including an instance of it is like including a module. Creating an instance like this:
Attributes.new(:accessor, ["title"], backend: :my_backend, locale_accessors: [:en, :ja], cache: true, fallbacks: true)
will generate an anonymous module looking something like this:
Module.new do
def title_backend
# Create a subclass of Mobility::Backend::MyBackend and include in it:
# - Mobility::Cache (from the cache: true option)
# - Mobility::Fallbacks (from the fallbacks: true option)
# Then instantiate the backend, memoize it, and return it.
end
def title(**)
title_backend.read(Mobility.locale, **).presence
end
def title?(**)
title_backend.read(Mobility.locale, **).present?
end
def title=(value)
title_backend.write(Mobility.locale, value.presence)
end
# Start Locale Accessors
#
def title_en(**)
title_backend.read(:en, **).presence
end
def title_en?(**)
title_backend.read(:en, **).present?
end
def title_en=(value)
title_backend.write(:en, value.presence)
end
def title_ja(**)
title_backend.read(:ja, **).presence
end
def title_ja?(**)
title_backend.read(:ja, **).present?
end
def title_ja=(value)
title_backend.write(:ja, value.presence)
end
# End Locale Accessors
end
Including this module into a model class will then add the backend method, the reader, writer and presence methods, and the locale accessor so the model class.
Setting up the Model Class
Accessor methods alone are of limited use without a hook to actually modify the model class. This hook is provided by the Backend::Setup#setup_model method, which is added to every backend class when it includes the Backend module.
Assuming the backend has defined a setup block by calling setup
, this block will be called when Attributes is #included in the model class, passed attributes and options defined when the backend was defined on the model class. This allows a backend to do things like (for example) define associations on a model class required by the backend, as happens in the Backend::KeyValue and Backend::Table backends.
The setup
block is also used to extend the i18n
scope/dataset with backend-specific query method support.
Since setup blocks are evaluated on the model class, it is possible that backends can conflict (for example, overwriting previously defined methods). Care should be taken to avoid defining methods on the model class, or where necessary, ensure that names are defined in such a way as to avoid conflicts with other backends.
Instance Attribute Summary collapse
-
#attributes ⇒ Array<String>
readonly
Attributes for which accessors will be defined.
-
#backend_class ⇒ Class
readonly
Backend class.
-
#backend_name ⇒ Symbol, Class
readonly
Name of backend.
-
#options ⇒ Hash
readonly
Backend options.
Instance Method Summary collapse
-
#each {|String| ... } ⇒ Object
Yield each attribute to block.
-
#included(model_class) ⇒ Object
Add this attributes module to shared Wrapper and setup model with backend setup block (see Backend::Setup#setup_model).
-
#initialize(method, *_attributes, **_options) ⇒ Attributes
constructor
A new instance of Attributes.
Constructor Details
#initialize(method, *_attributes, **_options) ⇒ Attributes
Returns a new instance of Attributes.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/mobility/attributes.rb', line 125 def initialize(method, *_attributes, **) raise ArgumentError, "method must be one of: reader, writer, accessor" unless %i[reader writer accessor].include?(method) @options = @attributes = _attributes.map &:to_s model_class = [:model_class] @backend_name = .delete(:backend) || Mobility.config.default_backend @backend_class = Class.new(get_backend_class(backend: @backend_name, model_class: model_class)) [:locale_accessors] ||= true if [:dirty] @backend_class.configure!() if @backend_class.respond_to?(:configure!) @backend_class.include Backend::Cache unless [:cache] == false @backend_class.include Backend::Dirty.for(model_class) if [:dirty] @backend_class.include Backend::Fallbacks if [:fallbacks] @accessor_locales = [:locale_accessors] @accessor_locales = Mobility.config.default_accessor_locales if [:locale_accessors] == true attributes.each do |attribute| define_backend(attribute) if %i[accessor reader].include?(method) define_method attribute do |**| mobility_get(attribute, ) end define_method "#{attribute}?" do |**| mobility_present?(attribute, ) end end define_method "#{attribute}=" do |value| mobility_set(attribute, value) end if %i[accessor writer].include?(method) define_locale_accessors(attribute, @accessor_locales) if @accessor_locales end end |
Instance Attribute Details
#attributes ⇒ Array<String> (readonly)
Attributes for which accessors will be defined
100 101 102 |
# File 'lib/mobility/attributes.rb', line 100 def attributes @attributes end |
#backend_class ⇒ Class (readonly)
Backend class
108 109 110 |
# File 'lib/mobility/attributes.rb', line 108 def backend_class @backend_class end |
#backend_name ⇒ Symbol, Class (readonly)
Name of backend
112 113 114 |
# File 'lib/mobility/attributes.rb', line 112 def backend_name @backend_name end |
#options ⇒ Hash (readonly)
Backend options
104 105 106 |
# File 'lib/mobility/attributes.rb', line 104 def @options end |
Instance Method Details
#each {|String| ... } ⇒ Object
Yield each attribute to block
175 176 177 |
# File 'lib/mobility/attributes.rb', line 175 def each &block attributes.each &block end |
#included(model_class) ⇒ Object
Add this attributes module to shared Wrapper and setup model with backend setup block (see Backend::Setup#setup_model).
168 169 170 171 |
# File 'lib/mobility/attributes.rb', line 168 def included(model_class) model_class.mobility << self backend_class.setup_model(model_class, attributes, ) end |