virtus 1.0.0.beta8 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,10 +14,6 @@ describe Virtus::ValueObject do
14
14
  expect(subject.class.attribute_set[:name]).to_not be_public_writer
15
15
  end
16
16
 
17
- it 'disallows mass-assignment' do
18
- expect(subject.private_methods).to include(:attributes=)
19
- end
20
-
21
17
  it 'disallows cloning' do
22
18
  expect(subject.clone).to be(subject)
23
19
  end
@@ -41,10 +37,20 @@ describe Virtus::ValueObject do
41
37
  end
42
38
  end
43
39
 
40
+ share_examples_for 'a valid value object with mass-assignment turned on' do
41
+ subject { model.new }
42
+
43
+ it 'disallows mass-assignment' do
44
+ expect(subject.private_methods).to include(:attributes=)
45
+ end
46
+ end
47
+
44
48
  context 'using new values {} block' do
45
49
  let(:model) {
50
+ model = Virtus.value_object(:coerce => false, :mass_assignment => mass_assignment)
51
+
46
52
  Class.new {
47
- include Virtus.value_object(:coerce => false)
53
+ include model
48
54
 
49
55
  def self.name
50
56
  'Model'
@@ -57,30 +63,41 @@ describe Virtus::ValueObject do
57
63
  }
58
64
  }
59
65
 
60
- it_behaves_like 'a valid value object'
66
+ context 'without mass-assignment' do
67
+ let(:mass_assignment) { false }
61
68
 
