attribute-filters 1.3.2 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,98 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Author:: Paweł Wilk (mailto:pw@gnu.org)
4
+ # Copyright:: (c) 2012 by Paweł Wilk
5
+ # License:: This program is licensed under the terms of {file:LGPL-LICENSE GNU Lesser General Public License} or {file:COPYING Ruby License}.
6
+ #
7
+ # This file contains ActiveModel::AttributeFilters::Common::Join module
8
+ # containing ready-to-use filtering method.
9
+
10
+ # @abstract This namespace is shared with ActveModel.
11
+ module ActiveModel
12
+ module AttributeFilters
13
+ # This module contains common, ready-to-use filtering methods.
14
+ module Common
15
+ # Joins attributes.
16
+ module Join
17
+ extend CommonFilter
18
+
19
+ # Joins attributes and writes the results into other attribute.
20
+ #
21
+ # The attrubutes to be destination for joins are taken from the attribute set
22
+ # called +should_be_joined+.
23
+ #
24
+ # The pattern used to join a string and the optional separator argument
25
+ # should be set using the model's class method +join_attribute+.
26
+ def join_attributes
27
+ filter_attrs_from_set(:should_be_joined, :process_all, :process_blank) do |atr_val, atr_name, set_obj|
28
+ from, compact = set_obj.annotation(atr_name, :join_from, :join_compact)
29
+ if from.blank?
30
+ next atr_val if !atr_val.is_a?(Array)
31
+ from = [ atr_name ]
32
+ elsif !from.is_a?(Array)
33
+ from = [ from ]
34
+ end
35
+ vals = AttributeSet::Query.new(from, self).values
36
+ separator = set_obj.has_annotation?(atr_name, :join_separator) ?
37
+ set_obj.annotation(atr_name, :join_separator) : " "
38
+ if compact && vals.respond_to?(:compact)
39
+ vals.compact.join(separator)
40
+ elsif vals.respond_to?(:join)
41
+ vals.join(separator)
42
+ else
43
+ vals
44
+ end
45
+ end
46
+ end
47
+
48
+ # This submodule contains class methods needed to describe
49
+ # attribute joining.
50
+ module ClassMethods
51
+ # This method parametrizes joining operation for an attribute of the given name.
52
+ # It uses attribute set annotations to register parameters used when joining.
53
+ #
54
+ # @param atr_name [String,Symbol] attribute name
55
+ # @param parameters [Hash] parameters hash # fixme: add YARD parameters explained
56
+ # @return [void]
57
+ def join_attribute(atr_name, parameters = nil)
58
+ atr_name.is_a?(Hash) and return atr_name.each_pair { |k, v| join_attribute(k, v) }
59
+ if atr_name.is_a?(Array)
60
+ if parameters.is_a?(Symbol) || parameters.is_a?(String)
61
+ return join_attribute(parameters, atr_name)
62
+ elsif parameters.is_a?(Hash)
63
+ dst = parameters.delete(:into) || parameters.delete(:in) || parameters.delete(:destination)
64
+ if dst.nil?
65
+ raise ArgumentError, "you have to specify destination attribute using :into => 'attribute_name'"
66
+ end
67
+ parameters[:from] = atr_name
68
+ return join_attribute(dst, parameters)
69
+ end
70
+ end
71
+ parameters = { :from => parameters } unless parameters.is_a?(Hash)
72
+ the_attribute(atr_name, :should_be_joined)
73
+ a = {}
74
+ if parameters.key?(:with)
75
+ a[:join_separator] = parameters[:with]
76
+ elsif parameters.key?(:separator)
77
+ a[:join_separator] = parameters[:separator]
78
+ elsif parameters.key?(:join_separator)
79
+ a[:join_separator] = parameters[:join_separator]
80
+ end
81
+ from = parameters[:from] || parameters[:source] || parameters[:sources] || parameters[:join_from]
82
+ compact = parameters.key?(:compact) ? !!parameters[:compact] : !!parameters[:join_compact]
83
+ a.merge!({ :join_compact => compact, :join_from => from })
84
+ annotate_attributes_that(:should_be_joined, atr_name => a)
85
+ end
86
+ alias_method :join_attributes, :join_attribute
87
+ alias_method :joint_attribute, :join_attribute
88
+ alias_method :joint_attributes, :join_attribute
89
+ alias_method :join_attributes_to, :join_attribute
90
+ alias_method :join_attributes_into, :join_attribute
91
+ end # module ClassMethods
92
+ end # module Join
93
+
94
+ include Join
95
+
96
+ end # module Common
97
+ end # module AttributeFilters
98
+ end # module ActiveModel
@@ -0,0 +1,130 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Author:: Paweł Wilk (mailto:pw@gnu.org)
4
+ # Copyright:: (c) 2012 by Paweł Wilk
5
+ # License:: This program is licensed under the terms of {file:LGPL-LICENSE GNU Lesser General Public License} or {file:COPYING Ruby License}.
6
+ #
7
+ # This file contains ActiveModel::AttributeFilters::Common::Split module
8
+ # containing ready-to-use filtering method.
9
+
10
+ # @abstract This namespace is shared with ActveModel.
11
+ module ActiveModel
12
+ module AttributeFilters
13
+ # This module contains common, ready-to-use filtering methods.
14
+ module Common
15
+ # Splits attributes.
16
+ module Split
17
+ extend CommonFilter
18
+ # Splits attributes and writes the results into other attributes.
19
+ #
20
+ # The attrubutes to be splitted are taken from the attribute set
21
+ # called +should_be_splitted+. This method is safe to be
22
+ # used with multibyte strings (containing diacritics).
23
+ #
24
+ # The pattern used to split a string and the optional limit argument
25
+ # should be set using the model's class method +split_attribute+
26
+ # or directly with annotations.
27
+ def split_attributes
28
+ for_each_attr_from_set(:should_be_splitted) do |atr_val, atr_name, set_obj|
29
+ pattern, limit, flatten, into = set_obj.annotation(atr_name, :split_pattern, :split_limit,
30
+ :split_flatten, :split_into)
31
+ if limit.nil?
32
+ r = AttributeFiltersHelpers.each_element(atr_val, String) do |v|
33
+ v.mb_chars.split(pattern)
34
+ end
35
+ else
36
+ r = AttributeFiltersHelpers.each_element(atr_val, String) do |v|
37
+ v.mb_chars.split(pattern, limit)
38
+ end
39
+ end
40
+ r = [ r ] unless r.is_a?(Array)
41
+ r.flatten! if flatten
42
+
43
+ # writing collected slices
44
+ if into.blank?
45
+ public_send("#{atr_name}=", r)
46
+ else
47
+ into.each_with_index { |dst_atr, i| public_send("#{dst_atr}=", r[i]) }
48
+ end
49
+ end
50
+ end
51
+
52
+ # This submodule contains class methods needed to describe
53
+ # attribute splitting.
54
+ module ClassMethods
55
+ # This method parametrizes splitting operation for an attribute of the given name.
56
+ # It uses attribute set annotations to register parameters used when splitting.
57
+ #
58
+ # If the separator is not specified and the source attribute is a kind of +String+ then the default
59
+ # separator is applied, which is a whitespace character. You can change that by explicitly setting
60
+ # the separator to +nil+. In such case the split will occuch for each character. If there are more
61
+ # resulting parts then destination attributes then the redundant elements are ignored. If there is
62
+ # a limit given and there are more array elements than attributes then the filter behaves like
63
+ # puts leaves the redundant (unsplittable) and puts it into the last destination attribute.
64
+ #
65
+ # If the source attribute is an array then the filter will put each element of that array into each
66
+ # destination attribute. If there are more array elements than attributes then the reduntant elements
67
+ # are ignored.
68
+ #
69
+ # If the destination attributes are not given then the split filter will generate an array and replace
70
+ # currently processed attribute with an array.
71
+ #
72
+ # The pattern parameter (+:pattern+ when using +split_attributes+ class method or +:split_pattern+ when directly
73
+ # annotating attribute in a set) should be a string. If you would like to separate each character
74
+ # you have to set it to +nil+.
75
+ #
76
+ # @example
77
+ # class User < ActiveRecord::Base
78
+ # include ActiveModel::AttributeFilters::Common::Split
79
+ #
80
+ # attr_virtual :real_name
81
+ # attr_accessible :real_name
82
+ # split_attributes :real_name, :limit => 2, :into => [ :first_name, :last_name ], :pattern => ' '
83
+ # before_validation :split_attributes
84
+ # end
85
+ #
86
+ # @example
87
+ # class User < ActiveRecord::Base
88
+ # include ActiveModel::AttributeFilters::Common::Split
89
+ #
90
+ # attr_virtual :real_name
91
+ # attr_accessible :real_name
92
+ # attributes_that :should_be_splitted => { :real_name =>
93
+ # { :limit => 2,
94
+ # :into => [ :first_name, :last_name ],
95
+ # :pattern => ' ' } }
96
+ # before_validation :split_attributes
97
+ # end
98
+ #
99
+ # @param atr_name [String,Symbol] attribute name
100
+ # @param parameters [Hash] parameters hash # fixme: add YARD parameters explained
101
+ # @return [void]
102
+ def split_attribute(atr_name, parameters = nil)
103
+ atr_name.is_a?(Hash) and return atr_name.each_pair { |k, v| split_attribute(k, v) }
104
+ parameters = { :into => parameters } unless parameters.is_a?(Hash)
105
+ the_attribute(atr_name, :should_be_splitted)
106
+ pattern = parameters[:with] || parameters[:pattern] || parameters[:split_pattern]
107
+ into = parameters[:into] || parameters[:to] || parameters[:split_into]
108
+ limit = parameters[:limit] || parameters[:split_limit]
109
+ limit = limit.to_i unless limit.blank?
110
+ flatten = parameters[:flatten] || parameters[:split_flatten]
111
+ if into.blank?
112
+ into = nil
113
+ elsif !into.is_a?(Array)
114
+ into = into.respond_to?(:to_a) ? into.to_a : [ into ]
115
+ end
116
+ annotate_attributes_that(:should_be_splitted, atr_name => {
117
+ :split_flatten => flatten,
118
+ :split_pattern => pattern,
119
+ :split_limit => limit,
120
+ :split_into => into})
121
+ end
122
+ alias_method :split_attributes, :split_attribute
123
+ end # module ClassMethods
124
+ end # module Split
125
+
126
+ include Split
127
+
128
+ end # module Common
129
+ end # module AttributeFilters
130
+ end # module ActiveModel
@@ -0,0 +1,75 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Author:: Paweł Wilk (mailto:pw@gnu.org)
4
+ # Copyright:: (c) 2012 by Paweł Wilk
5
+ # License:: This program is licensed under the terms of {file:LGPL-LICENSE GNU Lesser General Public License} or {file:COPYING Ruby License}.
6
+ #
7
+ # This file contains ActiveModel::AttributeFilters::Common::Squeeze module
8
+ # containing ready-to-use filtering method.
9
+
10
+ # @abstract This namespace is shared with ActveModel.
11
+ module ActiveModel
12
+ module AttributeFilters
13
+ # This module contains common, ready-to-use filtering methods.
14
+ module Common
15
+ # Squeezes white characters in attributes.
16
+ module Squeeze
17
+ extend CommonFilter
18
+ # Squeezes white characters in attributes.
19
+ #
20
+ # The attrubutes to be squeezed are taken from the attribute set
21
+ # called +should_be_squeezed+. This method is safe to be
22
+ # used with multibyte strings (containing diacritics).
23
+ #
24
+ # @note If a value of currently processed attribute is an array
25
+ # then any element of the array is changed.
26
+ #
27
+ # @return [void]
28
+ def squeeze_attributes
29
+ filter_attrs_from_set(:should_be_squeezed) do |atr|
30
+ AttributeFiltersHelpers.each_element(atr, String) do |v|
31
+ v.mb_chars.squeeze.to_s
32
+ end
33
+ end
34
+ end
35
+ # This submodule contains class methods used to easily define filter.
36
+ module ClassMethods
37
+ # Registers attributes that should be squeezed.
38
+ def squeeze_attributes(*args)
39
+ attributes_that(:should_be_squeezed, args)
40
+ end
41
+ alias_method :squeeze_attribute, :squeeze_attributes
42
+ end # module ClassMethods
43
+
44
+ # Squeezes white characters in attributes, removes leading and trailing spaces and newlines.
45
+ #
46
+ # The attrubutes to be squished are taken from the attribute set
47
+ # called +should_be_squished+. This method is safe to be
48
+ # used with multibyte strings (containing diacritics).
49
+ #
50
+ # @note If a value of currently processed attribute is an array
51
+ # then any element of the array is changed.
52
+ #
53
+ # @return [void]
54
+ def squish_attributes
55
+ filter_attrs_from_set(:should_be_squished) do |atr|
56
+ AttributeFiltersHelpers.each_element(atr, String) do |v|
57
+ v.mb_chars.squish.to_s
58
+ end
59
+ end
60
+ end
61
+ # This submodule contains class methods used to easily define filter.
62
+ module ClassMethods
63
+ # Registers attributes that should be squished.
64
+ def squish_attributes(*args)
65
+ attributes_that(:should_be_squished, args)
66
+ end
67
+ alias_method :squish_attribute, :squish_attributes
68
+ end # module ClassMethods
69
+ end # module Squeeze
70
+
71
+ include Squeeze
72
+
73
+ end # module Common
74
+ end # module AttributeFilters
75
+ end # module ActiveModel
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Author:: Paweł Wilk (mailto:pw@gnu.org)
4
+ # Copyright:: (c) 2012 by Paweł Wilk
5
+ # License:: This program is licensed under the terms of {file:LGPL-LICENSE GNU Lesser General Public License} or {file:COPYING Ruby License}.
6
+ #
7
+ # This file contains ActiveModel::AttributeFilters::Common::Strip module
8
+ # containing ready-to-use filtering method.
9
+
10
+ # @abstract This namespace is shared with ActveModel.
11
+ module ActiveModel
12
+ module AttributeFilters
13
+ # This module contains common, ready-to-use filtering methods.
14
+ module Common
15
+ # Strips attributes from leading and trailing spaces.
16
+ module Strip
17
+ extend CommonFilter
18
+ # Strips attributes from leading and trailing spaces.
19
+ #
20
+ # The attrubutes to be stripped are taken from the attribute set called
21
+ # +should_be_stripped+. It operates directly on attribute's contents.
22
+ #
23
+ # @note If a value of currently processed attribute is an array
24
+ # then any element of the array is changed.
25
+ #
26
+ # @return [void]
27
+ def strip_attributes
28
+ filter_attrs_from_set(:should_be_stripped) do |atr|
29
+ AttributeFiltersHelpers.each_element(atr, String) { |v| v.strip }
30
+ end
31
+ end
32
+ # This submodule contains class methods used to easily define filter.
33
+ module ClassMethods
34
+ # Registers attributes that should be stripped.
35
+ def strip_attributes(*args)
36
+ attributes_that(:should_be_stripped, args)
37
+ end
38
+ alias_method :strip_attribute, :strip_attributes
39
+ end # module ClassMethods
40
+ end # module Strip
41
+
42
+ include Strip
43
+
44
+ end # module Common
45
+ end # module AttributeFilters
46
+ end # module ActiveModel
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Author:: Paweł Wilk (mailto:pw@gnu.org)
4
+ # Copyright:: (c) 2012 by Paweł Wilk
5
+ # License:: This program is licensed under the terms of {file:LGPL-LICENSE GNU Lesser General Public License} or {file:COPYING Ruby License}.
6
+ #
7
+ # This file contains attr_virtual DSL method that sets up setter, getter,
8
+ # and enables change tracking for vitual attrbutes.
9
+
10
+ # @abstract This namespace is shared with ActveModel.
11
+ module ActiveModel
12
+ module AttributeFilters
13
+ module ClassMethods
14
+
15
+ private
16
+
17
+ unless method_defined?(:attr_virtual)
18
+ # This method creates setter and getter for attributes of the given names
19
+ # and ensures that changes of their values are tracked.
20
+ #
21
+ # @note Placing +attr_writer+ with the same attribute name AFTER
22
+ # +attr_virtual+ will overwrite setter. Don't do that.
23
+ def attr_virtual(*attribute_names)
24
+ attribute_names.flatten.compact.uniq.each do |atr_name|
25
+ writer_name = "#{atr_name}="
26
+ atr_name = atr_name.to_sym
27
+ attr_reader(atr_name) unless method_defined?(atr_name)
28
+ attr_accessible(atr_name) if method_defined?(:attr_accessible)
29
+ if method_defined?(writer_name)
30
+ self.class_eval <<-EVAL
31
+ alias_method :#{atr_name}_without_change_tracking=, :#{writer_name}
32
+ def #{writer_name}(val)
33
+ attribute_will_change!('#{atr_name}') if val != '#{atr_name}'
34
+ #{atr_name}_without_change_tracking=(val)
35
+ end
36
+ EVAL
37
+ else
38
+ self.class_eval <<-EVAL
39
+ def #{writer_name}(val)
40
+ attribute_will_change!('#{atr_name}') if val != '#{atr_name}'
41
+ @#{atr_name} = val
42
+ end
43
+ EVAL
44
+ end
45
+ end
46
+ end # def attr_virtual
47
+ end # unless method_defined?(:attr_virtual)
48
+ end # module ClassMethods
49
+ end # module AttributeFilters
50
+ end # module ActiveModel
@@ -13,7 +13,8 @@ module ActiveModel
13
13
  PROCESSING_FLAGS = {
14
14
  :process_blank => false,
15
15
  :process_all => false,
16
- :no_presence_check => false
16
+ :no_presence_check => false,
17
+ :include_missing => false
17
18
  }.freeze
