Class: Mobility::Attributes
- Inherits:
-
Module
- Object
- Module
- Mobility::Attributes
- Defined in:
- lib/mobility/attributes.rb
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("title", backend: :my_backend, locale_accessors: [:en, :ja], cache: true, fallbacks: true)
will generate an anonymous module that behaves like this:
Module.new do
def title_backend
# Create a subclass of Mobility::Backends::MyBackend and include in it:
# - Mobility::Plugins::Cache (from the +cache: true+ option)
# - Mobility::Plugins::Fallbacks (from the +fallbacks: true+ option)
# - Mobility::Plugins::Presence (by default, disabled by +presence: false+)
# 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 thus add the backend method, the
reader, writer and presence methods, and the locale accessor so the model
class. (These methods are in fact added to the model in an included hook.)
==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 Backends::KeyValue and
Backends::Table backends.
The setup block is also used to extend the query scope/dataset (+i18n+ by
default) 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
-
#backend_class ⇒ Class
readonly
Backend class.
-
#backend_name ⇒ Symbol, Class
readonly
Name of backend.
-
#method ⇒ Symbol
readonly
Method (accessor, reader or writer).
-
#model_class ⇒ Class
readonly
Model class.
-
#names ⇒ Array<String>
readonly
Attribute names for which accessors will be defined.
-
#options ⇒ Hash
readonly
Backend options.
Instance Method Summary collapse
-
#each {|Attribute| ... } ⇒ Object
Yield each attribute name to block.
-
#included(klass) ⇒ Object
Setup backend class, include modules into model class, add this attributes module to shared Wrapper and setup model with backend setup block (see Backend::Setup#setup_model).
-
#initialize(*attribute_names, method: :accessor, backend: Mobility.default_backend, **backend_options) ⇒ Attributes
constructor
A new instance of Attributes.
Constructor Details
#initialize(*attribute_names, method: :accessor, backend: Mobility.default_backend, **backend_options) ⇒ Attributes
Returns a new instance of Attributes.
131 132 133 134 135 136 137 138 |
# File 'lib/mobility/attributes.rb', line 131 def initialize(*attribute_names, method: :accessor, backend: Mobility.default_backend, **) raise ArgumentError, "method must be one of: reader, writer, accessor" unless %i[reader writer accessor].include?(method) @method = method @options = Mobility..merge() @names = attribute_names.map(&:to_s) raise Mobility::BackendRequired, "Backend option required if Mobility.config.default_backend is not set." if backend.nil? @backend_name = backend end |
Instance Attribute Details
#backend_class ⇒ Class (readonly)
Backend class
116 117 118 |
# File 'lib/mobility/attributes.rb', line 116 def backend_class @backend_class end |
#backend_name ⇒ Symbol, Class (readonly)
Name of backend
120 121 122 |
# File 'lib/mobility/attributes.rb', line 120 def backend_name @backend_name end |
#method ⇒ Symbol (readonly)
Method (accessor, reader or writer)
104 105 106 |
# File 'lib/mobility/attributes.rb', line 104 def method @method end |
#model_class ⇒ Class (readonly)
Model class
124 125 126 |
# File 'lib/mobility/attributes.rb', line 124 def model_class @model_class end |
#names ⇒ Array<String> (readonly)
Attribute names for which accessors will be defined
108 109 110 |
# File 'lib/mobility/attributes.rb', line 108 def names @names end |
#options ⇒ Hash (readonly)
Backend options
112 113 114 |
# File 'lib/mobility/attributes.rb', line 112 def @options end |
Instance Method Details
#each {|Attribute| ... } ⇒ Object
Yield each attribute name to block
167 168 169 |
# File 'lib/mobility/attributes.rb', line 167 def each &block names.each(&block) end |
#included(klass) ⇒ Object
Setup backend class, include modules into model class, add this attributes module to shared Wrapper and setup model with backend setup block (see Backend::Setup#setup_model).
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 144 def included(klass) @model_class = @options[:model_class] = klass @backend_class = Class.new(get_backend_class(backend_name).for(model_class)) @backend_class.configure() if @backend_class.respond_to?(:configure) Mobility.plugins.each do |name| plugin = get_plugin_class(name) plugin.apply(self, [name]) end names.each do |name| define_backend(name) define_reader(name) if %i[accessor reader].include?(method) define_writer(name) if %i[accessor writer].include?(method) end model_class.mobility << self backend_class.setup_model(model_class, names, ) end |