mass_assignment 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/lib/mass_assignment.rb +21 -21
- data/test/mass_assignment_test.rb +13 -49
- data/test/models.rb +51 -0
- data/test/test_helper.rb +2 -1
- metadata +10 -8
data/Rakefile
CHANGED
data/lib/mass_assignment.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
module MassAssignment
|
2
2
|
def self.included(base)
|
3
|
-
base.class_eval do
|
3
|
+
base.class_eval do
|
4
|
+
class_attribute :assignment_policy, :instance_reader => false, :instance_writer => false
|
5
|
+
def self.mass_assignment_policy(val)
|
6
|
+
self.assignment_policy = val
|
7
|
+
end
|
8
|
+
end
|
4
9
|
end
|
5
10
|
|
6
11
|
# Basic Example:
|
@@ -24,27 +29,35 @@ module MassAssignment
|
|
24
29
|
# @user.save!
|
25
30
|
def assign(attributes, allowed_attributes = nil, &block)
|
26
31
|
return unless attributes and attributes.is_a? Hash
|
27
|
-
|
32
|
+
|
28
33
|
if allowed_attributes
|
29
34
|
safe_attributes = filter_attributes(attributes, :only => allowed_attributes)
|
30
35
|
yield attributes if block_given?
|
31
|
-
|
36
|
+
mass_assign_safe_attributes(safe_attributes)
|
32
37
|
else
|
33
|
-
if policy = self.class.
|
38
|
+
if policy = self.class.assignment_policy
|
34
39
|
safe_attributes = filter_attributes(attributes, policy)
|
35
|
-
|
40
|
+
mass_assign_safe_attributes(safe_attributes)
|
36
41
|
else
|
37
|
-
#
|
42
|
+
# fall back on Rails' system
|
38
43
|
self.attributes = attributes
|
39
44
|
end
|
40
45
|
end
|
41
46
|
end
|
42
|
-
|
47
|
+
|
43
48
|
private
|
44
49
|
|
50
|
+
def mass_assign_safe_attributes(safe_attributes)
|
51
|
+
if respond_to?(:assign_attributes)
|
52
|
+
assign_attributes(safe_attributes, :without_protection => true)
|
53
|
+
else
|
54
|
+
self.send("attributes=", safe_attributes, false)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
45
58
|
def filter_attributes(attributes, options = {}) # could surely be refactored.
|
46
59
|
attributes = attributes.stringify_keys
|
47
|
-
|
60
|
+
|
48
61
|
if options[:only]
|
49
62
|
if options[:only].is_a? Regexp
|
50
63
|
attributes.reject { |k, v| !k.gsub(/\(.+/, "").match(options[:only]) }
|
@@ -73,19 +86,6 @@ module MassAssignment
|
|
73
86
|
attributes
|
74
87
|
end
|
75
88
|
end
|
76
|
-
|
77
|
-
module ClassMethods
|
78
|
-
# sets a default mass assignment policy for your model's attributes. you may choose to start from a
|
79
|
-
# closed state that allows no mass assignment, an open state that allows any mass assignment (this is
|
80
|
-
# activerecord's default), or somewhere inbetween.
|
81
|
-
def mass_assignment_policy(val)
|
82
|
-
write_inheritable_attribute :mass_assignment_policy, val
|
83
|
-
end
|
84
|
-
|
85
|
-
def get_mass_assignment_policy
|
86
|
-
read_inheritable_attribute :mass_assignment_policy
|
87
|
-
end
|
88
|
-
end
|
89
89
|
end
|
90
90
|
|
91
91
|
ActiveRecord::Base.class_eval do include MassAssignment end
|
@@ -1,55 +1,19 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/test_helper'
|
2
2
|
|
3
|
-
class User < ActiveRecord::Base
|
4
|
-
class << self
|
5
|
-
def columns
|
6
|
-
@columns ||= [
|
7
|
-
ActiveRecord::ConnectionAdapters::Column.new("name", nil, "varchar(100)", true),
|
8
|
-
ActiveRecord::ConnectionAdapters::Column.new("email", nil, "varchar(100)", true),
|
9
|
-
ActiveRecord::ConnectionAdapters::Column.new("role_id", nil, "integer(11)", false)
|
10
|
-
]
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def friend
|
15
|
-
@friend ||= User.new
|
16
|
-
end
|
17
|
-
|
18
|
-
def friend_attributes=(attributes)
|
19
|
-
friend.attributes = attributes
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
class ProtectedUser < User
|
24
|
-
attr_protected :role_id
|
25
|
-
end
|
26
|
-
|
27
|
-
class ClosedUser < User
|
28
|
-
mass_assignment_policy :except => :all
|
29
|
-
end
|
30
|
-
|
31
|
-
class SemiClosedUser < User
|
32
|
-
mass_assignment_policy :except => /_id$/
|
33
|
-
end
|
34
|
-
|
35
|
-
class OpenUser < User
|
36
|
-
mass_assignment_policy :only => :all
|
37
|
-
end
|
38
|
-
|
39
3
|
class MassAssignmentTest < ActiveSupport::TestCase
|
40
4
|
def setup
|
41
5
|
@user = ProtectedUser.new
|
42
6
|
@attributes = {"name" => "Bob", "email" => "bob@example.com"}
|
43
7
|
ActiveRecord::Base.logger = stub('debug' => true)
|
44
8
|
end
|
45
|
-
|
9
|
+
|
46
10
|
test "assigning nothing" do
|
47
11
|
params = {}
|
48
12
|
assert_nothing_raised do
|
49
13
|
@user.assign(params[:user])
|
50
14
|
end
|
51
15
|
end
|
52
|
-
|
16
|
+
|
53
17
|
test "assigning a string" do
|
54
18
|
params = {:user => "well this is embarrassing"}
|
55
19
|
assert_nothing_raised do
|
@@ -62,31 +26,31 @@ class MassAssignmentTest < ActiveSupport::TestCase
|
|
62
26
|
assert_equal "Bob", @user.name
|
63
27
|
assert_equal "bob@example.com", @user.email
|
64
28
|
end
|
65
|
-
|
29
|
+
|
66
30
|
test "assigning protected attributes" do
|
67
31
|
@user.assign(@attributes.merge(:role_id => 1))
|
68
32
|
assert_equal "Bob", @user.name
|
69
33
|
assert_nil @user.role_id
|
70
34
|
end
|
71
|
-
|
35
|
+
|
72
36
|
test "overriding protected attributes" do
|
73
37
|
@user.assign(@attributes.merge(:role_id => 1), [:name, :email, :role_id])
|
74
38
|
assert_equal "Bob", @user.name
|
75
39
|
assert_equal 1, @user.role_id
|
76
40
|
end
|
77
|
-
|
41
|
+
|
78
42
|
test "assigning unallowed attributes" do
|
79
43
|
@user.assign(@attributes.merge(:role_id => 1), [:name, :email])
|
80
44
|
assert_equal "Bob", @user.name
|
81
45
|
assert_nil @user.role_id
|
82
46
|
end
|
83
|
-
|
47
|
+
|
84
48
|
test "nested assignment" do
|
85
49
|
@user.assign(@attributes.merge(:friend_attributes => {:name => 'Joe', :role_id => 1}), [:name, :role_id, {:friend_attributes => [:name]}])
|
86
50
|
assert_equal "Joe", @user.friend.name
|
87
51
|
assert_nil @user.friend.role_id
|
88
52
|
end
|
89
|
-
|
53
|
+
|
90
54
|
test "deep assignment" do
|
91
55
|
@user.assign(@attributes.merge(:friend => {:name => 'Joe', :role_id => 1}), [:name, :role_id]) do |params|
|
92
56
|
@user.friend.assign(params[:friend], [:name])
|
@@ -101,42 +65,42 @@ class MassAssignmentPolicyTest < ActiveSupport::TestCase
|
|
101
65
|
@attributes = {"name" => "Bob", "role_id" => 1}
|
102
66
|
ActiveRecord::Base.logger = stub('debug' => true)
|
103
67
|
end
|
104
|
-
|
68
|
+
|
105
69
|
test "an open policy" do
|
106
70
|
@user = OpenUser.new
|
107
71
|
@user.assign(@attributes)
|
108
72
|
assert_equal "Bob", @user.name
|
109
73
|
assert_equal 1, @user.role_id
|
110
74
|
end
|
111
|
-
|
75
|
+
|
112
76
|
test "an overridden open policy" do
|
113
77
|
@user = OpenUser.new
|
114
78
|
@user.assign(@attributes, [:name])
|
115
79
|
assert_equal "Bob", @user.name
|
116
80
|
assert_nil @user.role_id
|
117
81
|
end
|
118
|
-
|
82
|
+
|
119
83
|
test "a closed policy" do
|
120
84
|
@user = ClosedUser.new
|
121
85
|
@user.assign(@attributes)
|
122
86
|
assert_nil @user.name
|
123
87
|
assert_nil @user.role_id
|
124
88
|
end
|
125
|
-
|
89
|
+
|
126
90
|
test "an overridden closed policy" do
|
127
91
|
@user = ClosedUser.new
|
128
92
|
@user.assign(@attributes, [:name, :role_id])
|
129
93
|
assert_equal "Bob", @user.name
|
130
94
|
assert_equal 1, @user.role_id
|
131
95
|
end
|
132
|
-
|
96
|
+
|
133
97
|
test "a semi-closed policy" do
|
134
98
|
@user = SemiClosedUser.new
|
135
99
|
@user.assign(@attributes)
|
136
100
|
assert_equal "Bob", @user.name
|
137
101
|
assert_nil @user.role_id
|
138
102
|
end
|
139
|
-
|
103
|
+
|
140
104
|
test "an overridden semi-closed policy" do
|
141
105
|
@user = SemiClosedUser.new
|
142
106
|
@user.assign(@attributes, [:name, :role_id])
|
data/test/models.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
class User < ActiveRecord::Base
|
2
|
+
class << self
|
3
|
+
def columns
|
4
|
+
@columns ||= [
|
5
|
+
ActiveRecord::ConnectionAdapters::Column.new("name", nil, "varchar(100)", true),
|
6
|
+
ActiveRecord::ConnectionAdapters::Column.new("email", nil, "varchar(100)", true),
|
7
|
+
ActiveRecord::ConnectionAdapters::Column.new("role_id", nil, "integer(11)", false)
|
8
|
+
]
|
9
|
+
end
|
10
|
+
|
11
|
+
def column_defaults
|
12
|
+
columns.inject({}) { |h, col| h.merge(col.name => col.default) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def columns_hash
|
16
|
+
columns.inject({}) { |h, col| h.merge(col.name => col) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def primary_key
|
20
|
+
'id'
|
21
|
+
end
|
22
|
+
|
23
|
+
def attributes_protected_by_default
|
24
|
+
[ primary_key ]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def friend
|
29
|
+
@friend ||= User.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def friend_attributes=(attributes)
|
33
|
+
friend.attributes = attributes
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class ProtectedUser < User
|
38
|
+
attr_protected :role_id
|
39
|
+
end
|
40
|
+
|
41
|
+
class ClosedUser < User
|
42
|
+
mass_assignment_policy :except => :all
|
43
|
+
end
|
44
|
+
|
45
|
+
class SemiClosedUser < User
|
46
|
+
mass_assignment_policy :except => /_id$/
|
47
|
+
end
|
48
|
+
|
49
|
+
class OpenUser < User
|
50
|
+
mass_assignment_policy :only => :all
|
51
|
+
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mass_assignment
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 19
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
- 0
|
9
8
|
- 1
|
10
|
-
|
9
|
+
- 0
|
10
|
+
version: 1.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Lance Ivy
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-11-21 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -45,8 +45,9 @@ files:
|
|
45
45
|
- LICENSE
|
46
46
|
- README.textile
|
47
47
|
- Rakefile
|
48
|
-
- test/test_helper.rb
|
49
48
|
- test/mass_assignment_test.rb
|
49
|
+
- test/models.rb
|
50
|
+
- test/test_helper.rb
|
50
51
|
has_rdoc: true
|
51
52
|
homepage: http://github.com/cainlevy/mass_assignment
|
52
53
|
licenses: []
|
@@ -77,10 +78,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
77
78
|
requirements: []
|
78
79
|
|
79
80
|
rubyforge_project:
|
80
|
-
rubygems_version: 1.
|
81
|
+
rubygems_version: 1.6.2
|
81
82
|
signing_key:
|
82
83
|
specification_version: 3
|
83
84
|
summary: Simple and secure params assignment for ActiveRecord
|
84
85
|
test_files:
|
85
|
-
- test/test_helper.rb
|
86
86
|
- test/mass_assignment_test.rb
|
87
|
+
- test/models.rb
|
88
|
+
- test/test_helper.rb
|