mass_assignable 1.0.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.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +79 -0
- data/Rakefile +11 -0
- data/lib/mass_assignable.rb +64 -0
- data/mass_assignable.gemspec +20 -0
- data/test/mass_assignable_test.rb +114 -0
- metadata +70 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Derrick Reimer
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# MassAssignable
|
2
|
+
|
3
|
+
MassAssignable is a simple gem that adds Rails-like mass-assignment behavior
|
4
|
+
to ordinary Ruby objects. This gem has no external dependencies and works
|
5
|
+
everywhere.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'mass_assignable'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install mass_assignable
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Simply include `MassAssignable` in your class and specify mass assignable
|
24
|
+
attributes using `attr_mass_assignable`. Any attributes not specified
|
25
|
+
will not be mass assignable.
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
require 'mass_assignable' # not needed with Rails
|
29
|
+
|
30
|
+
class Person
|
31
|
+
include MassAssignable
|
32
|
+
|
33
|
+
attr_accessor :name, :age, :height
|
34
|
+
attr_mass_assignable :name, :age
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
Then, mass assignment is as easy as calling `attributes=`.
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
person = Person.new
|
42
|
+
person.attributes = { :name => "Derrick", :age => 24, :height => 77 }
|
43
|
+
|
44
|
+
person.name
|
45
|
+
# => "Derrick"
|
46
|
+
|
47
|
+
person.age
|
48
|
+
# => 24
|
49
|
+
|
50
|
+
person.height
|
51
|
+
# => nil
|
52
|
+
```
|
53
|
+
|
54
|
+
Notice that `#height` is nil, because we didn't include it in our call to
|
55
|
+
`attr_mass_assignable`.
|
56
|
+
|
57
|
+
If you want an error to be raised when invalid mass assignment is attempted,
|
58
|
+
simply use `attr_mass_assignable!`.
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
class ParanoidPerson
|
62
|
+
include MassAssignable
|
63
|
+
|
64
|
+
attr_accessor :name, :age, :height
|
65
|
+
attr_mass_assignable! :name, :age
|
66
|
+
end
|
67
|
+
|
68
|
+
person = ParanoidPerson.new
|
69
|
+
person.attributes = { :height => 77 }
|
70
|
+
# => Raises a RuntimeError
|
71
|
+
```
|
72
|
+
|
73
|
+
## Contributing
|
74
|
+
|
75
|
+
1. Fork it
|
76
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
77
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
78
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
79
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
module MassAssignable
|
2
|
+
def self.included(base)
|
3
|
+
base.extend(ClassMethods)
|
4
|
+
end
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
# Internal: Flag determining whether to raise an exception when
|
8
|
+
# you attempt to mass-assign attributes that are not allowed.
|
9
|
+
attr_accessor :raise_on_invalid_mass_assignment
|
10
|
+
|
11
|
+
# Internal: The Array of Symbols representing attributes that are
|
12
|
+
# mass assignable. This property is defined by the attr_assignable
|
13
|
+
# method.
|
14
|
+
attr_writer :mass_assignable_attributes
|
15
|
+
|
16
|
+
def mass_assignable_attributes
|
17
|
+
@mass_assignable_attributes ||= []
|
18
|
+
end
|
19
|
+
|
20
|
+
# Public: Accepts a list of symbols representing instance methods
|
21
|
+
# that allow mass-assignment.
|
22
|
+
#
|
23
|
+
# *attributes - An Array of symbols or strings.
|
24
|
+
#
|
25
|
+
# Returns nothing.
|
26
|
+
def attr_mass_assignable(*attributes)
|
27
|
+
self.raise_on_invalid_mass_assignment = false
|
28
|
+
self.mass_assignable_attributes ||= []
|
29
|
+
self.mass_assignable_attributes.push(*attributes)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Public: Accepts a list of symbols representing instance methods
|
33
|
+
# that allow mass-assignment and will raise an exception if
|
34
|
+
# mass assignment is attempted for attributes not specified here.
|
35
|
+
#
|
36
|
+
# *attributes - An Array of symbols or strings.
|
37
|
+
#
|
38
|
+
# Returns nothing.
|
39
|
+
def attr_mass_assignable!(*attributes)
|
40
|
+
attr_mass_assignable(*attributes)
|
41
|
+
self.raise_on_invalid_mass_assignment = true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Public: Assigns a Hash of attributes to their corresponding
|
46
|
+
# instance methods. If attributes are specified with attr_assignable,
|
47
|
+
# then only those attributes are allowed to be assigned.
|
48
|
+
#
|
49
|
+
# attribute_hash - A Hash of attribute values with symbol keys.
|
50
|
+
#
|
51
|
+
# Returns nothing.
|
52
|
+
def attributes=(attribute_hash)
|
53
|
+
paranoid = self.class.raise_on_invalid_mass_assignment
|
54
|
+
allowed = self.class.mass_assignable_attributes.map { |a| a.to_s }
|
55
|
+
|
56
|
+
attribute_hash.each do |key, value|
|
57
|
+
if allowed.include?(key.to_s)
|
58
|
+
send(:"#{key}=", value)
|
59
|
+
else
|
60
|
+
raise(RuntimeError, "Mass assignment error") if paranoid
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.name = "mass_assignable"
|
7
|
+
gem.version = "1.0.0"
|
8
|
+
gem.authors = ["Derrick Reimer"]
|
9
|
+
gem.email = ["derrickreimer@gmail.com"]
|
10
|
+
gem.description = %q{Add Rails-like mass assignment to any Ruby object}
|
11
|
+
gem.summary = %q{MassAssignable provides mass assignment functionality to any Ruby object.}
|
12
|
+
gem.homepage = "https://github.com/djreimer/mass_assignable"
|
13
|
+
|
14
|
+
gem.files = `git ls-files`.split($/)
|
15
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
16
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
17
|
+
gem.require_paths = ["lib"]
|
18
|
+
|
19
|
+
gem.add_development_dependency "shoulda-context"
|
20
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
require 'mass_assignable'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'shoulda-context'
|
5
|
+
|
6
|
+
class MassAssignableTest < Test::Unit::TestCase
|
7
|
+
class Person
|
8
|
+
include MassAssignable
|
9
|
+
|
10
|
+
attr_accessor :name, :age, :height
|
11
|
+
attr_mass_assignable :name, :age, :height
|
12
|
+
end
|
13
|
+
|
14
|
+
class Car
|
15
|
+
include MassAssignable
|
16
|
+
|
17
|
+
attr_mass_assignable :make
|
18
|
+
attr_mass_assignable :model
|
19
|
+
end
|
20
|
+
|
21
|
+
class BlankClass
|
22
|
+
include MassAssignable
|
23
|
+
end
|
24
|
+
|
25
|
+
class NothingAssignable
|
26
|
+
include MassAssignable
|
27
|
+
attr_mass_assignable
|
28
|
+
end
|
29
|
+
|
30
|
+
class ParanoidNothingAssignable
|
31
|
+
include MassAssignable
|
32
|
+
attr_mass_assignable!
|
33
|
+
end
|
34
|
+
|
35
|
+
class ProtectedAttributes
|
36
|
+
include MassAssignable
|
37
|
+
|
38
|
+
attr_accessor :name, :age, :height
|
39
|
+
attr_mass_assignable :name
|
40
|
+
end
|
41
|
+
|
42
|
+
class ParanoidPerson
|
43
|
+
include MassAssignable
|
44
|
+
|
45
|
+
attr_accessor :name, :age, :height
|
46
|
+
attr_mass_assignable! :name, :age, :height
|
47
|
+
end
|
48
|
+
|
49
|
+
context ".attr_mass_assignable" do
|
50
|
+
should "set mass assignable attributes" do
|
51
|
+
assert_equal [:name, :age, :height], Person.mass_assignable_attributes
|
52
|
+
end
|
53
|
+
|
54
|
+
should "set mass assignable attribute to an empty array if not called" do
|
55
|
+
assert BlankClass.mass_assignable_attributes.is_a?(Array)
|
56
|
+
assert BlankClass.mass_assignable_attributes.empty?
|
57
|
+
end
|
58
|
+
|
59
|
+
should "set mass assignable attribute to an empty array if no arguments given" do
|
60
|
+
assert NothingAssignable.mass_assignable_attributes.is_a?(Array)
|
61
|
+
assert NothingAssignable.mass_assignable_attributes.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
should "append attributes on multiple calls" do
|
65
|
+
assert Car.mass_assignable_attributes.include?(:make)
|
66
|
+
assert Car.mass_assignable_attributes.include?(:model)
|
67
|
+
end
|
68
|
+
|
69
|
+
should "not raise an exception for invalid mass assignment attempts" do
|
70
|
+
person = Person.new
|
71
|
+
person.attributes = { :gender => "male" }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context ".attr_mass_assignable!" do
|
76
|
+
should "set mass assignable attributes" do
|
77
|
+
assert_equal [:name, :age, :height], ParanoidPerson.mass_assignable_attributes
|
78
|
+
end
|
79
|
+
|
80
|
+
should "set mass assignable attribute to an empty array if no arguments given" do
|
81
|
+
assert ParanoidNothingAssignable.mass_assignable_attributes.is_a?(Array)
|
82
|
+
assert ParanoidNothingAssignable.mass_assignable_attributes.empty?
|
83
|
+
end
|
84
|
+
|
85
|
+
should "raise an exception for invalid mass assignment attempts" do
|
86
|
+
assert_raises(RuntimeError) do
|
87
|
+
person = ParanoidPerson.new
|
88
|
+
person.attributes = { :gender => "male" }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "#attributes=" do
|
94
|
+
should "set attribute values" do
|
95
|
+
person = Person.new
|
96
|
+
person.attributes = { :name => "Derrick", :age => 24, :height => 77 }
|
97
|
+
assert_equal "Derrick", person.name
|
98
|
+
assert_equal 24, person.age
|
99
|
+
assert_equal 77, person.height
|
100
|
+
end
|
101
|
+
|
102
|
+
should "not overwrite unspecified attributes" do
|
103
|
+
original_attr = { :name => "Derrick" }
|
104
|
+
new_attr = { :age => 24, :height => 77 }
|
105
|
+
person = Person.new
|
106
|
+
person.attributes = original_attr
|
107
|
+
person.attributes = new_attr
|
108
|
+
|
109
|
+
assert_equal "Derrick", person.name
|
110
|
+
assert_equal 24, person.age
|
111
|
+
assert_equal 77, person.height
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mass_assignable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Derrick Reimer
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: shoulda-context
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: Add Rails-like mass assignment to any Ruby object
|
31
|
+
email:
|
32
|
+
- derrickreimer@gmail.com
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- .gitignore
|
38
|
+
- Gemfile
|
39
|
+
- LICENSE.txt
|
40
|
+
- README.md
|
41
|
+
- Rakefile
|
42
|
+
- lib/mass_assignable.rb
|
43
|
+
- mass_assignable.gemspec
|
44
|
+
- test/mass_assignable_test.rb
|
45
|
+
homepage: https://github.com/djreimer/mass_assignable
|
46
|
+
licenses: []
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
requirements: []
|
64
|
+
rubyforge_project:
|
65
|
+
rubygems_version: 1.8.23
|
66
|
+
signing_key:
|
67
|
+
specification_version: 3
|
68
|
+
summary: MassAssignable provides mass assignment functionality to any Ruby object.
|
69
|
+
test_files:
|
70
|
+
- test/mass_assignable_test.rb
|