18
19
 
19
20
  # Gets names of attributes for which filters should be applied by
@@ -23,7 +24,7 @@ module ActiveModel
23
24
  # @overload attributes_to_filter(set_name, process_all, no_presence_check)
24
25
  # @param set_name [String,Symbol] name of a set of attributes used to get attributes
25
26
  # @param process_all [Boolean] if set then all the attributes from the attribute set are selected,
26
- # not just attributes that has changed (defaults to +false+)
27
+ # not just attributes that have changed (defaults to +false+)
27
28
  # @param no_presence_check [Boolean] if set then the checking whether attribute exists will be
28
29
  # disabled (matters only when +process_all+ is also set) (defaults to +false+)
29
30
  # @return [AttributeSet] set of attributes (attribute name => previous_value)
@@ -36,9 +37,9 @@ module ActiveModel
36
37
  # disabled (matters only when +process_all+ is also set) (defaults to +false+)
37
38
  # @return [AttributeSet] set of attributes (attribute name => previous_value)
38
39
  def attributes_to_filter(set_name, process_all = false, no_presence_check = false)
39
- atf = set_name.is_a?(::ActiveModel::AttributeSet) ? set_name : attribute_set(set_name)
40
+ atf = set_name.is_a?(::ActiveModel::AttributeSet) ? set_name : attribute_set_simple(set_name)
40
41
  if process_all
