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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +85 -64
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +61 -24
  5. data/lib/active_model.rb +21 -11
  6. data/lib/active_model/attribute_methods.rb +150 -125
  7. data/lib/active_model/callbacks.rb +49 -34
  8. data/lib/active_model/conversion.rb +39 -19
  9. data/lib/active_model/deprecated_mass_assignment_security.rb +21 -0
  10. data/lib/active_model/dirty.rb +48 -32
  11. data/lib/active_model/errors.rb +176 -88
  12. data/lib/active_model/forbidden_attributes_protection.rb +27 -0
  13. data/lib/active_model/lint.rb +42 -55
  14. data/lib/active_model/locale/en.yml +3 -1
  15. data/lib/active_model/model.rb +97 -0
  16. data/lib/active_model/naming.rb +191 -51
  17. data/lib/active_model/railtie.rb +11 -1
  18. data/lib/active_model/secure_password.rb +55 -25
  19. data/lib/active_model/serialization.rb +51 -27
  20. data/lib/active_model/serializers/json.rb +83 -46
  21. data/lib/active_model/serializers/xml.rb +46 -12
  22. data/lib/active_model/test_case.rb +0 -12
  23. data/lib/active_model/translation.rb +9 -10
  24. data/lib/active_model/validations.rb +154 -52
  25. data/lib/active_model/validations/absence.rb +31 -0
  26. data/lib/active_model/validations/acceptance.rb +10 -22
  27. data/lib/active_model/validations/callbacks.rb +78 -25
  28. data/lib/active_model/validations/clusivity.rb +41 -0
  29. data/lib/active_model/validations/confirmation.rb +13 -23
  30. data/lib/active_model/validations/exclusion.rb +26 -55
  31. data/lib/active_model/validations/format.rb +44 -34
  32. data/lib/active_model/validations/inclusion.rb +22 -52
  33. data/lib/active_model/validations/length.rb +48 -49
  34. data/lib/active_model/validations/numericality.rb +30 -32
  35. data/lib/active_model/validations/presence.rb +12 -22
  36. data/lib/active_model/validations/validates.rb +68 -36
  37. data/lib/active_model/validations/with.rb +28 -23
  38. data/lib/active_model/validator.rb +22 -22
  39. data/lib/active_model/version.rb +4 -4
  40. metadata +23 -24
  41. data/lib/active_model/mass_assignment_security.rb +0 -237
  42. data/lib/active_model/mass_assignment_security/permission_set.rb +0 -40
  43. data/lib/active_model/mass_assignment_security/sanitizer.rb +0 -59
  44. data/lib/active_model/observer_array.rb +0 -147
  45. 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
- options.merge(:attributes => attr_names.flatten)
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, "This record is invalid"
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, :on => :create
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>:if => :allow_validation</tt>,
57
- # or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The method,
58
- # proc or string should return or evaluate to a true or false value.
59
- # * <tt>:unless</tt> - Specifies a method, proc or string to call to determine
60
- # if the validation should not occur (e.g. <tt>:unless => :skip_validation</tt>,
61
- # or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The method,
62
- # proc or string should return or evaluate to a true or false value.
63
- # * <tt>:strict</tt> - Specifies whether validation should be strict.
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 <tt>options</tt>:
72
+ # to the class and available as +options+:
68
73
  #
69
74
  # class Person
70
75
  # include ActiveModel::Validations
71
- # validates_with MyValidator, :my_custom_key => "my custom value"
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, :on => :create
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 (:on, :if and :unless), which are
127
- # available on the class version of validates_with, should instead be
128
- # placed on the <tt>validates</tt> method as these are applied and tested
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 <tt>options</tt>, please refer to the
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 #:nodoc:
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 <tt>validate</tt> which accepts a <tt>record</tt>.
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 <tt>record</tt>'s errors directly
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>. For example:
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. Mrs. or Dr.' unless value.in?(['Mr.', 'Mrs.', 'Dr.'])
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, :presence => true
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. Examples:
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.wrap(options.delete(:attributes))
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
@@ -1,9 +1,9 @@
1
1
  module ActiveModel
2
2
  module VERSION #:nodoc:
3
- MAJOR = 3
4
- MINOR = 2
5
- TINY = 22
6
- PRE = "5"
3
+ MAJOR = 4
4
+ MINOR = 0
5
+ TINY = 0
6
+ PRE = "beta1"
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
9
9
  end
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: 3.2.22.5
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: 2016-09-14 00:00:00.000000000 Z
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: 3.2.22.5
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: 3.2.22.5
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.0.0
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.0.0
41
- description: A toolkit for building modeling frameworks like Active Record and Active
42
- Resource. Rich support for attributes, callbacks, validations, observers, serialization,
43
- internationalization, and testing.
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/mass_assignment_security.rb
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.8.7
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: '0'
104
+ version: 1.3.1
105
105
  requirements: []
106
106
  rubyforge_project:
107
- rubygems_version: 2.6.6
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