safe_attributes 1.0.2 → 1.0.3
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/LICENSE +1 -1
- data/README.rdoc +17 -2
- data/VERSION +1 -1
- data/lib/safe_attributes.rb +46 -39
- data/safe_attributes.gemspec +2 -2
- data/spec/safe_attributes/safe_attributes_spec.rb +87 -78
- metadata +4 -4
data/LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -26,6 +26,8 @@ that this module does not prevent the creation of:
|
|
26
26
|
|
27
27
|
These largely should not run afoul of Ruby or ActiveRecord in most cases.
|
28
28
|
|
29
|
+
== Accessing Attributes
|
30
|
+
|
29
31
|
To access an attribute in ActiveRecord without its normal getter or setter
|
30
32
|
you can use a couple of different approaches.
|
31
33
|
|
@@ -35,6 +37,13 @@ you can use a couple of different approaches.
|
|
35
37
|
|
36
38
|
You can read more about reserved words[http://oldwiki.rubyonrails.org/rails/pages/ReservedWords] and magic field names[http://oldwiki.rubyonrails.org/rails/pages/MagicFieldNames] on Rails' wiki pages.
|
37
39
|
|
40
|
+
== Validations
|
41
|
+
|
42
|
+
By including safe_attributes, an instance method read_attribute_for_validation
|
43
|
+
is defined in a way that will work for all attributes instead of the
|
44
|
+
default implementation that relies upon the default accessors. In other
|
45
|
+
words, `validates_presence_of :class' will work as of version 1.0.3.
|
46
|
+
|
38
47
|
== Installing
|
39
48
|
|
40
49
|
gem install safe_attributes
|
@@ -60,10 +69,12 @@ Add safe_attributes to your Gemfile.
|
|
60
69
|
|
61
70
|
SafeAttributes is included into ActiveRecord::Base automatically. While
|
62
71
|
nothing else should be necessary, you can still add to the list of bad
|
63
|
-
attributes if you find it necessary.
|
72
|
+
attributes if you find it necessary. This list is a list of method names
|
73
|
+
not to generate.
|
64
74
|
|
65
75
|
class MyModel < ActiveRecord::Base
|
66
76
|
bad_attribute_names :my_attr
|
77
|
+
validates_presence_of :my_attr
|
67
78
|
end
|
68
79
|
|
69
80
|
=== Outside of Rails
|
@@ -84,4 +95,8 @@ attributes if you find it necessary.
|
|
84
95
|
|
85
96
|
== Copyright
|
86
97
|
|
87
|
-
Copyright (c) 2010 C. Brian Jones. See LICENSE for details.
|
98
|
+
Copyright (c) 2010,2011 C. Brian Jones. See LICENSE for details.
|
99
|
+
|
100
|
+
== Thanks
|
101
|
+
|
102
|
+
* Jaime Bellmyer - http://kconrails.com
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.3
|
data/lib/safe_attributes.rb
CHANGED
@@ -1,47 +1,54 @@
|
|
1
1
|
module SafeAttributes
|
2
|
-
|
2
|
+
extend ActiveSupport::Concern
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
4
|
+
module ClassMethods
|
5
|
+
#
|
6
|
+
# Within your model call this method once with a list of
|
7
|
+
# methods matching either attribute() or attribute=() for
|
8
|
+
# attributes (column names) you do not want to create the
|
9
|
+
# the normal method for. You should not need to do this
|
10
|
+
# but the option is there in case the default list is
|
11
|
+
# inadequate.
|
12
|
+
#
|
13
|
+
def bad_attribute_names(*attrs)
|
14
|
+
@bad_attribute_names ||= lambda {
|
15
|
+
methods = Array.new(attrs.collect { |x| x.to_s })
|
16
|
+
methods += ActiveRecord::Base.public_instance_methods
|
17
|
+
methods += ActiveRecord::Base.protected_instance_methods
|
18
|
+
methods += ActiveRecord::Base.private_instance_methods
|
19
|
+
methods -= ['id']
|
20
|
+
return methods
|
21
|
+
}.call
|
22
|
+
end
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
24
|
+
#
|
25
|
+
# Override the default implementation to not create the
|
26
|
+
# attribute() method if that method name is in the list of
|
27
|
+
# bad names
|
28
|
+
#
|
29
|
+
def define_method_attribute(attr_name)
|
30
|
+
return if (bad_attribute_names.include?(attr_name))
|
31
|
+
super(attr_name)
|
32
|
+
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
34
|
+
#
|
35
|
+
# Override the default implementation to not create the
|
36
|
+
# attribute= method if that method name is in the list of
|
37
|
+
# bad names
|
38
|
+
#
|
39
|
+
def define_method_attribute=(attr_name)
|
40
|
+
method = attr_name + '='
|
41
|
+
return if (bad_attribute_names.include?(method))
|
42
|
+
super(attr_name)
|
44
43
|
end
|
44
|
+
end
|
45
|
+
|
46
|
+
module InstanceMethods
|
47
|
+
def read_attribute_for_validation(attr)
|
48
|
+
self[attr.to_sym]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
45
52
|
end
|
46
53
|
|
47
54
|
require 'safe_attributes/railtie.rb' if defined?(Rails)
|
data/safe_attributes.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{safe_attributes}
|
8
|
-
s.version = "1.0.
|
8
|
+
s.version = "1.0.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Brian Jones"]
|
12
|
-
s.date = %q{2011-01
|
12
|
+
s.date = %q{2011-02-01}
|
13
13
|
s.description = %q{Better support for legacy database schemas for ActiveRecord, such as columns named class, or any other name that conflicts with an instance method of ActiveRecord.}
|
14
14
|
s.email = %q{cbj@gnu.org}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -3,90 +3,99 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
|
3
3
|
# create the table for the test in the database
|
4
4
|
ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS 'my_models'")
|
5
5
|
ActiveRecord::Base.connection.create_table(:my_models) do |t|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
t.string :class
|
7
|
+
t.string :bad_attribute
|
8
|
+
t.string :good_attribute
|
9
9
|
end
|
10
10
|
|
11
11
|
class MyModel < ActiveRecord::Base
|
12
|
-
|
13
|
-
|
12
|
+
include SafeAttributes
|
13
|
+
bad_attribute_names :bad_attribute, :bad_attribute=
|
14
|
+
validates_presence_of :class
|
14
15
|
end
|
15
16
|
|
16
17
|
describe MyModel do
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
19
|
+
before(:each) do
|
20
|
+
ActiveRecord::Base.connection.increment_open_transactions
|
21
|
+
ActiveRecord::Base.connection.begin_db_transaction
|
22
|
+
@model = MyModel.new
|
23
|
+
end
|
24
|
+
|
25
|
+
after(:each) do
|
26
|
+
ActiveRecord::Base.connection.rollback_db_transaction
|
27
|
+
ActiveRecord::Base.connection.decrement_open_transactions
|
28
|
+
end
|
29
|
+
|
30
|
+
it "inspecting class returns expected attribute names" do
|
31
|
+
MyModel.inspect.should match 'class: string'
|
32
|
+
end
|
33
|
+
|
34
|
+
it "inspecting instance returns expected attribute names" do
|
35
|
+
@model.inspect.should match 'class: nil'
|
36
|
+
end
|
37
|
+
|
38
|
+
it "does not redefine class()" do
|
39
|
+
@model.class.name.should == 'MyModel'
|
40
|
+
end
|
41
|
+
|
42
|
+
it "defines class=()" do
|
43
|
+
@model.respond_to?('class=') # to force method generation
|
44
|
+
@model.methods.include?('class=').should be_true
|
45
|
+
end
|
46
|
+
|
47
|
+
it "does not define bad_attribute()" do
|
48
|
+
@model.respond_to?('bad_attribute') # to force method generation
|
49
|
+
@model.methods.include?('bad_attribute').should be_false
|
50
|
+
end
|
51
|
+
|
52
|
+
it "does not define bad_attribute=()" do
|
53
|
+
@model.respond_to?('bad_attribute=') # to force method generation
|
54
|
+
@model.methods.include?('bad_attribute=').should be_false
|
55
|
+
end
|
56
|
+
|
57
|
+
it "does define good_attribute()" do
|
58
|
+
@model.respond_to?('good_attribute') # to force method generation
|
59
|
+
@model.methods.include?('good_attribute').should be_true
|
60
|
+
end
|
61
|
+
|
62
|
+
it "does define good_attribute=()" do
|
63
|
+
@model.respond_to?('good_attribute=') # to force method generation
|
64
|
+
@model.methods.include?('good_attribute=').should be_true
|
65
|
+
end
|
66
|
+
|
67
|
+
it "does define id()" do
|
68
|
+
@model.respond_to?('id') # to force method generation
|
69
|
+
@model.methods.include?('id').should be_true
|
70
|
+
end
|
71
|
+
|
72
|
+
it "can create instance in database with special attribute name" do
|
73
|
+
m = MyModel.create(:class => 'Foo')
|
74
|
+
m = MyModel.find(m.id)
|
75
|
+
m[:class].should == 'Foo'
|
76
|
+
end
|
77
|
+
|
78
|
+
it "has class attribute" do
|
79
|
+
MyModel.new().has_attribute?('class').should be_true
|
80
|
+
end
|
81
|
+
|
82
|
+
it "can call class= without error" do
|
83
|
+
m = MyModel.new()
|
84
|
+
m.class = 'Foo'
|
85
|
+
m[:class].should == 'Foo'
|
86
|
+
end
|
87
|
+
|
88
|
+
it "can use finders with attribute" do
|
89
|
+
m = MyModel.find_all_by_class('Foo')
|
90
|
+
m.size.should == 0
|
91
|
+
end
|
92
|
+
|
93
|
+
it "validates presence of class" do
|
94
|
+
@model.valid?.should be_false
|
95
|
+
Array(@model.errors[:class]).include?("can't be blank").should be_true
|
96
|
+
|
97
|
+
m = MyModel.new(:class => 'Foo')
|
98
|
+
m.valid?.should be_true
|
99
|
+
end
|
91
100
|
end
|
92
101
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: safe_attributes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.0.
|
9
|
+
- 3
|
10
|
+
version: 1.0.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Brian Jones
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-01
|
18
|
+
date: 2011-02-01 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|