41
- no_presence_check ? atf : atf & (__vatrf(no_presence_check) + attributes.keys)
42
+ no_presence_check ? atf : atf & all_attributes_simple(no_presence_check)
42
43
  else
43
44
  if self.class.filter_virtual_attributes_that_changed?
44
45
  atf & changes.keys
@@ -66,17 +67,18 @@ module ActiveModel
66
67
  #
67
68
  # The result of the given block is used to set a new values for processed attributes.
68
69
  #
69
- # @param set_name [Symbol] name of the attribute set
70
+ # @param set_name [Symbol] name of the attribute set or a set object
70
71
  # @param args [Array] optional additional arguments that will be passed to the block
71
72
  # @param flags [Array<Symbol>] optional additional flags controlling the processing of attributes:
72
73
  # * +:process_blank+ – tells to also process attributes that are blank (empty or +nil+)
73
74
  # * +:process_all+ - tells to process all attributes, not just the ones that has changed
74
75
  # * +:no_presence_check+ – tells not to check for existence of each processed attribute when processing
75
- # all attributes; increases performance but you must care about putting into set only the existing attributes
76
+ # all attributes; increases performance but you must care about putting only the existing attributes into sets
76
77
  # @yield [attribute_value, set_name, attribute_name, *args] block that will be called for each attribute
