activemodel 3.2.22.5 → 4.0.0.beta1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +85 -64
- data/MIT-LICENSE +1 -1
- data/README.rdoc +61 -24
- data/lib/active_model.rb +21 -11
- data/lib/active_model/attribute_methods.rb +150 -125
- data/lib/active_model/callbacks.rb +49 -34
- data/lib/active_model/conversion.rb +39 -19
- data/lib/active_model/deprecated_mass_assignment_security.rb +21 -0
- data/lib/active_model/dirty.rb +48 -32
- data/lib/active_model/errors.rb +176 -88
- data/lib/active_model/forbidden_attributes_protection.rb +27 -0
- data/lib/active_model/lint.rb +42 -55
- data/lib/active_model/locale/en.yml +3 -1
- data/lib/active_model/model.rb +97 -0
- data/lib/active_model/naming.rb +191 -51
- data/lib/active_model/railtie.rb +11 -1
- data/lib/active_model/secure_password.rb +55 -25
- data/lib/active_model/serialization.rb +51 -27
- data/lib/active_model/serializers/json.rb +83 -46
- data/lib/active_model/serializers/xml.rb +46 -12
- data/lib/active_model/test_case.rb +0 -12
- data/lib/active_model/translation.rb +9 -10
- data/lib/active_model/validations.rb +154 -52
- data/lib/active_model/validations/absence.rb +31 -0
- data/lib/active_model/validations/acceptance.rb +10 -22
- data/lib/active_model/validations/callbacks.rb +78 -25
- data/lib/active_model/validations/clusivity.rb +41 -0
- data/lib/active_model/validations/confirmation.rb +13 -23
- data/lib/active_model/validations/exclusion.rb +26 -55
- data/lib/active_model/validations/format.rb +44 -34
- data/lib/active_model/validations/inclusion.rb +22 -52
- data/lib/active_model/validations/length.rb +48 -49
- data/lib/active_model/validations/numericality.rb +30 -32
- data/lib/active_model/validations/presence.rb +12 -22
- data/lib/active_model/validations/validates.rb +68 -36
- data/lib/active_model/validations/with.rb +28 -23
- data/lib/active_model/validator.rb +22 -22
- data/lib/active_model/version.rb +4 -4
- metadata +23 -24
- data/lib/active_model/mass_assignment_security.rb +0 -237
- data/lib/active_model/mass_assignment_security/permission_set.rb +0 -40
- data/lib/active_model/mass_assignment_security/sanitizer.rb +0 -59
- data/lib/active_model/observer_array.rb +0 -147
- data/lib/active_model/observing.rb +0 -252
@@ -3,12 +3,14 @@ module ActiveModel
|
|
3
3
|
module HelperMethods
|
4
4
|
private
|
5
5
|
def _merge_attributes(attr_names)
|
6
|
-
options = attr_names.extract_options
|
7
|
-
|
6
|
+
options = attr_names.extract_options!.symbolize_keys
|
7
|
+
attr_names.flatten!
|
8
|
+
options[:attributes] = attr_names
|
9
|
+
options
|
8
10
|
end
|
9
11
|
end
|
10
12
|
|
11
|
-
class WithValidator < EachValidator
|
13
|
+
class WithValidator < EachValidator # :nodoc:
|
12
14
|
def validate_each(record, attr, val)
|
13
15
|
method_name = options[:with]
|
14
16
|
|
@@ -32,7 +34,7 @@ module ActiveModel
|
|
32
34
|
# class MyValidator < ActiveModel::Validator
|
33
35
|
# def validate(record)
|
34
36
|
# if some_complex_logic
|
35
|
-
# record.errors.add :base,
|
37
|
+
# record.errors.add :base, 'This record is invalid'
|
36
38
|
# end
|
37
39
|
# end
|
38
40
|
#
|
@@ -46,29 +48,32 @@ module ActiveModel
|
|
46
48
|
#
|
47
49
|
# class Person
|
48
50
|
# include ActiveModel::Validations
|
49
|
-
# validates_with MyValidator, MyOtherValidator, :
|
51
|
+
# validates_with MyValidator, MyOtherValidator, on: :create
|
50
52
|
# end
|
51
53
|
#
|
52
54
|
# Configuration options:
|
53
55
|
# * <tt>:on</tt> - Specifies when this validation is active
|
54
|
-
# (<tt>:create</tt> or <tt>:update</tt
|
56
|
+
# (<tt>:create</tt> or <tt>:update</tt>.
|
55
57
|
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine
|
56
|
-
# if the validation should occur (e.g. <tt
|
57
|
-
# or <tt
|
58
|
-
# proc or string should return or evaluate to a true or
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
58
|
+
# if the validation should occur (e.g. <tt>if: :allow_validation</tt>,
|
59
|
+
# or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>).
|
60
|
+
# The method, proc or string should return or evaluate to a +true+ or
|
61
|
+
# +false+ value.
|
62
|
+
# * <tt>:unless</tt> - Specifies a method, proc or string to call to
|
63
|
+
# determine if the validation should not occur
|
64
|
+
# (e.g. <tt>unless: :skip_validation</tt>, or
|
65
|
+
# <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>).
|
66
|
+
# The method, proc or string should return or evaluate to a +true+ or
|
67
|
+
# +false+ value.
|
68
|
+
# * <tt>:strict</tt> - Specifies whether validation should be strict.
|
64
69
|
# See <tt>ActiveModel::Validation#validates!</tt> for more information.
|
65
|
-
|
70
|
+
#
|
66
71
|
# If you pass any additional configuration options, they will be passed
|
67
|
-
# to the class and available as
|
72
|
+
# to the class and available as +options+:
|
68
73
|
#
|
69
74
|
# class Person
|
70
75
|
# include ActiveModel::Validations
|
71
|
-
# validates_with MyValidator, :
|
76
|
+
# validates_with MyValidator, my_custom_key: 'my custom value'
|
72
77
|
# end
|
73
78
|
#
|
74
79
|
# class MyValidator < ActiveModel::Validator
|
@@ -116,20 +121,20 @@ module ActiveModel
|
|
116
121
|
# class Person
|
117
122
|
# include ActiveModel::Validations
|
118
123
|
#
|
119
|
-
# validate :instance_validations, :
|
124
|
+
# validate :instance_validations, on: :create
|
120
125
|
#
|
121
126
|
# def instance_validations
|
122
127
|
# validates_with MyValidator, MyOtherValidator
|
123
128
|
# end
|
124
129
|
# end
|
125
130
|
#
|
126
|
-
# Standard configuration options (
|
127
|
-
# available on the class version of
|
128
|
-
# placed on the
|
129
|
-
# in the callback.
|
131
|
+
# Standard configuration options (<tt>:on</tt>, <tt>:if</tt> and
|
132
|
+
# <tt>:unless</tt>), which are available on the class version of
|
133
|
+
# +validates_with+, should instead be placed on the +validates+ method
|
134
|
+
# as these are applied and tested in the callback.
|
130
135
|
#
|
131
136
|
# If you pass any additional configuration options, they will be passed
|
132
|
-
# to the class and available as
|
137
|
+
# to the class and available as +options+, please refer to the
|
133
138
|
# class version of this method for more information.
|
134
139
|
def validates_with(*args, &block)
|
135
140
|
options = args.extract_options!
|
@@ -1,11 +1,8 @@
|
|
1
|
-
require 'active_support/core_ext/array/wrap'
|
2
1
|
require "active_support/core_ext/module/anonymous"
|
3
|
-
require 'active_support/core_ext/object/blank'
|
4
|
-
require 'active_support/core_ext/object/inclusion'
|
5
2
|
|
6
|
-
module ActiveModel
|
3
|
+
module ActiveModel
|
7
4
|
|
8
|
-
# == Active Model Validator
|
5
|
+
# == Active \Model \Validator
|
9
6
|
#
|
10
7
|
# A simple base class that can be used along with
|
11
8
|
# ActiveModel::Validations::ClassMethods.validates_with
|
@@ -29,7 +26,7 @@ module ActiveModel #:nodoc:
|
|
29
26
|
# end
|
30
27
|
#
|
31
28
|
# Any class that inherits from ActiveModel::Validator must implement a method
|
32
|
-
# called
|
29
|
+
# called +validate+ which accepts a +record+.
|
33
30
|
#
|
34
31
|
# class Person
|
35
32
|
# include ActiveModel::Validations
|
@@ -43,8 +40,8 @@ module ActiveModel #:nodoc:
|
|
43
40
|
# end
|
44
41
|
# end
|
45
42
|
#
|
46
|
-
# To cause a validation error, you must add to the
|
47
|
-
# from within the validators message
|
43
|
+
# To cause a validation error, you must add to the +record+'s errors directly
|
44
|
+
# from within the validators message.
|
48
45
|
#
|
49
46
|
# class MyValidator < ActiveModel::Validator
|
50
47
|
# def validate(record)
|
@@ -63,29 +60,31 @@ module ActiveModel #:nodoc:
|
|
63
60
|
# end
|
64
61
|
# end
|
65
62
|
#
|
63
|
+
# Note that the validator is initialized only once for the whole application
|
64
|
+
# lifecycle, and not on each validation run.
|
65
|
+
#
|
66
66
|
# The easiest way to add custom validators for validating individual attributes
|
67
|
-
# is with the convenient <tt>ActiveModel::EachValidator</tt>.
|
67
|
+
# is with the convenient <tt>ActiveModel::EachValidator</tt>.
|
68
68
|
#
|
69
69
|
# class TitleValidator < ActiveModel::EachValidator
|
70
70
|
# def validate_each(record, attribute, value)
|
71
|
-
# record.errors.add attribute, 'must be Mr
|
71
|
+
# record.errors.add attribute, 'must be Mr., Mrs., or Dr.' unless %w(Mr. Mrs. Dr.).include?(value)
|
72
72
|
# end
|
73
73
|
# end
|
74
74
|
#
|
75
75
|
# This can now be used in combination with the +validates+ method
|
76
|
-
# (see <tt>ActiveModel::Validations::ClassMethods.validates</tt> for more on this)
|
76
|
+
# (see <tt>ActiveModel::Validations::ClassMethods.validates</tt> for more on this).
|
77
77
|
#
|
78
78
|
# class Person
|
79
79
|
# include ActiveModel::Validations
|
80
80
|
# attr_accessor :title
|
81
81
|
#
|
82
|
-
# validates :title, :
|
82
|
+
# validates :title, presence: true
|
83
83
|
# end
|
84
84
|
#
|
85
85
|
# Validator may also define a +setup+ instance method which will get called
|
86
86
|
# with the class that using that validator as its argument. This can be
|
87
|
-
# useful when there are prerequisites such as an +attr_accessor+ being present
|
88
|
-
# for example:
|
87
|
+
# useful when there are prerequisites such as an +attr_accessor+ being present.
|
89
88
|
#
|
90
89
|
# class MyValidator < ActiveModel::Validator
|
91
90
|
# def setup(klass)
|
@@ -95,25 +94,26 @@ module ActiveModel #:nodoc:
|
|
95
94
|
#
|
96
95
|
# This setup method is only called when used with validation macros or the
|
97
96
|
# class level <tt>validates_with</tt> method.
|
98
|
-
#
|
99
97
|
class Validator
|
100
98
|
attr_reader :options
|
101
99
|
|
102
|
-
# Returns the kind of the validator.
|
100
|
+
# Returns the kind of the validator.
|
103
101
|
#
|
104
102
|
# PresenceValidator.kind # => :presence
|
105
103
|
# UniquenessValidator.kind # => :uniqueness
|
106
|
-
#
|
107
104
|
def self.kind
|
108
105
|
@kind ||= name.split('::').last.underscore.sub(/_validator$/, '').to_sym unless anonymous?
|
109
106
|
end
|
110
107
|
|
111
108
|
# Accepts options that will be made available through the +options+ reader.
|
112
|
-
def initialize(options)
|
109
|
+
def initialize(options = {})
|
113
110
|
@options = options.freeze
|
114
111
|
end
|
115
112
|
|
116
113
|
# Return the kind for this validator.
|
114
|
+
#
|
115
|
+
# PresenceValidator.new.kind # => :presence
|
116
|
+
# UniquenessValidator.new.kind # => :uniqueness
|
117
117
|
def kind
|
118
118
|
self.class.kind
|
119
119
|
end
|
@@ -130,15 +130,15 @@ module ActiveModel #:nodoc:
|
|
130
130
|
# record, attribute and value.
|
131
131
|
#
|
132
132
|
# All Active Model validations are built on top of this validator.
|
133
|
-
class EachValidator < Validator
|
133
|
+
class EachValidator < Validator #:nodoc:
|
134
134
|
attr_reader :attributes
|
135
135
|
|
136
136
|
# Returns a new validator instance. All options will be available via the
|
137
137
|
# +options+ reader, however the <tt>:attributes</tt> option will be removed
|
138
138
|
# and instead be made available through the +attributes+ reader.
|
139
139
|
def initialize(options)
|
140
|
-
@attributes = Array
|
141
|
-
raise ":attributes cannot be blank" if @attributes.empty?
|
140
|
+
@attributes = Array(options.delete(:attributes))
|
141
|
+
raise ArgumentError, ":attributes cannot be blank" if @attributes.empty?
|
142
142
|
super
|
143
143
|
check_validity!
|
144
144
|
end
|
@@ -169,7 +169,7 @@ module ActiveModel #:nodoc:
|
|
169
169
|
|
170
170
|
# +BlockValidator+ is a special +EachValidator+ which receives a block on initialization
|
171
171
|
# and call this block for each attribute being validated. +validates_each+ uses this validator.
|
172
|
-
class BlockValidator < EachValidator
|
172
|
+
class BlockValidator < EachValidator #:nodoc:
|
173
173
|
def initialize(options, &block)
|
174
174
|
@block = block
|
175
175
|
super
|
data/lib/active_model/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activemodel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2013-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,31 +16,31 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 4.0.0.beta1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 4.0.0.beta1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: builder
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 3.
|
33
|
+
version: 3.1.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 3.
|
41
|
-
description: A toolkit for building modeling frameworks like Active Record
|
42
|
-
|
43
|
-
|
40
|
+
version: 3.1.0
|
41
|
+
description: A toolkit for building modeling frameworks like Active Record. Rich support
|
42
|
+
for attributes, callbacks, validations, observers, serialization, internationalization,
|
43
|
+
and testing.
|
44
44
|
email: david@loudthinking.com
|
45
45
|
executables: []
|
46
46
|
extensions: []
|
@@ -49,20 +49,17 @@ files:
|
|
49
49
|
- CHANGELOG.md
|
50
50
|
- MIT-LICENSE
|
51
51
|
- README.rdoc
|
52
|
-
- lib/active_model.rb
|
53
52
|
- lib/active_model/attribute_methods.rb
|
54
53
|
- lib/active_model/callbacks.rb
|
55
54
|
- lib/active_model/conversion.rb
|
55
|
+
- lib/active_model/deprecated_mass_assignment_security.rb
|
56
56
|
- lib/active_model/dirty.rb
|
57
57
|
- lib/active_model/errors.rb
|
58
|
+
- lib/active_model/forbidden_attributes_protection.rb
|
58
59
|
- lib/active_model/lint.rb
|
59
60
|
- lib/active_model/locale/en.yml
|
60
|
-
- lib/active_model/
|
61
|
-
- lib/active_model/mass_assignment_security/permission_set.rb
|
62
|
-
- lib/active_model/mass_assignment_security/sanitizer.rb
|
61
|
+
- lib/active_model/model.rb
|
63
62
|
- lib/active_model/naming.rb
|
64
|
-
- lib/active_model/observer_array.rb
|
65
|
-
- lib/active_model/observing.rb
|
66
63
|
- lib/active_model/railtie.rb
|
67
64
|
- lib/active_model/secure_password.rb
|
68
65
|
- lib/active_model/serialization.rb
|
@@ -70,9 +67,10 @@ files:
|
|
70
67
|
- lib/active_model/serializers/xml.rb
|
71
68
|
- lib/active_model/test_case.rb
|
72
69
|
- lib/active_model/translation.rb
|
73
|
-
- lib/active_model/validations.rb
|
70
|
+
- lib/active_model/validations/absence.rb
|
74
71
|
- lib/active_model/validations/acceptance.rb
|
75
72
|
- lib/active_model/validations/callbacks.rb
|
73
|
+
- lib/active_model/validations/clusivity.rb
|
76
74
|
- lib/active_model/validations/confirmation.rb
|
77
75
|
- lib/active_model/validations/exclusion.rb
|
78
76
|
- lib/active_model/validations/format.rb
|
@@ -82,8 +80,10 @@ files:
|
|
82
80
|
- lib/active_model/validations/presence.rb
|
83
81
|
- lib/active_model/validations/validates.rb
|
84
82
|
- lib/active_model/validations/with.rb
|
83
|
+
- lib/active_model/validations.rb
|
85
84
|
- lib/active_model/validator.rb
|
86
85
|
- lib/active_model/version.rb
|
86
|
+
- lib/active_model.rb
|
87
87
|
homepage: http://www.rubyonrails.org
|
88
88
|
licenses:
|
89
89
|
- MIT
|
@@ -94,19 +94,18 @@ require_paths:
|
|
94
94
|
- lib
|
95
95
|
required_ruby_version: !ruby/object:Gem::Requirement
|
96
96
|
requirements:
|
97
|
-
- -
|
97
|
+
- - '>='
|
98
98
|
- !ruby/object:Gem::Version
|
99
|
-
version: 1.
|
99
|
+
version: 1.9.3
|
100
100
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
101
|
requirements:
|
102
|
-
- -
|
102
|
+
- - '>'
|
103
103
|
- !ruby/object:Gem::Version
|
104
|
-
version:
|
104
|
+
version: 1.3.1
|
105
105
|
requirements: []
|
106
106
|
rubyforge_project:
|
107
|
-
rubygems_version: 2.
|
107
|
+
rubygems_version: 2.0.0
|
108
108
|
signing_key:
|
109
109
|
specification_version: 4
|
110
110
|
summary: A toolkit for building modeling frameworks (part of Rails).
|
111
111
|
test_files: []
|
112
|
-
has_rdoc:
|
@@ -1,237 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/class/attribute'
|
2
|
-
require 'active_support/core_ext/string/inflections'
|
3
|
-
require 'active_support/core_ext/array/wrap'
|
4
|
-
require 'active_model/mass_assignment_security/permission_set'
|
5
|
-
require 'active_model/mass_assignment_security/sanitizer'
|
6
|
-
|
7
|
-
module ActiveModel
|
8
|
-
# = Active Model Mass-Assignment Security
|
9
|
-
module MassAssignmentSecurity
|
10
|
-
extend ActiveSupport::Concern
|
11
|
-
|
12
|
-
included do
|
13
|
-
class_attribute :_accessible_attributes
|
14
|
-
class_attribute :_protected_attributes
|
15
|
-
class_attribute :_active_authorizer
|
16
|
-
|
17
|
-
class_attribute :_mass_assignment_sanitizer
|
18
|
-
self.mass_assignment_sanitizer = :logger
|
19
|
-
end
|
20
|
-
|
21
|
-
# Mass assignment security provides an interface for protecting attributes
|
22
|
-
# from end-user assignment. For more complex permissions, mass assignment security
|
23
|
-
# may be handled outside the model by extending a non-ActiveRecord class,
|
24
|
-
# such as a controller, with this behavior.
|
25
|
-
#
|
26
|
-
# For example, a logged in user may need to assign additional attributes depending
|
27
|
-
# on their role:
|
28
|
-
#
|
29
|
-
# class AccountsController < ApplicationController
|
30
|
-
# include ActiveModel::MassAssignmentSecurity
|
31
|
-
#
|
32
|
-
# attr_accessible :first_name, :last_name
|
33
|
-
# attr_accessible :first_name, :last_name, :plan_id, :as => :admin
|
34
|
-
#
|
35
|
-
# def update
|
36
|
-
# ...
|
37
|
-
# @account.update_attributes(account_params)
|
38
|
-
# ...
|
39
|
-
# end
|
40
|
-
#
|
41
|
-
# protected
|
42
|
-
#
|
43
|
-
# def account_params
|
44
|
-
# role = admin ? :admin : :default
|
45
|
-
# sanitize_for_mass_assignment(params[:account], role)
|
46
|
-
# end
|
47
|
-
#
|
48
|
-
# end
|
49
|
-
#
|
50
|
-
# = Configuration options
|
51
|
-
#
|
52
|
-
# * <tt>mass_assignment_sanitizer</tt> - Defines sanitize method. Possible values are:
|
53
|
-
# * <tt>:logger</tt> (default) - writes filtered attributes to logger
|
54
|
-
# * <tt>:strict</tt> - raise <tt>ActiveModel::MassAssignmentSecurity::Error</tt> on any protected attribute update
|
55
|
-
#
|
56
|
-
# You can specify your own sanitizer object eg. MySanitizer.new.
|
57
|
-
# See <tt>ActiveModel::MassAssignmentSecurity::LoggerSanitizer</tt> for example implementation.
|
58
|
-
#
|
59
|
-
#
|
60
|
-
module ClassMethods
|
61
|
-
# Attributes named in this macro are protected from mass-assignment
|
62
|
-
# whenever attributes are sanitized before assignment. A role for the
|
63
|
-
# attributes is optional, if no role is provided then :default is used.
|
64
|
-
# A role can be defined by using the :as option.
|
65
|
-
#
|
66
|
-
# Mass-assignment to these attributes will simply be ignored, to assign
|
67
|
-
# to them you can use direct writer methods. This is meant to protect
|
68
|
-
# sensitive attributes from being overwritten by malicious users
|
69
|
-
# tampering with URLs or forms. Example:
|
70
|
-
#
|
71
|
-
# class Customer
|
72
|
-
# include ActiveModel::MassAssignmentSecurity
|
73
|
-
#
|
74
|
-
# attr_accessor :name, :credit_rating
|
75
|
-
#
|
76
|
-
# attr_protected :credit_rating, :last_login
|
77
|
-
# attr_protected :last_login, :as => :admin
|
78
|
-
#
|
79
|
-
# def assign_attributes(values, options = {})
|
80
|
-
# sanitize_for_mass_assignment(values, options[:as]).each do |k, v|
|
81
|
-
# send("#{k}=", v)
|
82
|
-
# end
|
83
|
-
# end
|
84
|
-
# end
|
85
|
-
#
|
86
|
-
# When using the :default role:
|
87
|
-
#
|
88
|
-
# customer = Customer.new
|
89
|
-
# customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :default)
|
90
|
-
# customer.name # => "David"
|
91
|
-
# customer.credit_rating # => nil
|
92
|
-
# customer.last_login # => nil
|
93
|
-
#
|
94
|
-
# customer.credit_rating = "Average"
|
95
|
-
# customer.credit_rating # => "Average"
|
96
|
-
#
|
97
|
-
# And using the :admin role:
|
98
|
-
#
|
99
|
-
# customer = Customer.new
|
100
|
-
# customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :admin)
|
101
|
-
# customer.name # => "David"
|
102
|
-
# customer.credit_rating # => "Excellent"
|
103
|
-
# customer.last_login # => nil
|
104
|
-
#
|
105
|
-
# To start from an all-closed default and enable attributes as needed,
|
106
|
-
# have a look at +attr_accessible+.
|
107
|
-
#
|
108
|
-
# Note that using <tt>Hash#except</tt> or <tt>Hash#slice</tt> in place of
|
109
|
-
# +attr_protected+ to sanitize attributes provides basically the same
|
110
|
-
# functionality, but it makes a bit tricky to deal with nested attributes.
|
111
|
-
def attr_protected(*args)
|
112
|
-
options = args.extract_options!
|
113
|
-
role = options[:as] || :default
|
114
|
-
|
115
|
-
self._protected_attributes = protected_attributes_configs.dup
|
116
|
-
|
117
|
-
Array.wrap(role).each do |name|
|
118
|
-
self._protected_attributes[name] = self.protected_attributes(name) + args
|
119
|
-
end
|
120
|
-
|
121
|
-
self._active_authorizer = self._protected_attributes
|
122
|
-
end
|
123
|
-
|
124
|
-
# Specifies a white list of model attributes that can be set via
|
125
|
-
# mass-assignment.
|
126
|
-
#
|
127
|
-
# Like +attr_protected+, a role for the attributes is optional,
|
128
|
-
# if no role is provided then :default is used. A role can be defined by
|
129
|
-
# using the :as option.
|
130
|
-
#
|
131
|
-
# This is the opposite of the +attr_protected+ macro: Mass-assignment
|
132
|
-
# will only set attributes in this list, to assign to the rest of
|
133
|
-
# attributes you can use direct writer methods. This is meant to protect
|
134
|
-
# sensitive attributes from being overwritten by malicious users
|
135
|
-
# tampering with URLs or forms. If you'd rather start from an all-open
|
136
|
-
# default and restrict attributes as needed, have a look at
|
137
|
-
# +attr_protected+.
|
138
|
-
#
|
139
|
-
# class Customer
|
140
|
-
# include ActiveModel::MassAssignmentSecurity
|
141
|
-
#
|
142
|
-
# attr_accessor :name, :credit_rating
|
143
|
-
#
|
144
|
-
# attr_accessible :name
|
145
|
-
# attr_accessible :name, :credit_rating, :as => :admin
|
146
|
-
#
|
147
|
-
# def assign_attributes(values, options = {})
|
148
|
-
# sanitize_for_mass_assignment(values, options[:as]).each do |k, v|
|
149
|
-
# send("#{k}=", v)
|
150
|
-
# end
|
151
|
-
# end
|
152
|
-
# end
|
153
|
-
#
|
154
|
-
# When using the :default role:
|
155
|
-
#
|
156
|
-
# customer = Customer.new
|
157
|
-
# customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :default)
|
158
|
-
# customer.name # => "David"
|
159
|
-
# customer.credit_rating # => nil
|
160
|
-
#
|
161
|
-
# customer.credit_rating = "Average"
|
162
|
-
# customer.credit_rating # => "Average"
|
163
|
-
#
|
164
|
-
# And using the :admin role:
|
165
|
-
#
|
166
|
-
# customer = Customer.new
|
167
|
-
# customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :admin)
|
168
|
-
# customer.name # => "David"
|
169
|
-
# customer.credit_rating # => "Excellent"
|
170
|
-
#
|
171
|
-
# Note that using <tt>Hash#except</tt> or <tt>Hash#slice</tt> in place of
|
172
|
-
# +attr_accessible+ to sanitize attributes provides basically the same
|
173
|
-
# functionality, but it makes a bit tricky to deal with nested attributes.
|
174
|
-
def attr_accessible(*args)
|
175
|
-
options = args.extract_options!
|
176
|
-
role = options[:as] || :default
|
177
|
-
|
178
|
-
self._accessible_attributes = accessible_attributes_configs.dup
|
179
|
-
|
180
|
-
Array.wrap(role).each do |name|
|
181
|
-
self._accessible_attributes[name] = self.accessible_attributes(name) + args
|
182
|
-
end
|
183
|
-
|
184
|
-
self._active_authorizer = self._accessible_attributes
|
185
|
-
end
|
186
|
-
|
187
|
-
def protected_attributes(role = :default)
|
188
|
-
protected_attributes_configs[role]
|
189
|
-
end
|
190
|
-
|
191
|
-
def accessible_attributes(role = :default)
|
192
|
-
accessible_attributes_configs[role]
|
193
|
-
end
|
194
|
-
|
195
|
-
def active_authorizers
|
196
|
-
self._active_authorizer ||= protected_attributes_configs
|
197
|
-
end
|
198
|
-
alias active_authorizer active_authorizers
|
199
|
-
|
200
|
-
def attributes_protected_by_default
|
201
|
-
[]
|
202
|
-
end
|
203
|
-
|
204
|
-
def mass_assignment_sanitizer=(value)
|
205
|
-
self._mass_assignment_sanitizer = if value.is_a?(Symbol)
|
206
|
-
const_get(:"#{value.to_s.camelize}Sanitizer").new(self)
|
207
|
-
else
|
208
|
-
value
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
private
|
213
|
-
|
214
|
-
def protected_attributes_configs
|
215
|
-
self._protected_attributes ||= begin
|
216
|
-
Hash.new { |h,k| h[k] = BlackList.new(attributes_protected_by_default) }
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
def accessible_attributes_configs
|
221
|
-
self._accessible_attributes ||= begin
|
222
|
-
Hash.new { |h,k| h[k] = WhiteList.new }
|
223
|
-
end
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
protected
|
228
|
-
|
229
|
-
def sanitize_for_mass_assignment(attributes, role = nil)
|
230
|
-
_mass_assignment_sanitizer.sanitize(attributes, mass_assignment_authorizer(role))
|
231
|
-
end
|
232
|
-
|
233
|
-
def mass_assignment_authorizer(role)
|
234
|
-
self.class.active_authorizer[role || :default]
|
235
|
-
end
|
236
|
-
end
|
237
|
-
end
|