Class: ActiveModel::AttributeSet::Query
- Inherits:
- BasicObject
- Defined in:
- lib/attribute-filters/attribute_set_query.rb
Overview
This class contains proxy methods used to interact with AttributeSet instances. It’s responsible for all of the DSL magic that allows sweet constructs like:
some_attribute_set.all.present?
Direct Known Subclasses
Instance Method Summary collapse
-
#initialize(set_object, am_object = nil) ⇒ Query
constructor
Creates new query object.
-
#method_missing(method_sym, *args) { ... } ⇒ Object
This is a proxy method that causes some calls to be queued to for the next call.
-
#next_step(method_name, args, block) ⇒ AttributeSet
protected
Queues any method of the given name to be called when next query (method call) is made.
-
#values ⇒ Array
Gets values of attributes from current set.
-
#values_hash ⇒ Hash{String => Object}
Gets attribute names and their values for attributes from current set.
Constructor Details
#initialize(am_object) ⇒ AttributeSet::Query #initialize(set_object, am_object) ⇒ AttributeSet::Query
Creates new query object.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/attribute-filters/attribute_set_query.rb', line 30 def initialize(set_object, am_object = nil) if am_object.nil? am_object = set_object unless am_object.included_modules.include?(::ActiveModel::AttributeFilters) raise ::ArgumentError, "incompatible object passed to AttributeSet::Query (not a model class?)" end set_object = ::ActiveModel::AttributeSet.new end if set_object.is_a?(::Symbol) || set_object.is_a?(::String) # global set assigned to model class set_object = am_object.attribute_set_simple(set_object) # - duplicated in class method that gets a set elsif !set_object.nil? && !set_object.is_a?(::ActiveModel::AttributeSet) # any other object set_object = ::ActiveModel::AttributeSet.new(set_object) # - duplicated in AttributeSet initializer end @set_object = set_object # AttributeSet (assuming it's duplicated if needed) @am_object = am_object @next_method = nil end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_sym, *args) { ... } ⇒ Object
This is a proxy method that causes some calls to be queued to for the next call. Is allows to create semi-natural syntax when querying attribute sets.
When method_sym
is set to :all
or :any
then new query is created and the next method given in chain is passed to each element of the set with question mark added to its name.
Example:
some_attribute_set.all.present?
is converted to
some_attribute_set.all? { |atr| atr.present? }
When method_sym
is set to list
or show
then new query is constructed and the next method given in chain is passed to any element collected by applying select
to set.
Example:
some_attribute_set.list.present?
is converted to
some_attribute_set.select { |atr| atr.present? }
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 146 147 148 149 150 151 |
# File 'lib/attribute-filters/attribute_set_query.rb', line 76 def method_missing(method_sym, *args, &block) method_sym = method_sym.to_sym # set name as a method name if @set_object.nil? @set_object = @am_object.class.af_attribute_set(method_sym) return self end # neutral method case method_sym when :are, :is, :be, :should return self end # special selectors if @next_method.nil? case method_sym when :all, :any, :none, :one ::ActiveModel::AttributeSet::Query.new(@set_object, @am_object). # new obj. == thread-safe next_step(method_sym.to_s << "?", args, block) when :list, :show ::ActiveModel::AttributeSet::Query.new(@set_object, @am_object). next_step(:select, args, block) when :valid?, :is_valid?, :are_valid?, :all_valid?, :are_all_valid? self.all.valid? when :invalid?, :is_not_valid?, :any_invalid?, :are_not_valid?, :not_valid?, :is_any_invalid? self.any.invalid? when :changed?, :any_changed?, :have_changed?, :have_any_changed?, :is_any_changed?, :has_any_changed?, :has_changed? self.any.changed? when :unchanged?, :none_changed?, :nothing_changed?, :is_unchanged?, :are_all_unchanged?, :all_unchanged?, :havent_changed?, :arent_changed?, :are_not_changed?, :none_changed?, :not_changed? self.all.unchanged? else r = @set_object.public_method(method_sym).call(*args, &block) return r if r.respond_to?(:__in_as_proxy) || !r.is_a?(::ActiveModel::AttributeSet) ::ActiveModel::AttributeSet::Query.new(r, @am_object) end else n_m, n_args, n_block = @next_method @next_method = nil # m contains a method that we should call on a set of names (e.g. all? or any?) # method_sym contains a method to be called on each attribute from a set (e.g. present?) r = case method_sym when :valid? @am_object.valid? method_for_each_attr(n_m, *args) { |atr| not @am_object.errors.include?(atr.to_sym) } when :invalid? @am_object.valid? method_for_each_attr(n_m, *args) { |atr| @am_object.errors.include?(atr.to_sym) } when :changed? method_for_each_attr(n_m, *args) { |atr| @am_object.changes.key?(atr) } when :unchanged? method_for_each_attr(n_m, *args) { |atr| not @am_object.changes.key?(atr) } else @set_object.public_method(n_m).call(*n_args) do |atr| @am_object.public_send(atr).public_method(method_sym).call(*args, &block) end end return r if r.respond_to?(:__in_as_proxy) || !r.is_a?(::ActiveModel::AttributeSet) ::ActiveModel::AttributeSet::Query.new(r, @am_object) end end |
Instance Method Details
#next_step(method_name, args, block) ⇒ AttributeSet (protected)
Queues any method of the given name to be called when next query (method call) is made.
228 229 230 231 |
# File 'lib/attribute-filters/attribute_set_query.rb', line 228 def next_step(method_name, args, block) @next_method = [method_name, args, block] return self end |
#values ⇒ Array
Gets values of attributes from current set. If an attribute does not exist it puts nil
in its place.
197 198 199 200 201 202 203 204 |
# File 'lib/attribute-filters/attribute_set_query.rb', line 197 def values r = [] @am_object.for_each_attr_from_set(@set_object, :process_all, :process_blank, :no_presence_check, :include_missing) { |a| r << a } r end |
#values_hash ⇒ Hash{String => Object}
Gets attribute names and their values for attributes from current set. If an attribute does not exist it puts nil
as its value.
210 211 212 213 214 215 216 217 |
# File 'lib/attribute-filters/attribute_set_query.rb', line 210 def values_hash r = {} @am_object.for_each_attr_from_set(@set_object, :process_all, :process_blank, :no_presence_check, :include_missing) { |a, n| r[n] = a } r end |