77
78
  # @yieldparam attribute_value [Object] current attribute value that should be altered
79
+ # @yieldparam attribute_name [String] a name of currently processed attribute
80
+ # @yieldparam set_object [Object] currently processed set that attribute belongs to
78
81
  # @yieldparam set_name [Symbol] a name of the processed attribute set
79
- # @yieldparam attribute_name [Object] a name of currently processed attribute
80
82
  # @yieldparam args [Array] optional arguments passed to the method
81
83
  # @yieldreturn [Object] the result of calling the block
82
84
  # @return [void]
@@ -95,7 +97,7 @@ module ActiveModel
95
97
  #
96
98
  # end
97
99
  def filter_attrs_from_set(set_name, *args, &block)
98
- operate_on_attrs_from_set(set_name, true, *args, &block)
100
+ operate_on_attrs_from_set(set_name, true, *args, &block)
99
101
  end
100
102
  alias_method :attribute_filter_for_set, :filter_attrs_from_set
101
103
  alias_method :filter_attributes_which, :filter_attrs_from_set
@@ -131,17 +133,20 @@ module ActiveModel
131
133
  # method in a block or explicitly assign new, calculated value to the attribute
132
134
  # using its name (also passed to a block as one of arguments).
133
135
  #
134
- # @param set_name [Symbol] name of the attribute set
136
+ # @param set_name [Symbol] name of the attribute set or a set object
135
137
  # @param args [Array] optional additional arguments that will be passed to a block
