activemodel 3.2.22.5 → 4.0.0.beta1

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