62
- context 'with a model subclass' do
63
- let(:subclass) {
64
- Class.new(model) {
65
- values do
66
- attribute :email, String
67
- end
69
+ it_behaves_like 'a valid value object'
70
+ end
71
+
72
+ context 'with mass-assignment' do
73
+ let(:mass_assignment) { true }
74
+
75
+ it_behaves_like 'a valid value object'
76
+ it_behaves_like 'a valid value object with mass-assignment turned on'
77
+
78
+ context 'with a model subclass' do
79
+ let(:subclass) {
80
+ Class.new(model) {
81
+ values do
82
+ attribute :email, String
83
+ end
84
+ }
68
85
  }
69
- }
70
86
 
71
- it_behaves_like 'a valid value object' do
72
- subject { subclass.new(attributes) }
87
+ it_behaves_like 'a valid value object' do
88
+ subject { subclass.new(attributes) }
73
89
 
74
- let(:attributes) { Hash[:id => 1, :name => 'Jane Doe', :email => 'jane@doe.com'] }
90
+ let(:attributes) { Hash[:id => 1, :name => 'Jane Doe', :email => 'jane@doe.com'] }
75
91
 
76
- its(:email) { should eql('jane@doe.com') }
92
+ its(:email) { should eql('jane@doe.com') }
77
93
 
78
- it 'sets private writers for additional values' do
79
- expect(subclass.attribute_set[:email]).to_not be_public_writer
80
- end
94
+ it 'sets private writers for additional values' do
95
+ expect(subclass.attribute_set[:email]).to_not be_public_writer
96
+ end
81
97
 
82
- it 'defines valid #== for a subclass' do
83
- expect(subject == subject.class.new(attributes.merge(:id => 2))).to be(false)
98
+ it 'defines valid #== for a subclass' do
99
+ expect(subject == subject.class.new(attributes.merge(:id => 2))).to be(false)
100
+ end
84
101
  end
85
102
  end
86
103
  end
data/virtus.gemspec CHANGED
@@ -10,6 +10,7 @@ Gem::Specification.new do |gem|
10
10
  gem.description = "Attributes on Steroids for Plain Old Ruby Objects"
11
11
  gem.summary = gem.description
12
12
  gem.homepage = "https://github.com/solnic/virtus"
13
+ gem.license = 'MIT'
13
14
 
14
15
  gem.require_paths = [ "lib" ]
15
16
  gem.files = `git ls-files`.split("\n")
@@ -19,5 +20,5 @@ Gem::Specification.new do |gem|
19
20
  gem.add_dependency('descendants_tracker', '~> 0.0.1')
20
21
  gem.add_dependency('equalizer', '~> 0.0.7')
21
22
  gem.add_dependency('coercible', '~> 0.2')
22
- gem.add_dependency('axiom-types', '~> 0.0.3')
23
+ gem.add_dependency('axiom-types', '~> 0.0.4')
23
24
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: virtus
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta8
4
+ version: 1.0.0.rc1
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-28 00:00:00.000000000 Z
12
+ date: 2013-10-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: descendants_tracker
@@ -66,7 +66,7 @@ dependencies:
66
66
  requirements:
67
67
  - - ~>
68
68
  - !ruby/object:Gem::Version
69
- version: 0.0.3
69
+ version: 0.0.4
70
70
  type: :runtime
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -74,7 +74,7 @@ dependencies:
74
74
  requirements:
75
75
  - - ~>
76
76
  - !ruby/object:Gem::Version
77
- version: 0.0.3
77
+ version: 0.0.4
78
78
  description: Attributes on Steroids for Plain Old Ruby Objects
79
79
  email:
80
80
  - piotr.solnica@gmail.com
@@ -122,6 +122,8 @@ files:
122
122
  - lib/virtus/attribute/lazy_default.rb
123
123
  - lib/virtus/attribute/strict.rb
124
124
  - lib/virtus/attribute_set.rb
125
+ - lib/virtus/builder.rb
126
+ - lib/virtus/builder/hook_context.rb
125
127
  - lib/virtus/class_inclusions.rb
126
128
  - lib/virtus/class_methods.rb
127
129
  - lib/virtus/configuration.rb
@@ -129,7 +131,6 @@ files:
129
131
  - lib/virtus/extensions.rb
130
132
  - lib/virtus/instance_methods.rb
131
133
  - lib/virtus/model.rb
132
- - lib/virtus/module_builder.rb
133
134
  - lib/virtus/module_extensions.rb
134
135
  - lib/virtus/support/equalizer.rb
135
136
  - lib/virtus/support/options.rb
@@ -145,6 +146,7 @@ files:
145
146
  - spec/integration/embedded_value_spec.rb
146
147
  - spec/integration/extending_objects_spec.rb
147
148
  - spec/integration/hash_attributes_coercion_spec.rb
149
+ - spec/integration/inheritance_spec.rb
148
150
  - spec/integration/injectible_coercers_spec.rb
149
151
  - spec/integration/mass_assignment_with_accessors_spec.rb
150
152
  - spec/integration/overriding_virtus_spec.rb
@@ -201,7 +203,8 @@ files:
201
203
  - spec/unit/virtus/value_object_spec.rb
202
204
  - virtus.gemspec
203
205
  homepage: https://github.com/solnic/virtus
204
- licenses: []
206
+ licenses:
207
+ - MIT
205
208
  post_install_message:
206
209
  rdoc_options: []
207
210
  require_paths:
@@ -1,192 +0,0 @@
1
- module Virtus
2
-
3
- # Class to build a Virtus module with it's own configuration
4
- #
5
- # This allows for individual Virtus modules to be included in
6
- # classes and not impacted by the global Virtus configuration,
7
- # which is implemented using Virtus::Configuration.
8
- #
9
- # @private
10
- class ExtensionBuilder
11
-
12
- # Return module
13
- #
14
- # @return [Module]
15
- #
16
- # @api private
17
- attr_reader :module
18
-
19
- # Return configuration
20
- #
21
- # @return [Configuration]
22
- #
23
- # @api private
24
- attr_reader :configuration
25
-
26
- # Builds a new Virtus module
27
- #
28
- # The block is passed to Virtus::Configuration
29
- #
30
- # @example
31
- # ModuleBuilder.call do |config|
32
- # # config settings
33
- # end
34
- #
35
- # @return [Module]
36
- #
37
- # @api public
38
- def self.call(options = {}, &block)
39
- config = Configuration.build(&block)
40
- options.each { |key, value| config.public_send("#{key}=", value) }
41
- builder = new(config)
42
- builder.add_included_hook
43
- builder.add_extended_hook
44
- builder.module
45
- end
46
-
47
- # @api private
48
- def self.pending
49
- @pending ||= []
50
- end
51
-
52
- # Initializes a new ModuleBuilder
53
- #
54
- # @param [Configuration] configuration
55
- #
56
- # @param [Module] mod
57
- #
58
- # @return [undefined]
59
- #
60
- # @api private
61
- def initialize(configuration, mod = Module.new)
62
- @configuration = configuration
63
- @module = mod
64
- end
65
-
66
- # Adds the .included hook to the anonymous module which then defines the
67
- # .attribute method to override the default.
68
- #
69
- # @return [Module]
70
- #
71
- # @api private
72
- def add_included_hook
73
- attribute_proc = attribute_method(configuration)
74
- constructor = configuration.constructor
75
- mass_assignment = configuration.mass_assignment
76
- finalize = configuration.finalize
77
- extensions = core_extensions
78
- inclusions = core_inclusions
79
-
80
- self.module.define_singleton_method :included do |object|
81
- super(object)
82
- ExtensionBuilder.pending << object unless finalize
83
- extensions.each { |mod| object.extend(mod) }
84
- inclusions.each { |mod| object.send(:include, mod) }
85
- object.send(:include, Model::Constructor) if constructor
86
- object.send(:include, Model::MassAssignment) if mass_assignment
87
- object.send(:define_singleton_method, :attribute, attribute_proc)
88
- end
89
- end
90
-
91
- # @api private
92
- def add_extended_hook
93
- attribute_proc = attribute_method(configuration)
94
- mass_assignment = configuration.mass_assignment
95
- extensions = core_inclusions + core_extensions
96
-
97
- self.module.define_singleton_method :extended do |object|
98
- super(object)
99
- extensions.each { |mod| object.extend(mod) }
100
- object.extend(Model::MassAssignment) if mass_assignment
101
- object.send :define_singleton_method, :attribute, attribute_proc
102
- end
103
- end
104
-
105
- # Wrapper for the attribute method that is used in .add_included_hook
106
- # The coercer is passed in the unused key :configured_coercer to allow the
107
- # property encapsulation by Virtus::Attribute::Coercer, where the
108
- # coercion method is known.
109
- #
110
- # @return [Proc(lambda)]
111
- #
112
- # @api private
113
- def attribute_method(configuration)
114
- module_options = self.module_options
115
-
116
- lambda do |name, type = Object, options = {}|
117
- super(name, type, module_options.merge(options))
118
- end
119
- end
120
-
121
- # @api private
122
- def module_options
123
- { :coerce => configuration.coerce,
124
- :finalize => configuration.finalize,
125
- :strict => configuration.strict,
126
- :configured_coercer => configuration.coercer }
127
- end
128
-
129
- # @api private
130
- def core_inclusions
131
- [Model::Core]
132
- end
133
-
134
- # @api private
135
- def core_extensions
136
- []
137
- end
138
-
139
- end # class ExtensionBuilder
140
-
141
- # @private
142
- class ModelExtensionBuilder < ExtensionBuilder
143
- end # ModelExtensionBuilder
144
-
145
- # @private
146
- class ModuleExtensionBuilder < ExtensionBuilder
147
-
148
- # @api private
149
- def add_included_hook
150
- attribute_proc = attribute_method(configuration)
151
- inclusions = core_inclusions
152
-
153
- inclusions << Model::Constructor if configuration.constructor
154
- inclusions << Model::MassAssignment if configuration.mass_assignment
155
-
156
- self.module.define_singleton_method :included do |object|
157
- super(object)
158
- object.extend(ModuleExtensions)
159
- object.instance_variable_set('@inclusions', inclusions)
160
- object.send(:define_singleton_method, :attribute, attribute_proc)
161
- end
162
- end
163
-
164
- end # ModuleExtensionBuilder
165
-
166
- # @private
167
- class ValueObjectExtensionBuilder < ExtensionBuilder
168
-
169
- # @api private
170
- def initialize(configuration, mod = Module.new)
171
- super
172
- @configuration.constructor = true
173
- end
174
-
175
- # @api private
176
- def module_options
177
- super.update(:writer => :private)
178
- end
179
-
180
- # @api private
181
- def core_inclusions
182
- super << ValueObject::AllowedWriterMethods << ValueObject::InstanceMethods
183
- end
184
-
185
- # @api private
186
- def core_extensions
187
- super << ValueObject::AllowedWriterMethods
188
- end
189
-
190
- end # ValueObjectBuilder
191
-
192
- end # module Virtus