136
138
  # @param flags [Array<Symbol>] optional additional flags controlling the processing of attributes:
137
139
  # * +:process_blank+ – tells to also process attributes that are blank (empty or +nil+)
138
140
  # * +:process_all+ - tells to process all attributes, not just the ones that has changed
139
141
  # * +:no_presence_check+ – tells not to check for existence of each processed attribute when processing
140
142
  # all attributes; increases performance but you must care about putting into set only the existing attributes
143
+ # * +:include_missing+ – includes attributes that does not exist in a resulting iteration (their values are
144
+ # always +nil+); has effect only when +process_blank+ and +no_presence_check+ are set to +true+
141
145
  # @yield [attribute_value, set_name, attribute_name, *args] block that will be called for each attribute
142
146
  # @yieldparam attribute_value [Object] current attribute value that should be altered
147
+ # @yieldparam attribute_name [String] a name of currently processed attribute
148
+ # @yieldparam set_object [Object] currently processed set that attribute belongs to
143
149
  # @yieldparam set_name [Symbol] a name of the processed attribute set
144
- # @yieldparam attribute_name [Object] a name of currently processed attribute
145
150
  # @yieldparam args [Array] optional arguments passed to the method
146
151
  # @yieldreturn [Object] the result of calling the block
147
152
  # @return [void]
