attribute-filters 1.3.2 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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