ardm-types 1.2.2

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.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +36 -0
  3. data/.travis.yml +11 -0
  4. data/Gemfile +51 -0
  5. data/LICENSE +20 -0
  6. data/README.rdoc +3 -0
  7. data/Rakefile +4 -0
  8. data/ardm-types.gemspec +29 -0
  9. data/lib/ardm-types.rb +1 -0
  10. data/lib/dm-types/api_key.rb +30 -0
  11. data/lib/dm-types/bcrypt_hash.rb +34 -0
  12. data/lib/dm-types/comma_separated_list.rb +29 -0
  13. data/lib/dm-types/csv.rb +38 -0
  14. data/lib/dm-types/enum.rb +51 -0
  15. data/lib/dm-types/epoch_time.rb +41 -0
  16. data/lib/dm-types/file_path.rb +32 -0
  17. data/lib/dm-types/flag.rb +63 -0
  18. data/lib/dm-types/ip_address.rb +42 -0
  19. data/lib/dm-types/json.rb +50 -0
  20. data/lib/dm-types/paranoid/base.rb +55 -0
  21. data/lib/dm-types/paranoid_boolean.rb +23 -0
  22. data/lib/dm-types/paranoid_datetime.rb +22 -0
  23. data/lib/dm-types/regexp.rb +21 -0
  24. data/lib/dm-types/slug.rb +29 -0
  25. data/lib/dm-types/support/dirty_minder.rb +166 -0
  26. data/lib/dm-types/support/flags.rb +41 -0
  27. data/lib/dm-types/uri.rb +38 -0
  28. data/lib/dm-types/uuid.rb +74 -0
  29. data/lib/dm-types/version.rb +5 -0
  30. data/lib/dm-types/yaml.rb +41 -0
  31. data/lib/dm-types.rb +23 -0
  32. data/spec/fixtures/api_user.rb +14 -0
  33. data/spec/fixtures/article.rb +35 -0
  34. data/spec/fixtures/bookmark.rb +23 -0
  35. data/spec/fixtures/invention.rb +7 -0
  36. data/spec/fixtures/network_node.rb +36 -0
  37. data/spec/fixtures/person.rb +25 -0
  38. data/spec/fixtures/software_package.rb +33 -0
  39. data/spec/fixtures/ticket.rb +21 -0
  40. data/spec/fixtures/tshirt.rb +24 -0
  41. data/spec/integration/api_key_spec.rb +27 -0
  42. data/spec/integration/bcrypt_hash_spec.rb +47 -0
  43. data/spec/integration/comma_separated_list_spec.rb +87 -0
  44. data/spec/integration/dirty_minder_spec.rb +197 -0
  45. data/spec/integration/enum_spec.rb +80 -0
  46. data/spec/integration/epoch_time_spec.rb +61 -0
  47. data/spec/integration/file_path_spec.rb +160 -0
  48. data/spec/integration/flag_spec.rb +72 -0
  49. data/spec/integration/ip_address_spec.rb +153 -0
  50. data/spec/integration/json_spec.rb +72 -0
  51. data/spec/integration/slug_spec.rb +67 -0
  52. data/spec/integration/uri_spec.rb +139 -0
  53. data/spec/integration/uuid_spec.rb +102 -0
  54. data/spec/integration/yaml_spec.rb +69 -0
  55. data/spec/rcov.opts +6 -0
  56. data/spec/shared/flags_shared_spec.rb +37 -0
  57. data/spec/shared/identity_function_group.rb +5 -0
  58. data/spec/spec.opts +4 -0
  59. data/spec/spec_helper.rb +30 -0
  60. data/spec/unit/bcrypt_hash_spec.rb +155 -0
  61. data/spec/unit/csv_spec.rb +142 -0
  62. data/spec/unit/enum_spec.rb +126 -0
  63. data/spec/unit/epoch_time_spec.rb +74 -0
  64. data/spec/unit/file_path_spec.rb +87 -0
  65. data/spec/unit/flag_spec.rb +114 -0
  66. data/spec/unit/ip_address_spec.rb +121 -0
  67. data/spec/unit/json_spec.rb +144 -0
  68. data/spec/unit/paranoid_boolean_spec.rb +150 -0
  69. data/spec/unit/paranoid_datetime_spec.rb +154 -0
  70. data/spec/unit/regexp_spec.rb +63 -0
  71. data/spec/unit/uri_spec.rb +64 -0
  72. data/spec/unit/uuid_spec.rb +25 -0
  73. data/spec/unit/yaml_spec.rb +111 -0
  74. data/tasks/spec.rake +38 -0
  75. data/tasks/yard.rake +9 -0
  76. data/tasks/yardstick.rake +19 -0
  77. metadata +236 -0
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+
3
+ require './spec/fixtures/tshirt'
4
+
5
+ try_spec do
6
+ describe DataMapper::Property::Flag do
7
+ describe '.dump' do
8
+ before :all do
9
+ @flag = DataMapper::TypesFixtures::TShirt.property(
10
+ :stuff, DataMapper::Property::Flag[:first, :second, :third, :fourth, :fifth])
11
+
12
+ @property_klass = DataMapper::Property::Flag
13
+ end
14
+
15
+ it_should_behave_like "A property with flags"
16
+
17
+ describe 'when argument matches a value in the flag map' do
18
+ before :all do
19
+ @result = @flag.dump(:first)
20
+ end
21
+
22
+ it 'returns flag bit of value' do
23
+ @result.should == 1
24
+ end
25
+ end
26
+
27
+ describe 'when argument matches 2nd value in the flag map' do
28
+ before :all do
29
+ @result = @flag.dump(:second)
30
+ end
31
+
32
+ it 'returns flag bit of value' do
33
+ @result.should == 2
34
+ end
35
+ end
36
+
37
+ describe 'when argument matches multiple Symbol values in the flag map' do
38
+ before :all do
39
+ @result = @flag.dump([ :second, :fourth ])
40
+ end
41
+
42
+ it 'builds binary flag from key values of all matches' do
43
+ @result.should == 10
44
+ end
45
+ end
46
+
47
+ describe 'when argument matches multiple string values in the flag map' do
48
+ before :all do
49
+ @result = @flag.dump(['first', 'second', 'third', 'fourth', 'fifth'])
50
+ end
51
+
52
+ it 'builds binary flag from key values of all matches' do
53
+ @result.should == 31
54
+ end
55
+ end
56
+
57
+ describe 'when argument does not match a single value in the flag map' do
58
+ before :all do
59
+ @result = @flag.dump(:zero)
60
+ end
61
+
62
+ it 'returns zero' do
63
+ @result.should == 0
64
+ end
65
+ end
66
+
67
+ describe 'when argument contains duplicate flags' do
68
+ before :all do
69
+ @result = @flag.dump([ :second, :fourth, :second ])
70
+ end
71
+
72
+ it 'behaves the same as if there were no duplicates' do
73
+ @result.should == @flag.dump([ :second, :fourth ])
74
+ end
75
+ end
76
+ end
77
+
78
+ describe '.load' do
79
+ before :all do
80
+ @flag = DataMapper::TypesFixtures::TShirt.property(:stuff, DataMapper::Property::Flag, :flags => [:uno, :dos, :tres, :cuatro, :cinco])
81
+ end
82
+
83
+ describe 'when argument matches a key in the flag map' do
84
+ before :all do
85
+ @result = @flag.load(4)
86
+ end
87
+
88
+ it 'returns array with a single matching element' do
89
+ @result.should == [ :tres ]
90
+ end
91
+ end
92
+
93
+ describe 'when argument matches multiple keys in the flag map' do
94
+ before :all do
95
+ @result = @flag.load(10)
96
+ end
97
+
98
+ it 'returns array of matching values' do
99
+ @result.should == [ :dos, :cuatro ]
100
+ end
101
+ end
102
+
103
+ describe 'when argument does not match a single key in the flag map' do
104
+ before :all do
105
+ @result = @flag.load(nil)
106
+ end
107
+
108
+ it 'returns an empty array' do
109
+ @result.should == []
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,121 @@
1
+ require 'spec_helper'
2
+
3
+ require './spec/fixtures/network_node'
4
+
5
+ try_spec do
6
+ describe DataMapper::Property::IPAddress do
7
+ before :all do
8
+ @stored = '81.20.130.1'
9
+ @input = IPAddr.new(@stored)
10
+ @property = DataMapper::TypesFixtures::NetworkNode.properties[:ip_address]
11
+ end
12
+
13
+ describe '#valid?' do
14
+ describe "with a String" do
15
+ subject { @property.valid?(@stored) }
16
+ it { subject.should be(true) }
17
+ end
18
+
19
+ describe "with an IPAddr" do
20
+ subject { @property.valid?(@input) }
21
+ it { subject.should be(true) }
22
+ end
23
+ end
24
+
25
+ describe '.dump' do
26
+ describe 'when argument is an IP address given as Ruby object' do
27
+ before :all do
28
+ @result = @property.dump(@input)
29
+ end
30
+
31
+ it 'dumps input into a string' do
32
+ @result.should == @stored
33
+ end
34
+ end
35
+
36
+ describe 'when argument is nil' do
37
+ before :all do
38
+ @result = @property.dump(nil)
39
+ end
40
+
41
+ it 'returns nil' do
42
+ @result.should be_nil
43
+ end
44
+ end
45
+
46
+ describe 'when input is a blank string' do
47
+ before :all do
48
+ @result = @property.dump('')
49
+ end
50
+
51
+ it 'retuns a blank string' do
52
+ @result.should == ''
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '.load' do
58
+ describe 'when argument is a valid IP address as a string' do
59
+ before :all do
60
+ @result = @property.load(@stored)
61
+ end
62
+
63
+ it 'returns IPAddr instance from stored value' do
64
+ @result.should == @input
65
+ end
66
+ end
67
+
68
+ describe 'when argument is nil' do
69
+ before :all do
70
+ @result = @property.load(nil)
71
+ end
72
+
73
+ it 'returns nil' do
74
+ @result.should be_nil
75
+ end
76
+ end
77
+
78
+ describe 'when argument is a blank string' do
79
+ before :all do
80
+ @result = @property.load('')
81
+ end
82
+
83
+ it 'returns IPAddr instance from stored value' do
84
+ @result.should == IPAddr.new('0.0.0.0')
85
+ end
86
+ end
87
+
88
+ describe 'when argument is an Array instance' do
89
+ before :all do
90
+ @operation = lambda { @property.load([]) }
91
+ end
92
+
93
+ it 'raises ArgumentError with a meaningful message' do
94
+ @operation.should raise_error(ArgumentError, '+value+ must be nil or a String')
95
+ end
96
+ end
97
+ end
98
+
99
+ describe '.typecast' do
100
+ describe 'when argument is an IpAddr object' do
101
+ before :all do
102
+ @result = @property.typecast(@input)
103
+ end
104
+
105
+ it 'does not change the value' do
106
+ @result.should == @input
107
+ end
108
+ end
109
+
110
+ describe 'when argument is a valid IP address as a string' do
111
+ before :all do
112
+ @result = @property.typecast(@stored)
113
+ end
114
+
115
+ it 'instantiates IPAddr instance' do
116
+ @result.should == @input
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,144 @@
1
+ require 'spec_helper'
2
+ require 'shared/identity_function_group'
3
+
4
+ try_spec do
5
+
6
+ require './spec/fixtures/person'
7
+
8
+ describe DataMapper::Property::Json do
9
+ before :all do
10
+ @property = DataMapper::TypesFixtures::Person.properties[:positions]
11
+ end
12
+
13
+ describe '#valid?' do
14
+ before :all do
15
+ @string = '{ "foo": "bar" }'
16
+ @json = MultiJson.decode(@string)
17
+ end
18
+
19
+ describe "with a String" do
20
+ subject { @property.valid?(@input) }
21
+ it { subject.should be(true) }
22
+ end
23
+
24
+ describe "with JSON" do
25
+ subject { @property.valid?(@json) }
26
+ it { subject.should be(true) }
27
+ end
28
+ end
29
+
30
+ describe '.load' do
31
+ describe 'when nil is provided' do
32
+ it 'returns nil' do
33
+ @property.load(nil).should be_nil
34
+ end
35
+ end
36
+
37
+ describe 'when Json encoded primitive string is provided' do
38
+ it 'returns decoded value as Ruby string' do
39
+ @property.load(MultiJson.encode(:value => 'JSON encoded string')).should == { 'value' => 'JSON encoded string' }
40
+ end
41
+ end
42
+
43
+ describe 'when something else is provided' do
44
+ it 'raises ArgumentError with a meaningful message' do
45
+ lambda {
46
+ @property.load(:sym)
47
+ }.should raise_error(ArgumentError, '+value+ of a property of JSON type must be nil or a String')
48
+ end
49
+ end
50
+ end
51
+
52
+ describe '.dump' do
53
+ describe 'when nil is provided' do
54
+ it 'returns nil' do
55
+ @property.dump(nil).should be_nil
56
+ end
57
+ end
58
+
59
+ describe 'when Json encoded primitive string is provided' do
60
+ it 'does not do double encoding' do
61
+ @property.dump('Json encoded string').should == 'Json encoded string'
62
+ end
63
+ end
64
+
65
+ describe 'when regular Ruby string is provided' do
66
+ it 'dumps argument to Json' do
67
+ @property.dump('dump me (to JSON)').should == 'dump me (to JSON)'
68
+ end
69
+ end
70
+
71
+ describe 'when Ruby array is provided' do
72
+ it 'dumps argument to Json' do
73
+ @property.dump([1, 2, 3]).should == '[1,2,3]'
74
+ end
75
+ end
76
+
77
+ describe 'when Ruby hash is provided' do
78
+ it 'dumps argument to Json' do
79
+ @property.dump({ :datamapper => 'Data access layer in Ruby' }).
80
+ should == '{"datamapper":"Data access layer in Ruby"}'
81
+ end
82
+ end
83
+ end
84
+
85
+ describe '.typecast' do
86
+ class ::SerializeMe
87
+ attr_accessor :name
88
+ end
89
+
90
+ describe 'when given instance of a Hash' do
91
+ before :all do
92
+ @input = { :library => 'DataMapper' }
93
+
94
+ @result = @property.typecast(@input)
95
+ end
96
+
97
+ it_should_behave_like 'identity function'
98
+ end
99
+
100
+ describe 'when given instance of an Array' do
101
+ before :all do
102
+ @input = %w[ dm-core dm-more ]
103
+
104
+ @result = @property.typecast(@input)
105
+ end
106
+
107
+ it_should_behave_like 'identity function'
108
+ end
109
+
110
+ describe 'when given nil' do
111
+ before :all do
112
+ @input = nil
113
+
114
+ @result = @property.typecast(@input)
115
+ end
116
+
117
+ it_should_behave_like 'identity function'
118
+ end
119
+
120
+ describe 'when given JSON encoded value' do
121
+ before :all do
122
+ @input = '{ "value": 11 }'
123
+
124
+ @result = @property.typecast(@input)
125
+ end
126
+
127
+ it 'decodes value from JSON' do
128
+ @result.should == { 'value' => 11 }
129
+ end
130
+ end
131
+
132
+ describe 'when given instance of a custom class' do
133
+ before :all do
134
+ @input = SerializeMe.new
135
+ @input.name = 'Hello!'
136
+
137
+ # @result = @property.typecast(@input)
138
+ end
139
+
140
+ it 'attempts to load value from JSON string'
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,150 @@
1
+ require 'spec_helper'
2
+
3
+ describe DataMapper::Property::ParanoidBoolean do
4
+ before :all do
5
+ Object.send(:remove_const, :Blog) if defined?(Blog)
6
+
7
+ module ::Blog
8
+ class Draft
9
+ include DataMapper::Resource
10
+
11
+ property :id, Serial
12
+ property :deleted, ParanoidBoolean
13
+
14
+ before :destroy, :before_destroy
15
+
16
+ def before_destroy; end
17
+ end
18
+
19
+ class Article < Draft; end
20
+
21
+ class Review < Article; end
22
+ end
23
+
24
+ @model = Blog::Article
25
+ end
26
+
27
+ supported_by :all do
28
+ describe 'Resource#destroy' do
29
+ subject { @resource.destroy }
30
+
31
+ describe 'with a new resource' do
32
+ before do
33
+ @resource = @model.new
34
+ end
35
+
36
+ it { should be(false) }
37
+
38
+ it 'should not delete the resource from the datastore' do
39
+ method(:subject).should_not change { @model.with_deleted.size }.from(0)
40
+ end
41
+
42
+ it 'should not set the paranoid column' do
43
+ method(:subject).should_not change { @resource.deleted }.from(false)
44
+ end
45
+
46
+ it 'should run the destroy hook' do
47
+ @resource.should_receive(:before_destroy).with(no_args)
48
+ subject
49
+ end
50
+ end
51
+
52
+ describe 'with a saved resource' do
53
+ before do
54
+ @resource = @model.create
55
+ end
56
+
57
+ it { should be(true) }
58
+
59
+ it 'should not delete the resource from the datastore' do
60
+ method(:subject).should_not change { @model.with_deleted.size }.from(1)
61
+ end
62
+
63
+ it 'should set the paranoid column' do
64
+ method(:subject).should change { @resource.deleted }.from(false).to(true)
65
+ end
66
+
67
+ it 'should run the destroy hook' do
68
+ @resource.should_receive(:before_destroy).with(no_args)
69
+ subject
70
+ end
71
+ end
72
+ end
73
+
74
+ describe 'Resource#destroy!' do
75
+ subject { @resource.destroy! }
76
+
77
+ describe 'with a new resource' do
78
+ before do
79
+ @resource = @model.new
80
+ end
81
+
82
+ it { should be(false) }
83
+
84
+ it 'should not delete the resource from the datastore' do
85
+ method(:subject).should_not change { @model.with_deleted.size }.from(0)
86
+ end
87
+
88
+ it 'should not set the paranoid column' do
89
+ method(:subject).should_not change { @resource.deleted }.from(false)
90
+ end
91
+
92
+ it 'should not run the destroy hook' do
93
+ @resource.should_not_receive(:before_destroy).with(no_args)
94
+ subject
95
+ end
96
+ end
97
+
98
+ describe 'with a saved resource' do
99
+ before do
100
+ @resource = @model.create
101
+ end
102
+
103
+ it { should be(true) }
104
+
105
+ it 'should delete the resource from the datastore' do
106
+ method(:subject).should change { @model.with_deleted.size }.from(1).to(0)
107
+ end
108
+
109
+ it 'should not set the paranoid column' do
110
+ method(:subject).should_not change { @resource.deleted }.from(false)
111
+ end
112
+
113
+ it 'should not run the destroy hook' do
114
+ @resource.should_not_receive(:before_destroy).with(no_args)
115
+ subject
116
+ end
117
+ end
118
+ end
119
+
120
+ describe 'Model#with_deleted' do
121
+ before do
122
+ @resource = @model.create
123
+ @resource.destroy
124
+ end
125
+
126
+ describe 'with a block' do
127
+ subject { @model.with_deleted { @model.all } }
128
+
129
+ it 'should scope the block to return all resources' do
130
+ subject.map { |resource| resource.key }.should == [ @resource.key ]
131
+ end
132
+ end
133
+
134
+ describe 'without a block' do
135
+ subject { @model.with_deleted }
136
+
137
+ it 'should return a collection scoped to return all resources' do
138
+ subject.map { |resource| resource.key }.should == [ @resource.key ]
139
+ end
140
+ end
141
+ end
142
+
143
+ describe 'Model.inherited' do
144
+ it 'sets @paranoid_properties' do
145
+ ::Blog::Review.instance_variable_get(:@paranoid_properties).should ==
146
+ ::Blog::Article.instance_variable_get(:@paranoid_properties)
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,154 @@
1
+ require 'spec_helper'
2
+
3
+ describe DataMapper::Property::ParanoidDateTime do
4
+ before :all do
5
+ Object.send(:remove_const, :Blog) if defined?(Blog)
6
+ module ::Blog
7
+ class Draft
8
+ include DataMapper::Resource
9
+
10
+ property :id, Serial
11
+ property :deleted_at, ParanoidDateTime
12
+
13
+ before :destroy, :before_destroy
14
+
15
+ def before_destroy; end
16
+ end
17
+
18
+ class Article < Draft; end
19
+
20
+ class Review < Article; end
21
+ end
22
+
23
+ @model = Blog::Article
24
+ end
25
+
26
+ supported_by :all do
27
+ describe 'Resource#destroy' do
28
+ before do
29
+ pending 'Does not work with < 1.8.7, see if backports fixes it' if RUBY_VERSION < '1.8.7'
30
+ end
31
+
32
+ subject { @resource.destroy }
33
+
34
+ describe 'with a new resource' do
35
+ before do
36
+ @resource = @model.new
37
+ end
38
+
39
+ it { should be(false) }
40
+
41
+ it 'should not delete the resource from the datastore' do
42
+ method(:subject).should_not change { @model.with_deleted.size }.from(0)
43
+ end
44
+
45
+ it 'should not set the paranoid column' do
46
+ method(:subject).should_not change { @resource.deleted_at }.from(nil)
47
+ end
48
+
49
+ it 'should run the destroy hook' do
50
+ @resource.should_receive(:before_destroy).with(no_args)
51
+ subject
52
+ end
53
+ end
54
+
55
+ describe 'with a saved resource' do
56
+ before do
57
+ @resource = @model.create
58
+ end
59
+
60
+ it { should be(true) }
61
+
62
+ it 'should not delete the resource from the datastore' do
63
+ method(:subject).should_not change { @model.with_deleted.size }.from(1)
64
+ end
65
+
66
+ it 'should set the paranoid column' do
67
+ method(:subject).should change { @resource.deleted_at }.from(nil)
68
+ end
69
+
70
+ it 'should run the destroy hook' do
71
+ @resource.should_receive(:before_destroy).with(no_args)
72
+ subject
73
+ end
74
+ end
75
+ end
76
+
77
+ describe 'Resource#destroy!' do
78
+ subject { @resource.destroy! }
79
+
80
+ describe 'with a new resource' do
81
+ before do
82
+ @resource = @model.new
83
+ end
84
+
85
+ it { should be(false) }
86
+
87
+ it 'should not delete the resource from the datastore' do
88
+ method(:subject).should_not change { @model.with_deleted.size }.from(0)
89
+ end
90
+
91
+ it 'should not set the paranoid column' do
92
+ method(:subject).should_not change { @resource.deleted_at }.from(nil)
93
+ end
94
+
95
+ it 'should not run the destroy hook' do
96
+ @resource.should_not_receive(:before_destroy).with(no_args)
97
+ subject
98
+ end
99
+ end
100
+
101
+ describe 'with a saved resource' do
102
+ before do
103
+ @resource = @model.create
104
+ end
105
+
106
+ it { should be(true) }
107
+
108
+ it 'should delete the resource from the datastore' do
109
+ method(:subject).should change { @model.with_deleted.size }.from(1).to(0)
110
+ end
111
+
112
+ it 'should not set the paranoid column' do
113
+ method(:subject).should_not change { @resource.deleted_at }.from(nil)
114
+ end
115
+
116
+ it 'should not run the destroy hook' do
117
+ @resource.should_not_receive(:before_destroy).with(no_args)
118
+ subject
119
+ end
120
+ end
121
+ end
122
+
123
+ describe 'Model#with_deleted' do
124
+ before do
125
+ pending 'Does not work with < 1.8.7, see if backports fixes it' if RUBY_VERSION < '1.8.7'
126
+ @resource = @model.create
127
+ @resource.destroy
128
+ end
129
+
130
+ describe 'with a block' do
131
+ subject { @model.with_deleted { @model.all } }
132
+
133
+ it 'should scope the block to return all resources' do
134
+ subject.map { |resource| resource.key }.should == [ @resource.key ]
135
+ end
136
+ end
137
+
138
+ describe 'without a block' do
139
+ subject { @model.with_deleted }
140
+
141
+ it 'should return a collection scoped to return all resources' do
142
+ subject.map { |resource| resource.key }.should == [ @resource.key ]
143
+ end
144
+ end
145
+ end
146
+
147
+ describe 'Model.inherited' do
148
+ it 'sets @paranoid_properties' do
149
+ ::Blog::Review.instance_variable_get(:@paranoid_properties).should ==
150
+ ::Blog::Article.instance_variable_get(:@paranoid_properties)
151
+ end
152
+ end
153
+ end
154
+ end