@@ -200,6 +205,7 @@ module ActiveModel
200
205
  end
201
206
  alias_method :filter_virtual_attributes_that_changed, :filter_virtual_attributes_that_have_changed
202
207
  alias_method :filter_changed_virtual_attributes, :filter_virtual_attributes_that_have_changed
208
+ alias_method :virtual_attributes_are_tracked, :filter_virtual_attributes_that_have_changed
203
209
 
204
210
  # Gets the internal flag that causes to check virtual attributes
205
211
  # for changes when selecting attributes for filtering.
@@ -220,49 +226,54 @@ module ActiveModel
220
226
 
221
227
  # Applies operations to elements from set.
222
228
  def operate_on_attrs_from_set(set_name, alter_mode, *args, &block)
229
+ block_given? or return enum_for(__method__, set_name, alter_mode, *args)
223
230
  flags = AttributeFiltersHelpers.process_flags(args)
224
231
  process_all = flags[:process_all]
225
232
  process_blank = flags[:process_blank]
226
233
  no_presence_check = flags[:no_presence_check]
227
- attrs_to_process = attributes_to_filter(set_name, process_all, no_presence_check)
234
+ include_missing = flags[:include_missing]
235
+ if set_name.is_a?(::ActiveModel::AttributeSet)
236
+ set_obj = set_name
237
+ set_name = nil
238
+ else
239
+ set_obj = attribute_set_simple(set_name)
240
+ end
241
+ attrs_to_process = attributes_to_filter(set_obj, process_all, no_presence_check)
228
242
  if alter_mode
