activemodel 3.1.0.beta1 → 3.1.0.rc1
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.
- data/CHANGELOG +34 -1
- data/lib/active_model/conversion.rb +4 -4
- data/lib/active_model/mass_assignment_security.rb +23 -23
- data/lib/active_model/naming.rb +3 -2
- data/lib/active_model/observer_array.rb +44 -1
- data/lib/active_model/observing.rb +9 -6
- data/lib/active_model/serializers/xml.rb +2 -1
- data/lib/active_model/validations/length.rb +2 -2
- data/lib/active_model/validations/numericality.rb +0 -4
- data/lib/active_model/version.rb +1 -1
- metadata +4 -4
data/CHANGELOG
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
*Rails 3.1.0 (unreleased)*
|
2
2
|
|
3
|
+
* attr_accessible and friends now accepts :as as option to specify a role [Josh Kalderimis]
|
4
|
+
|
3
5
|
* Add support for proc or lambda as an option for InclusionValidator,
|
4
6
|
ExclusionValidator, and FormatValidator [Prem Sichanugrist]
|
5
7
|
|
@@ -13,8 +15,39 @@
|
|
13
15
|
|
14
16
|
* ActiveModel::AttributeMethods allows attributes to be defined on demand [Alexander Uvarov]
|
15
17
|
|
18
|
+
* Add support for selectively enabling/disabling observers [Myron Marston]
|
19
|
+
|
20
|
+
|
21
|
+
*Rails 3.0.7 (April 18, 2011)*
|
22
|
+
|
23
|
+
*No changes.
|
24
|
+
|
25
|
+
|
26
|
+
*Rails 3.0.6 (April 5, 2011)
|
27
|
+
|
28
|
+
* Fix when database column name has some symbolic characters (e.g. Oracle CASE# VARCHAR2(20)) #5818 #6850 [Robert Pankowecki, Santiago Pastorino]
|
29
|
+
|
30
|
+
* Fix length validation for fixnums #6556 [Andriy Tyurnikov]
|
31
|
+
|
32
|
+
* Fix i18n key collision with namespaced models #6448 [yves.senn]
|
33
|
+
|
34
|
+
|
35
|
+
*Rails 3.0.5 (February 26, 2011)*
|
36
|
+
|
37
|
+
* No changes.
|
38
|
+
|
39
|
+
|
40
|
+
*Rails 3.0.4 (February 8, 2011)*
|
41
|
+
|
42
|
+
* No changes.
|
43
|
+
|
44
|
+
|
45
|
+
*Rails 3.0.3 (November 16, 2010)*
|
46
|
+
|
47
|
+
* No changes.
|
48
|
+
|
16
49
|
|
17
|
-
*Rails 3.0.2 (
|
50
|
+
*Rails 3.0.2 (November 15, 2010)*
|
18
51
|
|
19
52
|
* No changes
|
20
53
|
|
@@ -21,8 +21,8 @@ module ActiveModel
|
|
21
21
|
#
|
22
22
|
module Conversion
|
23
23
|
# If your object is already designed to implement all of the Active Model
|
24
|
-
# you can use the default to_model implementation, which simply
|
25
|
-
# self.
|
24
|
+
# you can use the default <tt>:to_model</tt> implementation, which simply
|
25
|
+
# returns self.
|
26
26
|
#
|
27
27
|
# If your model does not act like an Active Model object, then you should
|
28
28
|
# define <tt>:to_model</tt> yourself returning a proxy object that wraps
|
@@ -35,13 +35,13 @@ module ActiveModel
|
|
35
35
|
# if the object is persisted or not.
|
36
36
|
#
|
37
37
|
# Note the default implementation uses persisted? just because all objects
|
38
|
-
# in Ruby 1.8.x responds to
|
38
|
+
# in Ruby 1.8.x responds to <tt>:id</tt>.
|
39
39
|
def to_key
|
40
40
|
persisted? ? [id] : nil
|
41
41
|
end
|
42
42
|
|
43
43
|
# Returns a string representing the object's key suitable for use in URLs,
|
44
|
-
# or nil if persisted
|
44
|
+
# or nil if <tt>persisted?</tt> is false.
|
45
45
|
def to_param
|
46
46
|
persisted? ? to_key.join('-') : nil
|
47
47
|
end
|
@@ -35,17 +35,17 @@ module ActiveModel
|
|
35
35
|
# protected
|
36
36
|
#
|
37
37
|
# def account_params
|
38
|
-
#
|
39
|
-
# sanitize_for_mass_assignment(params[:account],
|
38
|
+
# role = admin ? :admin : :default
|
39
|
+
# sanitize_for_mass_assignment(params[:account], role)
|
40
40
|
# end
|
41
41
|
#
|
42
42
|
# end
|
43
43
|
#
|
44
44
|
module ClassMethods
|
45
45
|
# Attributes named in this macro are protected from mass-assignment
|
46
|
-
# whenever attributes are sanitized before assignment. A
|
47
|
-
# attributes is optional, if no
|
48
|
-
# A
|
46
|
+
# whenever attributes are sanitized before assignment. A role for the
|
47
|
+
# attributes is optional, if no role is provided then :default is used.
|
48
|
+
# A role can be defined by using the :as option.
|
49
49
|
#
|
50
50
|
# Mass-assignment to these attributes will simply be ignored, to assign
|
51
51
|
# to them you can use direct writer methods. This is meant to protect
|
@@ -67,7 +67,7 @@ module ActiveModel
|
|
67
67
|
# end
|
68
68
|
# end
|
69
69
|
#
|
70
|
-
# When using
|
70
|
+
# When using the :default role :
|
71
71
|
#
|
72
72
|
# customer = Customer.new
|
73
73
|
# customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :default)
|
@@ -78,7 +78,7 @@ module ActiveModel
|
|
78
78
|
# customer.credit_rating = "Average"
|
79
79
|
# customer.credit_rating # => "Average"
|
80
80
|
#
|
81
|
-
# And using the :admin
|
81
|
+
# And using the :admin role :
|
82
82
|
#
|
83
83
|
# customer = Customer.new
|
84
84
|
# customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :admin)
|
@@ -93,10 +93,10 @@ module ActiveModel
|
|
93
93
|
# to sanitize attributes won't provide sufficient protection.
|
94
94
|
def attr_protected(*args)
|
95
95
|
options = args.extract_options!
|
96
|
-
|
96
|
+
role = options[:as] || :default
|
97
97
|
|
98
98
|
self._protected_attributes = protected_attributes_configs.dup
|
99
|
-
self._protected_attributes[
|
99
|
+
self._protected_attributes[role] = self.protected_attributes(role) + args
|
100
100
|
|
101
101
|
self._active_authorizer = self._protected_attributes
|
102
102
|
end
|
@@ -104,8 +104,8 @@ module ActiveModel
|
|
104
104
|
# Specifies a white list of model attributes that can be set via
|
105
105
|
# mass-assignment.
|
106
106
|
#
|
107
|
-
# Like +attr_protected+, a
|
108
|
-
# if no
|
107
|
+
# Like +attr_protected+, a role for the attributes is optional,
|
108
|
+
# if no role is provided then :default is used. A role can be defined by
|
109
109
|
# using the :as option.
|
110
110
|
#
|
111
111
|
# This is the opposite of the +attr_protected+ macro: Mass-assignment
|
@@ -131,7 +131,7 @@ module ActiveModel
|
|
131
131
|
# end
|
132
132
|
# end
|
133
133
|
#
|
134
|
-
# When using
|
134
|
+
# When using the :default role :
|
135
135
|
#
|
136
136
|
# customer = Customer.new
|
137
137
|
# customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :default)
|
@@ -141,7 +141,7 @@ module ActiveModel
|
|
141
141
|
# customer.credit_rating = "Average"
|
142
142
|
# customer.credit_rating # => "Average"
|
143
143
|
#
|
144
|
-
# And using the :admin
|
144
|
+
# And using the :admin role :
|
145
145
|
#
|
146
146
|
# customer = Customer.new
|
147
147
|
# customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :admin)
|
@@ -152,20 +152,20 @@ module ActiveModel
|
|
152
152
|
# to sanitize attributes won't provide sufficient protection.
|
153
153
|
def attr_accessible(*args)
|
154
154
|
options = args.extract_options!
|
155
|
-
|
155
|
+
role = options[:as] || :default
|
156
156
|
|
157
157
|
self._accessible_attributes = accessible_attributes_configs.dup
|
158
|
-
self._accessible_attributes[
|
158
|
+
self._accessible_attributes[role] = self.accessible_attributes(role) + args
|
159
159
|
|
160
160
|
self._active_authorizer = self._accessible_attributes
|
161
161
|
end
|
162
162
|
|
163
|
-
def protected_attributes(
|
164
|
-
protected_attributes_configs[
|
163
|
+
def protected_attributes(role = :default)
|
164
|
+
protected_attributes_configs[role]
|
165
165
|
end
|
166
166
|
|
167
|
-
def accessible_attributes(
|
168
|
-
accessible_attributes_configs[
|
167
|
+
def accessible_attributes(role = :default)
|
168
|
+
accessible_attributes_configs[role]
|
169
169
|
end
|
170
170
|
|
171
171
|
def active_authorizers
|
@@ -198,12 +198,12 @@ module ActiveModel
|
|
198
198
|
|
199
199
|
protected
|
200
200
|
|
201
|
-
def sanitize_for_mass_assignment(attributes,
|
202
|
-
mass_assignment_authorizer(
|
201
|
+
def sanitize_for_mass_assignment(attributes, role = :default)
|
202
|
+
mass_assignment_authorizer(role).sanitize(attributes)
|
203
203
|
end
|
204
204
|
|
205
|
-
def mass_assignment_authorizer(
|
206
|
-
self.class.active_authorizer[
|
205
|
+
def mass_assignment_authorizer(role = :default)
|
206
|
+
self.class.active_authorizer[role]
|
207
207
|
end
|
208
208
|
end
|
209
209
|
end
|
data/lib/active_model/naming.rb
CHANGED
@@ -7,8 +7,9 @@ module ActiveModel
|
|
7
7
|
attr_reader :singular, :plural, :element, :collection, :partial_path, :route_key, :param_key, :i18n_key
|
8
8
|
alias_method :cache_key, :collection
|
9
9
|
|
10
|
-
def initialize(klass, namespace = nil)
|
11
|
-
|
10
|
+
def initialize(klass, namespace = nil, name = nil)
|
11
|
+
name ||= klass.name
|
12
|
+
super(name)
|
12
13
|
@unnamespaced = self.sub(/^#{namespace.name}::/, '') if namespace
|
13
14
|
|
14
15
|
@klass = klass
|
@@ -2,7 +2,7 @@ require 'set'
|
|
2
2
|
|
3
3
|
module ActiveModel
|
4
4
|
# Stores the enabled/disabled state of individual observers for
|
5
|
-
# a particular model
|
5
|
+
# a particular model class.
|
6
6
|
class ObserverArray < Array
|
7
7
|
attr_reader :model_class
|
8
8
|
def initialize(model_class, *args)
|
@@ -10,14 +10,57 @@ module ActiveModel
|
|
10
10
|
super(*args)
|
11
11
|
end
|
12
12
|
|
13
|
+
# Returns true if the given observer is disabled for the model class.
|
13
14
|
def disabled_for?(observer)
|
14
15
|
disabled_observers.include?(observer.class)
|
15
16
|
end
|
16
17
|
|
18
|
+
# Disables one or more observers. This supports multiple forms:
|
19
|
+
#
|
20
|
+
# ORM.observers.disable :user_observer
|
21
|
+
# # => disables the UserObserver
|
22
|
+
#
|
23
|
+
# User.observers.disable AuditTrail
|
24
|
+
# # => disables the AuditTrail observer for User notifications.
|
25
|
+
# # Other models will still notify the AuditTrail observer.
|
26
|
+
#
|
27
|
+
# ORM.observers.disable :observer_1, :observer_2
|
28
|
+
# # => disables Observer1 and Observer2 for all models.
|
29
|
+
#
|
30
|
+
# ORM.observers.disable :all
|
31
|
+
# # => disables all observers for all models.
|
32
|
+
#
|
33
|
+
# User.observers.disable :all do
|
34
|
+
# # all user observers are disabled for
|
35
|
+
# # just the duration of the block
|
36
|
+
# end
|
17
37
|
def disable(*observers, &block)
|
18
38
|
set_enablement(false, observers, &block)
|
19
39
|
end
|
20
40
|
|
41
|
+
# Enables one or more observers. This supports multiple forms:
|
42
|
+
#
|
43
|
+
# ORM.observers.enable :user_observer
|
44
|
+
# # => enables the UserObserver
|
45
|
+
#
|
46
|
+
# User.observers.enable AuditTrail
|
47
|
+
# # => enables the AuditTrail observer for User notifications.
|
48
|
+
# # Other models will not be affected (i.e. they will not
|
49
|
+
# # trigger notifications to AuditTrail if previously disabled)
|
50
|
+
#
|
51
|
+
# ORM.observers.enable :observer_1, :observer_2
|
52
|
+
# # => enables Observer1 and Observer2 for all models.
|
53
|
+
#
|
54
|
+
# ORM.observers.enable :all
|
55
|
+
# # => enables all observers for all models.
|
56
|
+
#
|
57
|
+
# User.observers.enable :all do
|
58
|
+
# # all user observers are enabled for
|
59
|
+
# # just the duration of the block
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# Note: all observers are enabled by default. This method is only
|
63
|
+
# useful when you have previously disabled one or more observers.
|
21
64
|
def enable(*observers, &block)
|
22
65
|
set_enablement(true, observers, &block)
|
23
66
|
end
|
@@ -40,7 +40,11 @@ module ActiveModel
|
|
40
40
|
observers.replace(values.flatten)
|
41
41
|
end
|
42
42
|
|
43
|
-
# Gets
|
43
|
+
# Gets an array of observers observing this model.
|
44
|
+
# The array also provides +enable+ and +disable+ methods
|
45
|
+
# that allow you to selectively enable and disable observers.
|
46
|
+
# (see <tt>ActiveModel::ObserverArray.enable</tt> and
|
47
|
+
# <tt>ActiveModel::ObserverArray.disable</tt> for more on this)
|
44
48
|
def observers
|
45
49
|
@observers ||= ObserverArray.new(self)
|
46
50
|
end
|
@@ -67,9 +71,7 @@ module ActiveModel
|
|
67
71
|
|
68
72
|
# Notify list of observers of a change.
|
69
73
|
def notify_observers(*arg)
|
70
|
-
|
71
|
-
observer.update(*arg)
|
72
|
-
end
|
74
|
+
observer_instances.each { |observer| observer.update(*arg) }
|
73
75
|
end
|
74
76
|
|
75
77
|
# Total number of observers.
|
@@ -123,7 +125,7 @@ module ActiveModel
|
|
123
125
|
#
|
124
126
|
# class CommentObserver < ActiveModel::Observer
|
125
127
|
# def after_save(comment)
|
126
|
-
# Notifications.
|
128
|
+
# Notifications.comment("admin@do.com", "New comment was posted", comment).deliver
|
127
129
|
# end
|
128
130
|
# end
|
129
131
|
#
|
@@ -222,7 +224,8 @@ module ActiveModel
|
|
222
224
|
self.class.observed_classes
|
223
225
|
end
|
224
226
|
|
225
|
-
# Send observed_method(object) if the method exists
|
227
|
+
# Send observed_method(object) if the method exists and
|
228
|
+
# the observer is enabled for the given object's class.
|
226
229
|
def update(observed_method, object) #:nodoc:
|
227
230
|
return unless respond_to?(observed_method)
|
228
231
|
return if disabled_for?(object)
|
@@ -25,7 +25,7 @@ module ActiveModel
|
|
25
25
|
def decorations
|
26
26
|
decorations = {}
|
27
27
|
decorations[:encoding] = 'base64' if type == :binary
|
28
|
-
decorations[:type] = type
|
28
|
+
decorations[:type] = (type == :string) ? nil : type
|
29
29
|
decorations[:nil] = true if value.nil?
|
30
30
|
decorations
|
31
31
|
end
|
@@ -33,6 +33,7 @@ module ActiveModel
|
|
33
33
|
protected
|
34
34
|
|
35
35
|
def compute_type
|
36
|
+
return if value.nil?
|
36
37
|
type = ActiveSupport::XmlMini::TYPE_NAMES[value.class.name]
|
37
38
|
type ||= :string if value.respond_to?(:to_str)
|
38
39
|
type ||= :yaml
|
@@ -16,7 +16,7 @@ module ActiveModel
|
|
16
16
|
options[:maximum] -= 1 if range.exclude_end?
|
17
17
|
end
|
18
18
|
|
19
|
-
super
|
19
|
+
super
|
20
20
|
end
|
21
21
|
|
22
22
|
def check_validity!
|
@@ -36,7 +36,7 @@ module ActiveModel
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def validate_each(record, attribute, value)
|
39
|
-
value = options[:tokenizer].call(value) if value.kind_of?(String)
|
39
|
+
value = (options[:tokenizer] || DEFAULT_TOKENIZER).call(value) if value.kind_of?(String)
|
40
40
|
|
41
41
|
CHECKS.each do |key, validity_check|
|
42
42
|
next unless check_value = options[key]
|
@@ -9,10 +9,6 @@ module ActiveModel
|
|
9
9
|
|
10
10
|
RESERVED_OPTIONS = CHECKS.keys + [:only_integer]
|
11
11
|
|
12
|
-
def initialize(options)
|
13
|
-
super(options.reverse_merge(:only_integer => false, :allow_nil => false))
|
14
|
-
end
|
15
|
-
|
16
12
|
def check_validity!
|
17
13
|
keys = CHECKS.keys - [:odd, :even]
|
18
14
|
options.slice(*keys).each do |option, value|
|
data/lib/active_model/version.rb
CHANGED
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: activemodel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: 6
|
5
|
-
version: 3.1.0.
|
5
|
+
version: 3.1.0.rc1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- David Heinemeier Hansson
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-05-
|
13
|
+
date: 2011-05-21 00:00:00 -05:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
requirements:
|
22
22
|
- - "="
|
23
23
|
- !ruby/object:Gem::Version
|
24
|
-
version: 3.1.0.
|
24
|
+
version: 3.1.0.rc1
|
25
25
|
type: :runtime
|
26
26
|
version_requirements: *id001
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -127,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
127
127
|
version: 1.3.1
|
128
128
|
requirements: []
|
129
129
|
|
130
|
-
rubyforge_project:
|
130
|
+
rubyforge_project:
|
131
131
|
rubygems_version: 1.6.2
|
132
132
|
signing_key:
|
133
133
|
specification_version: 3
|