protected_attributes_continued 1.2.3 → 1.6.0
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 +5 -5
- data/LICENSE.txt +1 -1
- data/README.md +62 -24
- data/lib/active_model/mass_assignment_security.rb +1 -5
- data/lib/active_record/mass_assignment_security.rb +0 -4
- data/lib/active_record/mass_assignment_security/associations.rb +33 -16
- data/lib/active_record/mass_assignment_security/core.rb +16 -0
- data/lib/active_record/mass_assignment_security/inheritance.rb +30 -7
- data/lib/active_record/mass_assignment_security/nested_attributes.rb +18 -8
- data/lib/active_record/mass_assignment_security/relation.rb +32 -3
- data/lib/protected_attributes.rb +0 -1
- data/lib/protected_attributes/version.rb +1 -1
- data/lib/protected_attributes_continued.rb +0 -18
- metadata +26 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b10566280e992ec0bc867ca4d2c0b52f29c9e7b98aa197f523bc7e8930634197
|
4
|
+
data.tar.gz: b98a820d98f4828e5cd9a94ee96d8072112548b964576cdfab74a73c3660daa1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a57bc937ec7efe500d594ffdf3200b51265c7ff0e1dd14e5188d43a0495840b55728168585da2cc5bba5f1b4fb8cf769e83391eeca6118089251ce7b31012974
|
7
|
+
data.tar.gz: e0933854f707e6a810103bd49f3001dd3eecceeb4c08cbca3c69b0c5d7d3758884026c7da594833b3a3eb957dd8a372ff8e68e442680485e0b35388b68aff046
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,25 +1,26 @@
|
|
1
1
|
# Protected Attributes Continued
|
2
|
+
<a href="https://badge.fury.io/rb/protected_attributes_continued" target="_blank"><img height="21" style='border:0px;height:21px;' border='0' src="https://badge.fury.io/rb/protected_attributes_continued.svg" alt="Gem Version"></a>
|
3
|
+
<a href='https://travis-ci.com/westonganger/protected_attributes_continued' target='_blank'><img height='21' style='border:0px;height:21px;' src='https://api.travis-ci.org/westonganger/protected_attributes_continued.svg?branch=master' border='0' alt='Build Status' /></a>
|
4
|
+
<a href='https://rubygems.org/gems/protected_attributes_continued' target='_blank'><img height='21' style='border:0px;height:21px;' src='https://ruby-gem-downloads-badge.herokuapp.com/protected_attributes_continued?label=rubygems&type=total&total_label=downloads&color=brightgreen' border='0' alt='RubyGems Downloads' /></a>
|
2
5
|
|
3
|
-
|
4
|
-
|
5
|
-
This is the community continued version of `protected_attributes`. I have created this new repo and changed the name because the Rails team refuses to support the `protected_attributes` gem for Rails 5. For people who would like to continue using this feature in their Rails 5 apps lets continue here. I am currently_using this successfully in number of Rails 5 production apps.
|
6
|
-
|
7
|
-
Protect attributes from mass-assignment in Active Record models.
|
8
|
-
|
9
|
-
This plugin adds the class methods `attr_accessible` and `attr_protected` to your models to be able to declare white or black lists of attributes.
|
10
|
-
|
6
|
+
> This is the community continued version of `protected_attributes` for Rails 5+. I recommend you only use it to support legacy portions of your application that you do not want to upgrade. The Rails team dropped this feature and switched to `strong_parameters` because of security issues. However some applications simply cannot be upgraded or security like this is a non-issue. To continue supporting this feature going forward lets continue the work here.
|
11
7
|
|
8
|
+
Protect attributes from mass-assignment in Active Record models. This gem adds the class methods `attr_accessible` and `attr_protected` to declare white or black lists of attributes.
|
12
9
|
|
13
10
|
|
14
11
|
## Installation
|
15
12
|
|
16
13
|
Add this line to your application's `Gemfile`:
|
17
14
|
|
18
|
-
|
15
|
+
```ruby
|
16
|
+
gem 'protected_attributes_continued'
|
17
|
+
```
|
19
18
|
|
20
19
|
And then execute:
|
21
20
|
|
22
|
-
|
21
|
+
```ruby
|
22
|
+
bundle install
|
23
|
+
```
|
23
24
|
|
24
25
|
## Usage
|
25
26
|
|
@@ -32,19 +33,19 @@ attr_protected :admin
|
|
32
33
|
`attr_protected` also optionally takes a role option using `:as` which allows you to define multiple mass-assignment groupings. If no role is defined then attributes will be added to the `:default` role.
|
33
34
|
|
34
35
|
```ruby
|
35
|
-
attr_protected :last_login, :
|
36
|
+
attr_protected :last_login, as: :admin
|
36
37
|
```
|
37
38
|
A much better way, because it follows the whitelist-principle, is the `attr_accessible` method. It is the exact opposite of `attr_protected`, because it takes a list of attributes that will be mass-assigned if present. Any other attributes will be ignored. This way you won’t forget to protect attributes when adding new ones in the course of development. Here is an example:
|
38
39
|
|
39
40
|
```ruby
|
40
41
|
attr_accessible :name
|
41
|
-
attr_accessible :name, :is_admin, :
|
42
|
+
attr_accessible :name, :is_admin, as: :admin
|
42
43
|
```
|
43
44
|
|
44
45
|
If you want to set a protected attribute, you will have to assign it individually:
|
45
46
|
|
46
47
|
```ruby
|
47
|
-
params[:user] # => {:
|
48
|
+
params[:user] # => {name: "owned", is_admin: true}
|
48
49
|
@user = User.new(params[:user])
|
49
50
|
@user.is_admin # => false, not mass-assigned
|
50
51
|
@user.is_admin = true
|
@@ -58,15 +59,15 @@ You can also bypass mass-assignment security by using the `:without_protection`
|
|
58
59
|
```ruby
|
59
60
|
@user = User.new
|
60
61
|
|
61
|
-
@user.assign_attributes(:
|
62
|
+
@user.assign_attributes(name: 'Josh', is_admin: true)
|
62
63
|
@user.name # => Josh
|
63
64
|
@user.is_admin # => false
|
64
65
|
|
65
|
-
@user.assign_attributes({ :
|
66
|
+
@user.assign_attributes({ name: 'Josh', is_admin: true }, as: :admin)
|
66
67
|
@user.name # => Josh
|
67
68
|
@user.is_admin # => true
|
68
69
|
|
69
|
-
@user.assign_attributes({ :
|
70
|
+
@user.assign_attributes({ name: 'Josh', is_admin: true }, without_protection: true)
|
70
71
|
@user.name # => Josh
|
71
72
|
@user.is_admin # => true
|
72
73
|
```
|
@@ -74,18 +75,18 @@ You can also bypass mass-assignment security by using the `:without_protection`
|
|
74
75
|
In a similar way, `new`, `create`, `create!`, `update_attributes` and `update_attributes!` methods all respect mass-assignment security and accept either `:as` or `:without_protection` options. For example:
|
75
76
|
|
76
77
|
```ruby
|
77
|
-
@user = User.new({ :
|
78
|
+
@user = User.new({ name: 'Sebastian', is_admin: true }, as: :admin)
|
78
79
|
@user.name # => Sebastian
|
79
80
|
@user.is_admin # => true
|
80
81
|
|
81
|
-
@user = User.create({ :
|
82
|
+
@user = User.create({ name: 'Sebastian', is_admin: true }, without_protection: true)
|
82
83
|
@user.name # => Sebastian
|
83
84
|
@user.is_admin # => true
|
84
85
|
```
|
85
86
|
|
86
87
|
By default the gem will use the strong parameters protection when assigning attribute, unless your model has `attr_accessible` or `attr_protected` calls.
|
87
88
|
|
88
|
-
|
89
|
+
## Errors
|
89
90
|
|
90
91
|
By default, attributes in the params hash which are not allowed to be updated are just ignored. If you prefer an exception to be raised configure:
|
91
92
|
|
@@ -97,8 +98,45 @@ Any protected attributes violation raises `ActiveModel::MassAssignmentSecurity::
|
|
97
98
|
|
98
99
|
## Contributing
|
99
100
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
101
|
+
We use the `appraisal` gem for testing multiple versions of `Rails`. Please use the following steps to test using `appraisal`.
|
102
|
+
|
103
|
+
1. `bundle exec appraisal install`
|
104
|
+
2. `bundle exec appraisal rake test`
|
105
|
+
|
106
|
+
## Credits
|
107
|
+
|
108
|
+
Created & Maintained by [Weston Ganger](https://westonganger.com) - [@westonganger](https://github.com/westonganger)
|
109
|
+
|
110
|
+
Originally forked from the dead/unmaintained `protected_attributes` gem by the Rails team.
|
111
|
+
|
112
|
+
## A Simple and Similar strong_params Alternative
|
113
|
+
|
114
|
+
While I do utilize this gem in some legacy projects. The latest approach I have adopted is similar to this gem but only utilizes Rails built-in `strong_params` which is a much more future proof way of doing things. The following is an example implementation.
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
### Model
|
118
|
+
class Post < ActiveRecord::Base
|
119
|
+
def self.strong_params(params)
|
120
|
+
params.permit(:post).permit(:name, :content, :published_at)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
### Controller
|
125
|
+
class PostsController < ApplicationController
|
126
|
+
def create
|
127
|
+
@post = Post.new(Post.strong_params(params))
|
128
|
+
|
129
|
+
@post.save
|
130
|
+
|
131
|
+
respond_with @post
|
132
|
+
end
|
133
|
+
|
134
|
+
def update
|
135
|
+
@post = Post.find(params[:id])
|
136
|
+
|
137
|
+
@post.update(Post.strong_params(params))
|
138
|
+
|
139
|
+
respond_with @post
|
140
|
+
end
|
141
|
+
end
|
142
|
+
```
|
@@ -323,11 +323,7 @@ module ActiveModel
|
|
323
323
|
# customer.assign_attributes(name: 'David')
|
324
324
|
# # => StandardError: StandardError
|
325
325
|
def mass_assignment_sanitizer=(value)
|
326
|
-
self._mass_assignment_sanitizer =
|
327
|
-
const_get(:"#{value.to_s.camelize}Sanitizer").new(self)
|
328
|
-
else
|
329
|
-
value
|
330
|
-
end
|
326
|
+
self._mass_assignment_sanitizer = value.is_a?(Symbol) ? const_get(:"#{value.to_s.camelize}Sanitizer").new(self) : value
|
331
327
|
end
|
332
328
|
|
333
329
|
private
|
@@ -1,9 +1,5 @@
|
|
1
1
|
require "active_record"
|
2
2
|
|
3
|
-
def active_record_40?
|
4
|
-
ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 0
|
5
|
-
end
|
6
|
-
|
7
3
|
require "active_record/mass_assignment_security/associations"
|
8
4
|
require "active_record/mass_assignment_security/attribute_assignment"
|
9
5
|
require "active_record/mass_assignment_security/core"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
### Original Rails Code - https://github.com/rails/rails/tree/master/activerecord/lib/active_record/associations
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Associations
|
3
5
|
class Association
|
@@ -5,11 +7,11 @@ module ActiveRecord
|
|
5
7
|
|
6
8
|
def build_record(attributes, options)
|
7
9
|
reflection.build_association(attributes, options) do |record|
|
8
|
-
|
10
|
+
the_scope = (ActiveRecord::VERSION::STRING.to_f >= 5.2 ? scope_for_create : create_scope)
|
11
|
+
attributes = the_scope.except(*(record.changed - [reflection.foreign_key]))
|
9
12
|
record.assign_attributes(attributes, without_protection: true)
|
10
13
|
end
|
11
14
|
end
|
12
|
-
|
13
15
|
private :build_record
|
14
16
|
end
|
15
17
|
|
@@ -52,7 +54,6 @@ module ActiveRecord
|
|
52
54
|
end
|
53
55
|
end
|
54
56
|
end
|
55
|
-
|
56
57
|
private :create_record
|
57
58
|
end
|
58
59
|
|
@@ -75,26 +76,41 @@ module ActiveRecord
|
|
75
76
|
end
|
76
77
|
|
77
78
|
module ThroughAssociation
|
78
|
-
|
79
|
+
### Cant use respond_to?(method, true) because its a module instead of a class
|
80
|
+
undef :build_record if self.private_instance_methods.include?(:build_record)
|
81
|
+
def build_record(attributes, options={})
|
82
|
+
inverse = source_reflection.inverse_of
|
83
|
+
target = through_association.target
|
79
84
|
|
80
|
-
|
85
|
+
if inverse && target && !target.is_a?(Array)
|
86
|
+
attributes[inverse.foreign_key] = target.id
|
87
|
+
end
|
81
88
|
|
82
|
-
|
83
|
-
|
84
|
-
|
89
|
+
super(attributes, options)
|
90
|
+
end
|
91
|
+
private :build_record
|
92
|
+
end
|
85
93
|
|
86
|
-
|
87
|
-
|
94
|
+
class HasManyThroughAssociation
|
95
|
+
if ActiveRecord.version >= Gem::Version.new('5.2.3')
|
96
|
+
undef :build_through_record
|
97
|
+
def build_through_record(record)
|
98
|
+
@through_records[record.object_id] ||= begin
|
99
|
+
ensure_mutable
|
100
|
+
|
101
|
+
attributes = through_scope_attributes
|
102
|
+
attributes[source_reflection.name] = record
|
103
|
+
attributes[source_reflection.foreign_type] = options[:source_type] if options[:source_type]
|
104
|
+
|
105
|
+
# Pass in `without_protection: true` here because `options_for_through_record`
|
106
|
+
# was removed in https://github.com/rails/rails/pull/35799
|
107
|
+
through_association.build(attributes, without_protection: true)
|
88
108
|
end
|
89
|
-
|
90
|
-
super(attributes, options)
|
91
109
|
end
|
92
|
-
|
110
|
+
private :build_through_record
|
111
|
+
end
|
93
112
|
|
94
|
-
class HasManyThroughAssociation
|
95
113
|
undef :build_record
|
96
|
-
undef :options_for_through_record if respond_to?(:options_for_through_record, false)
|
97
|
-
|
98
114
|
def build_record(attributes, options = {})
|
99
115
|
ensure_not_nested
|
100
116
|
|
@@ -113,6 +129,7 @@ module ActiveRecord
|
|
113
129
|
end
|
114
130
|
private :build_record
|
115
131
|
|
132
|
+
undef :options_for_through_record if respond_to?(:options_for_through_record, true)
|
116
133
|
def options_for_through_record
|
117
134
|
[through_scope_attributes, without_protection: true]
|
118
135
|
end
|
@@ -2,6 +2,21 @@ module ActiveRecord
|
|
2
2
|
module MassAssignmentSecurity
|
3
3
|
module Core
|
4
4
|
|
5
|
+
def initialize(attributes = nil, options = {})
|
6
|
+
@new_record = true
|
7
|
+
self.class.define_attribute_methods
|
8
|
+
@attributes = self.class._default_attributes.deep_dup
|
9
|
+
|
10
|
+
init_internals
|
11
|
+
initialize_internals_callback
|
12
|
+
|
13
|
+
# +options+ argument is only needed to make protected_attributes gem easier to hook.
|
14
|
+
init_attributes(attributes, options) if attributes
|
15
|
+
|
16
|
+
yield self if block_given?
|
17
|
+
_run_initialize_callbacks
|
18
|
+
end
|
19
|
+
|
5
20
|
private
|
6
21
|
|
7
22
|
def init_attributes(attributes, options)
|
@@ -12,6 +27,7 @@ module ActiveRecord
|
|
12
27
|
super
|
13
28
|
@mass_assignment_options = nil
|
14
29
|
end
|
30
|
+
|
15
31
|
end
|
16
32
|
end
|
17
33
|
end
|
@@ -4,18 +4,41 @@ module ActiveRecord
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
module ClassMethods
|
7
|
-
|
7
|
+
|
8
|
+
private
|
9
|
+
|
8
10
|
# Detect the subclass from the inheritance column of attrs. If the inheritance column value
|
9
11
|
# is not self or a valid subclass, raises ActiveRecord::SubclassNotFound
|
10
|
-
|
11
|
-
# this will ignore the inheritance column and return nil
|
12
|
-
def subclass_from_attributes?(attrs)
|
12
|
+
def subclass_from_attributes(attrs)
|
13
13
|
active_authorizer[:default].deny?(inheritance_column) ? nil : super
|
14
14
|
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
15
19
|
|
16
|
-
|
17
|
-
|
18
|
-
|
20
|
+
module ActiveRecord
|
21
|
+
module Inheritance
|
22
|
+
module ClassMethods
|
23
|
+
undef :new
|
24
|
+
|
25
|
+
def new(attributes = nil, options = {}, &block)
|
26
|
+
if abstract_class? || self == Base
|
27
|
+
raise NotImplementedError, "#{self} is an abstract class and cannot be instantiated."
|
28
|
+
end
|
29
|
+
|
30
|
+
if has_attribute?(inheritance_column)
|
31
|
+
subclass = subclass_from_attributes(attributes)
|
32
|
+
|
33
|
+
if respond_to?(:column_defaults) && subclass.nil? && base_class == self
|
34
|
+
subclass = subclass_from_attributes(column_defaults)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
if subclass && subclass != self
|
39
|
+
subclass.new(attributes, options, &block)
|
40
|
+
else
|
41
|
+
super
|
19
42
|
end
|
20
43
|
end
|
21
44
|
end
|
@@ -15,7 +15,7 @@ module ActiveRecord
|
|
15
15
|
|
16
16
|
attr_names.each do |association_name|
|
17
17
|
if reflection = reflect_on_association(association_name)
|
18
|
-
if
|
18
|
+
if ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 0
|
19
19
|
reflection.options[:autosave] = true
|
20
20
|
else
|
21
21
|
reflection.autosave = true
|
@@ -28,7 +28,7 @@ module ActiveRecord
|
|
28
28
|
|
29
29
|
type = (reflection.collection? ? :collection : :one_to_one)
|
30
30
|
|
31
|
-
generated_methods_module =
|
31
|
+
generated_methods_module = (ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 0) ? generated_feature_methods : generated_association_methods
|
32
32
|
|
33
33
|
# def pirate_attributes=(attributes)
|
34
34
|
# assign_nested_attributes_for_one_to_one_association(:pirate, attributes, mass_assignment_options)
|
@@ -54,10 +54,16 @@ module ActiveRecord
|
|
54
54
|
|
55
55
|
def assign_nested_attributes_for_one_to_one_association(association_name, attributes, assignment_opts = {})
|
56
56
|
options = self.nested_attributes_options[association_name]
|
57
|
+
|
58
|
+
if attributes.class.name == 'ActionController::Parameters'
|
59
|
+
attributes = attributes.to_unsafe_h
|
60
|
+
elsif !attributes.is_a?(Hash) && !attributes.is_a?(Array)
|
61
|
+
raise ArgumentError, "ActionController::Parameters or Hash or Array expected, got #{attributes.class.name} (#{attributes.inspect})"
|
62
|
+
end
|
63
|
+
|
57
64
|
attributes = attributes.with_indifferent_access
|
58
65
|
|
59
|
-
if
|
60
|
-
(options[:update_only] || record.id.to_s == attributes['id'].to_s)
|
66
|
+
if (options[:update_only] || !attributes['id'].blank?) && (record = send(association_name)) && (options[:update_only] || record.id.to_s == attributes['id'].to_s)
|
61
67
|
assign_to_or_mark_for_destruction(record, attributes, options[:allow_destroy], assignment_opts) unless call_reject_if(association_name, attributes)
|
62
68
|
|
63
69
|
elsif attributes['id'].present? && !assignment_opts[:without_protection]
|
@@ -76,11 +82,9 @@ module ActiveRecord
|
|
76
82
|
def assign_nested_attributes_for_collection_association(association_name, attributes_collection, assignment_opts = {})
|
77
83
|
options = self.nested_attributes_options[association_name]
|
78
84
|
|
79
|
-
|
80
|
-
|
81
|
-
if class_name == 'ActionController::Parameters'
|
85
|
+
if attributes_collection.class.name == 'ActionController::Parameters'
|
82
86
|
attributes_collection = attributes_collection.to_unsafe_h
|
83
|
-
elsif !
|
87
|
+
elsif !attributes_collection.is_a?(Hash) && !attributes_collection.is_a?(Array)
|
84
88
|
raise ArgumentError, "ActionController::Parameters or Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
|
85
89
|
end
|
86
90
|
|
@@ -118,6 +122,12 @@ module ActiveRecord
|
|
118
122
|
end
|
119
123
|
|
120
124
|
attributes_collection.each do |attributes|
|
125
|
+
if attributes.class.name == 'ActionController::Parameters'
|
126
|
+
attributes = attributes.to_unsafe_h
|
127
|
+
elsif !attributes.is_a?(Hash) && !attributes.is_a?(Array)
|
128
|
+
raise ArgumentError, "ActionController::Parameters or Hash or Array expected, got #{attributes.class.name} (#{attributes.inspect})"
|
129
|
+
end
|
130
|
+
|
121
131
|
attributes = attributes.with_indifferent_access
|
122
132
|
|
123
133
|
if attributes['id'].blank?
|
@@ -1,5 +1,8 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
class Relation
|
3
|
+
undef :new
|
4
|
+
undef :create
|
5
|
+
undef :create!
|
3
6
|
undef :first_or_create
|
4
7
|
undef :first_or_create!
|
5
8
|
undef :first_or_initialize
|
@@ -7,6 +10,32 @@ module ActiveRecord
|
|
7
10
|
undef :find_or_create_by
|
8
11
|
undef :find_or_create_by!
|
9
12
|
|
13
|
+
def new(attributes = nil, options = {}, &block)
|
14
|
+
attrs = respond_to?(:values_for_create) ? values_for_create(attributes) : attributes
|
15
|
+
|
16
|
+
scoping { klass.new(attrs, options, &block) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def create(attributes = nil, options = {}, &block)
|
20
|
+
if attributes.is_a?(Array)
|
21
|
+
attributes.collect { |attr| create(attr, options, &block) }
|
22
|
+
else
|
23
|
+
attrs = respond_to?(:values_for_create) ? values_for_create(attributes) : attributes
|
24
|
+
|
25
|
+
scoping { klass.create(attrs, options, &block) }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def create!(attributes = nil, options = {}, &block)
|
30
|
+
if attributes.is_a?(Array)
|
31
|
+
attributes.collect { |attr| create!(attr, options, &block) }
|
32
|
+
else
|
33
|
+
attrs = respond_to?(:values_for_create) ? values_for_create(attributes) : attributes
|
34
|
+
|
35
|
+
scoping { klass.create!(attrs, options, &block) }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
10
39
|
# Tries to load the first record; if it fails, then <tt>create</tt> is called with the same arguments as this method.
|
11
40
|
#
|
12
41
|
# Expects arguments in the same format as +Base.create+.
|
@@ -50,15 +79,15 @@ module ActiveRecord
|
|
50
79
|
end
|
51
80
|
|
52
81
|
def find_or_initialize_by(attributes, options = {}, &block)
|
53
|
-
find_by(attributes) || new(attributes, options, &block)
|
82
|
+
find_by(attributes.respond_to?(:to_unsafe_h) ? attributes.to_unsafe_h : attributes) || new(attributes, options, &block)
|
54
83
|
end
|
55
84
|
|
56
85
|
def find_or_create_by(attributes, options = {}, &block)
|
57
|
-
find_by(attributes) || create(attributes, options, &block)
|
86
|
+
find_by(attributes.respond_to?(:to_unsafe_h) ? attributes.to_unsafe_h : attributes) || create(attributes, options, &block)
|
58
87
|
end
|
59
88
|
|
60
89
|
def find_or_create_by!(attributes, options = {}, &block)
|
61
|
-
find_by(attributes) || create!(attributes, options, &block)
|
90
|
+
find_by(attributes.respond_to?(:to_unsafe_h) ? attributes.to_unsafe_h : attributes) || create!(attributes, options, &block)
|
62
91
|
end
|
63
92
|
end
|
64
93
|
|
data/lib/protected_attributes.rb
CHANGED
@@ -1,19 +1 @@
|
|
1
1
|
require "protected_attributes"
|
2
|
-
|
3
|
-
module ActiveRecord
|
4
|
-
module Core
|
5
|
-
def initialize(attributes = nil, options = {})
|
6
|
-
@attributes = self.class._default_attributes.dup
|
7
|
-
self.class.define_attribute_methods
|
8
|
-
|
9
|
-
init_internals
|
10
|
-
initialize_internals_callback
|
11
|
-
|
12
|
-
# +options+ argument is only needed to make protected_attributes gem easier to hook.
|
13
|
-
init_attributes(attributes, options) if attributes
|
14
|
-
|
15
|
-
yield self if block_given?
|
16
|
-
_run_initialize_callbacks
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protected_attributes_continued
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- David Heinemeier Hansson
|
8
7
|
- Weston Ganger
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2020-10-01 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: activemodel
|
@@ -17,80 +16,56 @@ dependencies:
|
|
17
16
|
requirements:
|
18
17
|
- - ">="
|
19
18
|
- !ruby/object:Gem::Version
|
20
|
-
version:
|
21
|
-
- - "<"
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: '6.0'
|
19
|
+
version: '5.0'
|
24
20
|
type: :runtime
|
25
21
|
prerelease: false
|
26
22
|
version_requirements: !ruby/object:Gem::Requirement
|
27
23
|
requirements:
|
28
24
|
- - ">="
|
29
25
|
- !ruby/object:Gem::Version
|
30
|
-
version:
|
31
|
-
- - "<"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '6.0'
|
26
|
+
version: '5.0'
|
34
27
|
- !ruby/object:Gem::Dependency
|
35
28
|
name: activerecord
|
36
29
|
requirement: !ruby/object:Gem::Requirement
|
37
30
|
requirements:
|
38
31
|
- - ">="
|
39
32
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
41
|
-
- - "<"
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: '6.0'
|
33
|
+
version: '5.0'
|
44
34
|
type: :development
|
45
35
|
prerelease: false
|
46
36
|
version_requirements: !ruby/object:Gem::Requirement
|
47
37
|
requirements:
|
48
38
|
- - ">="
|
49
39
|
- !ruby/object:Gem::Version
|
50
|
-
version:
|
51
|
-
- - "<"
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '6.0'
|
40
|
+
version: '5.0'
|
54
41
|
- !ruby/object:Gem::Dependency
|
55
42
|
name: actionpack
|
56
43
|
requirement: !ruby/object:Gem::Requirement
|
57
44
|
requirements:
|
58
45
|
- - ">="
|
59
46
|
- !ruby/object:Gem::Version
|
60
|
-
version:
|
61
|
-
- - "<"
|
62
|
-
- !ruby/object:Gem::Version
|
63
|
-
version: '6.0'
|
47
|
+
version: '5.0'
|
64
48
|
type: :development
|
65
49
|
prerelease: false
|
66
50
|
version_requirements: !ruby/object:Gem::Requirement
|
67
51
|
requirements:
|
68
52
|
- - ">="
|
69
53
|
- !ruby/object:Gem::Version
|
70
|
-
version:
|
71
|
-
- - "<"
|
72
|
-
- !ruby/object:Gem::Version
|
73
|
-
version: '6.0'
|
54
|
+
version: '5.0'
|
74
55
|
- !ruby/object:Gem::Dependency
|
75
56
|
name: railties
|
76
57
|
requirement: !ruby/object:Gem::Requirement
|
77
58
|
requirements:
|
78
59
|
- - ">="
|
79
60
|
- !ruby/object:Gem::Version
|
80
|
-
version:
|
81
|
-
- - "<"
|
82
|
-
- !ruby/object:Gem::Version
|
83
|
-
version: '6.0'
|
61
|
+
version: '5.0'
|
84
62
|
type: :development
|
85
63
|
prerelease: false
|
86
64
|
version_requirements: !ruby/object:Gem::Requirement
|
87
65
|
requirements:
|
88
66
|
- - ">="
|
89
67
|
- !ruby/object:Gem::Version
|
90
|
-
version:
|
91
|
-
- - "<"
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: '6.0'
|
68
|
+
version: '5.0'
|
94
69
|
- !ruby/object:Gem::Dependency
|
95
70
|
name: sqlite3
|
96
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -107,6 +82,20 @@ dependencies:
|
|
107
82
|
version: '0'
|
108
83
|
- !ruby/object:Gem::Dependency
|
109
84
|
name: mocha
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.4.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.4.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: appraisal
|
110
99
|
requirement: !ruby/object:Gem::Requirement
|
111
100
|
requirements:
|
112
101
|
- - ">="
|
@@ -121,8 +110,7 @@ dependencies:
|
|
121
110
|
version: '0'
|
122
111
|
description: Protect attributes from mass assignment
|
123
112
|
email:
|
124
|
-
-
|
125
|
-
- westonganger@gmail.com
|
113
|
+
- weston@westonganger.com
|
126
114
|
executables: []
|
127
115
|
extensions: []
|
128
116
|
extra_rdoc_files: []
|
@@ -166,8 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
166
154
|
- !ruby/object:Gem::Version
|
167
155
|
version: '0'
|
168
156
|
requirements: []
|
169
|
-
|
170
|
-
rubygems_version: 2.5.1
|
157
|
+
rubygems_version: 3.1.2
|
171
158
|
signing_key:
|
172
159
|
specification_version: 4
|
173
160
|
summary: Protect attributes from mass assignment in Active Record models
|