229
243
  if process_blank
230
244
  # filtering without testing for blank
231
245
  attrs_to_process.each do |atr|
232
- send("#{atr}=", yield(send(atr), set_name, atr, *args))
246
+ public_send("#{atr}=", yield(public_send(atr), atr, set_obj, set_name, *args))
233
247
  end
234
248
  else
235
249
  # filtering present only
236
250
  attrs_to_process.each do |atr|
237
- v = send(atr)
238
- send("#{atr}=", yield(v, set_name, atr, *args)) if v.present?
251
+ v = public_send(atr)
252
+ public_send("#{atr}=", yield(v, atr, set_obj, set_name, *args)) if v.present?
239
253
  end
240
254
  end
241
255
  else
242
256
  if process_blank
243
257
  # calling without testing for blank
244
- attrs_to_process.each do |atr|
245
- yield(send(atr), set_name, atr, *args)
258
+ if include_missing
259
+ # including missing attributes (changing them into nils)
260
+ attrs_to_process.each do |atr|
261
+ v = respond_to?(atr) ? public_send(atr) : nil
262
+ yield(v, atr, set_obj, set_name, *args)
263
+ end
264
+ else
265
+ attrs_to_process.each do |atr|
266
+ yield(public_send(atr), atr, set_obj, set_name, *args)
267
+ end
246
268
  end
247
269
  else
248
270
  # calling present only
249
271
  attrs_to_process.each do |atr|
250
- v = send(atr)
251
- yield(v, set_name, atr, *args) if v.present?
272
+ v = public_send(atr)
273
+ yield(v, atr, set_obj, set_name, *args) if v.present?
252
274
  end
253
275
  end
254
276
  end
255
277
  end
256
-
257
- private
258
-
259
- # Helper that collects virtual attributes that
260
- # have setters and getters.
261
- def __vatrf(no_presence_check = false)
262
- tar = self.class.send(:__treat_as_real)
263
- return tar if no_presence_check || tar.empty?
264
- tar.select { |a| respond_to?(a) && respond_to?("#{a}=") }
265
- end
266
-
267
278
  end # module AttributeFilters
268
279
  end # module ActiveModel