Class: ActiveModel::AttributeSet::AttrQuery

Inherits:
Query
  • Object
show all
Defined in:
lib/attribute-filters/attribute_set_attrquery.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:

the_attribute(:x).is.in_set?

Instance Method Summary collapse

Methods inherited from Query

#next_step, #values, #values_hash

Constructor Details

#initialize(attribute_name = nil, am_object = nil) ⇒ AttrQuery

Creates new query object.

Parameters:

  • set_object (AttributeSet)

    attribute set containing set names for which the query will be made

  • am_object (Object) (defaults to: nil)

    model object which has access to attributes (may be an instance of ActiveRecord or similar)

  • attribute_name (Sting, Symbol) (defaults to: nil)

    name of attribute the query is made for



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/attribute-filters/attribute_set_attrquery.rb', line 23

def initialize(attribute_name = nil, am_object = nil)
  if am_object.nil?
    am_object = attribute_name
    attribute_name = nil
    unless am_object.included_modules.include?(::ActiveModel::AttributeFilters)
      raise ::ArgumentError, "incompatible object passed to AttributeSet::AttrQuery (not a model class?)"
    end
  end
  @am_object = am_object
  @next_method = nil
  unless attribute_name.nil?
    @set_object = @am_object.class.filter_attribute(attribute_name)
    @attribute_name = attribute_name.to_s
  end
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 intercepted. Is allows to create semi-natural syntax when querying attribute sets containing set names.

When the called method name ends with question mark then its name is considered to be an attribute set name that should be tested for presence of the attribute. To use that syntax you have to be sure that there is no already defined method for AttributeSet object which name ends with question mark. Otherwise you may get false positives or a strange errors when trying to test if attribute belongs to a set. The real method call will override your check.

Examples:

the_attribute(:some_attribute).is.in?(:some_set)
the_attribute(:some_attribute).list.sets
the_attribute(:some_attribute).is.in.a.set.that?(:should_be_downcased)
the_attribute(:some_attribute).should_be_downcased?

Parameters:

  • method_sym (Symbol, String)

    name of method that will be queued or called on a set

  • args (Array)

    optional arguments to be passed to a method call

Yields:

  • optional block to be passed to a method call



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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
# File 'lib/attribute-filters/attribute_set_attrquery.rb', line 61

def method_missing(method_sym, *args, &block)
  method_sym = method_sym.to_sym

  if @attribute_name.nil?
    @attribute_name = method_sym.to_s
    @set_object = @am_object.class.filter_attribute(@attribute_name)
    return self
  end

  case method_sym
  when :are, :is, :one, :is_one, :in, :list, :be, :should,
       :the, :a, :sets, :in_sets, :set, :in_a_set, :in_set, :belongs_to
    self

  when :belongs_to?, :in?, :in_set?, :in_a_set?, :in_the_set?,
       :the_set?, :set?, :is_one_that?, :one_that?, :that?
    if args.present? && args.is_a?(::Array)
      args = args.map{ |a| a.to_sym if a.respond_to?(:to_sym) }
    end
    @set_object.include?(*args, &block)

  when :accessible?, :is_accessible?
    @am_object.class.accessible_attributes.include?(@attribute_name)

  when :inaccessible?, :is_inaccessible?
    @am_object.all_inaccessible_attributes.include?(@attribute_name)

  when :protected?, :is_protected?
    @am_object.class.protected_attributes.include?(@attribute_name)

  when :virtual?, :is_virtual?
    @am_object.class.attribute_filters_virtual.include?(@attribute_name)

  when :semi_real?, :is_semi_real?
    @am_object.class.treat_as_real.include?(@attribute_name)

  when :valid?, :is_valid?
    return false unless @am_object.send(:__all_attributes).include?(@attribute_name)
    return true if @am_object.valid?
    not @am_object.errors.has_key?(@attribute_name.to_sym)

  when :invalid?, :is_invalid?
    return true unless @am_object.send(:__all_attributes).include?(@attribute_name)
    return false if @am_object.valid?
    @am_object.errors.has_key?(@attribute_name.to_sym)

  when :changed?, :is_changed?, :has_changed?
    return false unless @am_object.changed? && @am_object.send(:__all_attributes).include?(@attribute_name)
    @am_object.changes.key?(@attribute_name)

  when :unchanged?, :is_unchanged?, :hasnt_changed?, :not_changed?
    return true unless @am_object.changed?
    @am_object.changes.key?(@attribute_name)

  else
    set_name_str = method_sym.to_s
    if !@set_object.respond_to?(method_sym) && set_name_str.slice!(/\?\z/) == '?'
      @set_object.include?(set_name_str.to_sym, &block)
    else
      @set_object.public_method(method_sym).call(*args, &block)
    end
  end
end

Instance Method Details

#valueObject

Gets value of current attribute. If the attribute does not exist it returns nil.

Returns:

  • (Object)

    the value of an attribute



129
130
131
# File 'lib/attribute-filters/attribute_set_attrquery.rb', line 129

def value
  @am_object.respond_to?(@attribute_name) ? @am_object.public_send(@attribute_name) : nil
end