usine 1.1.0 → 1.2.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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/README.md +64 -43
- data/lib/usine.rb +11 -52
- data/lib/usine/null_model.rb +3 -0
- data/lib/usine/operation_factory.rb +31 -0
- data/lib/usine/operation_wrapper.rb +49 -0
- data/lib/usine/version.rb +1 -1
- data/usine.gemspec +1 -0
- metadata +18 -7
- data/lib/usine/definition.rb +0 -11
- data/lib/usine/definition_evaluator.rb +0 -39
- data/lib/usine/exceptions.rb +0 -11
- data/lib/usine/factory.rb +0 -13
- data/lib/usine/factory_evaluator.rb +0 -73
- data/lib/usine/sequence.rb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03d1e6d91e2856f9104d7a7c7b6907988674cdf8
|
4
|
+
data.tar.gz: 7573d835285b97a7243304ab437bd43ae425e150
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fcc0c03dff27f57b4a1d63eda0c11803ee7bb8fee770b8eb9fa2378fe0851b65fa6eddee7003741d89a8a15351b49585fe1ba013603e9332eb26387fc4537028
|
7
|
+
data.tar.gz: df77515eb45fe2bec61f553fa20c7e696beb544ca93a753895bbf28f4772bd17fec5fa7ae59219d03d30e710648017ca0480eef1343dc3288705e2a73f21436e
|
data/README.md
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
# Usine
|
2
2
|
|
3
|
-
Usine (french word for factory) is a
|
4
|
-
when using Trailblazer’s operations. [Trailblazer](http://trailblazer.to/) advocates against using factory_girl to avoid
|
5
|
-
differences when initializing objects. Usine follows this path but allows you to define defaults for the
|
6
|
-
parameters passed to your operations.
|
3
|
+
Usine (french word for factory) is a wrapper around factory_girls with two goals: simplify using [Trailblazer](http://trailblazer.to/) with factory_girl, and avoid initializing models through factory_girl instead of Trailblazer.
|
7
4
|
|
8
5
|
## Installation
|
9
6
|
|
@@ -23,72 +20,96 @@ Or install it yourself as:
|
|
23
20
|
|
24
21
|
## Usage
|
25
22
|
|
26
|
-
|
27
|
-
|
28
|
-
Definitions are the base of anything in Usine, they are used in factories to generate
|
29
|
-
the hash of params sent to the operation.
|
23
|
+
Usine let you reuse your factories and use them to define the params sent to your Operation.
|
30
24
|
|
31
25
|
```ruby
|
32
|
-
|
33
|
-
|
26
|
+
FactoryGirl.define do
|
27
|
+
factory :item do
|
28
|
+
title { "Default title"}
|
29
|
+
end
|
30
|
+
|
31
|
+
factory :user do
|
32
|
+
email { "xx@exxample.com"}
|
33
|
+
end
|
34
34
|
end
|
35
35
|
|
36
|
-
Usine
|
37
|
-
|
36
|
+
# If no symbol given, Usine will try to find an existing factory with this name
|
37
|
+
Usine.operation(Item::Create) do
|
38
|
+
item
|
39
|
+
current_user :user
|
38
40
|
end
|
39
|
-
```
|
40
41
|
|
41
|
-
|
42
|
+
# Usine will transmit [call, run, present] to the operation invocation
|
43
|
+
# so you can have the kind of operation you want in your test
|
44
|
+
# for example `present` will not run process in your Operation
|
45
|
+
Usine.(Item::Create, item: {title: "Another title"})
|
46
|
+
Usine.call(Item::Create, item: {title: "Another title"})
|
47
|
+
Usine.run(Item::Create, item: {title: "Another title"})
|
48
|
+
Usine.present(Item::Create, item: {title: "Another title"})
|
49
|
+
```
|
42
50
|
|
43
|
-
|
44
|
-
This is what you will call when building your objects in a test.
|
51
|
+
### Model less factories
|
45
52
|
|
53
|
+
If your params are not related to a model you can simply create a factory this way:
|
46
54
|
```ruby
|
47
|
-
|
48
|
-
|
49
|
-
|
55
|
+
FactoryGirl.define do
|
56
|
+
factory :search, class:Usine::NullModel do
|
57
|
+
query { "*"}
|
58
|
+
end
|
50
59
|
end
|
51
60
|
```
|
52
61
|
|
53
|
-
###
|
62
|
+
### Factory girl features
|
54
63
|
|
55
|
-
|
56
|
-
Which means you have 3 different ways to invoke a factory :
|
64
|
+
All factory_girl features should work, sequences for example are working:
|
57
65
|
|
58
66
|
```ruby
|
59
|
-
|
60
|
-
|
61
|
-
|
67
|
+
FactoryGirl.define do
|
68
|
+
sequence(:email) do |n|
|
69
|
+
"some_email_#{n}@example.com"
|
70
|
+
end
|
71
|
+
|
72
|
+
factory :user do
|
73
|
+
contact { generate(:email) }
|
74
|
+
end
|
75
|
+
end
|
62
76
|
```
|
63
77
|
|
64
|
-
|
78
|
+
### Writing a test with Usine
|
65
79
|
|
66
|
-
Let see an example in a test :
|
67
80
|
```
|
68
|
-
|
69
|
-
|
81
|
+
# Without Usine
|
82
|
+
let(:item) {
|
83
|
+
Item::Create.({
|
84
|
+
item: {
|
85
|
+
title: "DEFAULT_TITLE"
|
86
|
+
},
|
87
|
+
current_user: User::Create.(email: "some_email@example.com").model
|
88
|
+
}).model
|
70
89
|
}
|
71
|
-
```
|
72
90
|
|
73
|
-
|
91
|
+
# With Usine
|
92
|
+
FactoryGirl.define do
|
93
|
+
factory :item do
|
94
|
+
title { "DEFAULT_TITLE" }
|
95
|
+
end
|
74
96
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
# global sequence
|
79
|
-
Usine.sequence(:title) do |n|
|
80
|
-
"title number #{n}"
|
97
|
+
factory :user do
|
98
|
+
email { "some_email@example.com" }
|
99
|
+
end
|
81
100
|
end
|
82
101
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
email # if no block given, Usine will try to invoke generate(:email)
|
87
|
-
title # and will also search in global sequences
|
88
|
-
alt_email { generate(:email) }
|
102
|
+
Usine.operation(Item::Create) do
|
103
|
+
item
|
104
|
+
current_user :user
|
89
105
|
end
|
106
|
+
|
107
|
+
let(:item) { Usine.(Item::Create).model }
|
90
108
|
```
|
91
109
|
|
110
|
+
The second example might look more verbose, but you only have to define factories/operations one time.
|
111
|
+
And then you can reuse it for all your tests.
|
112
|
+
|
92
113
|
## Contributing
|
93
114
|
|
94
115
|
Bug reports and pull requests are welcome on GitHub at https://github.com/jjaffeux/usine. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
data/lib/usine.rb
CHANGED
@@ -1,68 +1,27 @@
|
|
1
|
+
require "uber/inheritable_attr"
|
2
|
+
require "factory_girl"
|
1
3
|
require "usine/version"
|
2
4
|
require "usine/utils"
|
3
|
-
require "usine/
|
4
|
-
require "usine/
|
5
|
-
require "usine/
|
6
|
-
require "usine/definition_evaluator"
|
7
|
-
require "usine/definition"
|
8
|
-
require "usine/sequence"
|
9
|
-
require "uber/inheritable_attr"
|
5
|
+
require "usine/null_model"
|
6
|
+
require "usine/operation_factory"
|
7
|
+
require "usine/operation_wrapper"
|
10
8
|
|
11
9
|
module Usine
|
12
10
|
extend Uber::InheritableAttr
|
13
|
-
inheritable_attr :
|
14
|
-
self.
|
15
|
-
inheritable_attr :factories
|
16
|
-
self.factories = []
|
17
|
-
inheritable_attr :sequences
|
18
|
-
self.sequences = []
|
11
|
+
inheritable_attr :operations
|
12
|
+
self.operations = []
|
19
13
|
|
20
14
|
class << self
|
21
|
-
|
22
15
|
[:call, :run, :present].each do |mode|
|
23
16
|
define_method mode, ->(*args, &block) {
|
24
17
|
operation = args.shift
|
25
|
-
|
26
|
-
|
18
|
+
attributes = args.shift || {}
|
19
|
+
OperationWrapper.(mode, operation, attributes)
|
27
20
|
}
|
28
21
|
end
|
29
22
|
|
30
|
-
def
|
31
|
-
self.
|
32
|
-
|
33
|
-
self.factories << Factory.new(operation, *extensions, &block)
|
34
|
-
|
35
|
-
extensions.each do |extension|
|
36
|
-
self.factories << Factory.new(operation, *extension, &block)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def sequence(name, initial_value = 1, &block)
|
41
|
-
self.sequences << Sequence.new(name, initial_value, &block)
|
42
|
-
end
|
43
|
-
|
44
|
-
def definition(attribute, *extensions, &block)
|
45
|
-
self.definitions ||= []
|
46
|
-
|
47
|
-
self.definitions << Definition.new(attribute, &block)
|
48
|
-
|
49
|
-
extensions.each do |extension|
|
50
|
-
self.definitions << Definition.new(attribute, &block)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
protected
|
55
|
-
|
56
|
-
def find_factory_for_operation(operation)
|
57
|
-
factory = Usine.factories.detect do |f|
|
58
|
-
f.operation == operation
|
59
|
-
end
|
60
|
-
|
61
|
-
if factory.nil?
|
62
|
-
raise "NOT FOUND FACTORY for #{operation}"
|
63
|
-
end
|
64
|
-
|
65
|
-
factory
|
23
|
+
def operation(operation, *args, &block)
|
24
|
+
self.operations << OperationFactory.new(operation, &block)
|
66
25
|
end
|
67
26
|
end
|
68
27
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Usine
|
2
|
+
class OperationFactory
|
3
|
+
attr_reader :operation_class
|
4
|
+
|
5
|
+
def initialize(operation_class, &block)
|
6
|
+
@operation_class = operation_class
|
7
|
+
@block = block
|
8
|
+
@attributes = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def process
|
12
|
+
self.instance_eval(&@block)
|
13
|
+
@attributes
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(method_symbol, factory_name = nil, &block)
|
17
|
+
if factory_name
|
18
|
+
@attributes[method_symbol] = attributes_for_factory_name(factory_name)
|
19
|
+
else
|
20
|
+
@attributes[method_symbol] = attributes_for_factory_name(method_symbol)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def attributes_for_factory_name(name)
|
27
|
+
factory = FactoryGirl.factory_by_name(name)
|
28
|
+
factory.run(FactoryGirl::Strategy::AttributesFor, {})
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Usine
|
2
|
+
class OperationWrapper
|
3
|
+
def initialize(mode, operation, attributes = {})
|
4
|
+
@mode = mode
|
5
|
+
@operation = operation
|
6
|
+
@operation_factory = find_operation_factory(operation)
|
7
|
+
@attributes = attributes
|
8
|
+
end
|
9
|
+
|
10
|
+
def operations=(operations)
|
11
|
+
@operations = operations
|
12
|
+
end
|
13
|
+
|
14
|
+
def operations
|
15
|
+
@operations ||= Usine.operations
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.call(mode, operation, attributes = {})
|
19
|
+
wrapper = new(mode, operation, attributes)
|
20
|
+
wrapper.process
|
21
|
+
end
|
22
|
+
|
23
|
+
def process
|
24
|
+
factory_attributes = @operation_factory.process
|
25
|
+
merged_attributes = Utils.merge_hashes(factory_attributes, @attributes)
|
26
|
+
@operation.send(@mode, merged_attributes)
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def find_operation_factory(operation_class)
|
32
|
+
operation_factory = operations.detect do |op|
|
33
|
+
op.operation_class == operation_class
|
34
|
+
end
|
35
|
+
|
36
|
+
unless operation_factory
|
37
|
+
message = <<-MSG
|
38
|
+
Couldn’t find an operation factory for: #{operation_class}
|
39
|
+
|
40
|
+
Please define it with:
|
41
|
+
Usine.operation(#{operation_class}) {}
|
42
|
+
MSG
|
43
|
+
raise(ArgumentError, message)
|
44
|
+
end
|
45
|
+
|
46
|
+
operation_factory
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/usine/version.rb
CHANGED
data/usine.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: usine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joffrey JAFFEUX
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: factory_girl
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: bundler
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,12 +112,9 @@ files:
|
|
98
112
|
- bin/console
|
99
113
|
- bin/setup
|
100
114
|
- lib/usine.rb
|
101
|
-
- lib/usine/
|
102
|
-
- lib/usine/
|
103
|
-
- lib/usine/
|
104
|
-
- lib/usine/factory.rb
|
105
|
-
- lib/usine/factory_evaluator.rb
|
106
|
-
- lib/usine/sequence.rb
|
115
|
+
- lib/usine/null_model.rb
|
116
|
+
- lib/usine/operation_factory.rb
|
117
|
+
- lib/usine/operation_wrapper.rb
|
107
118
|
- lib/usine/utils.rb
|
108
119
|
- lib/usine/version.rb
|
109
120
|
- usine.gemspec
|
data/lib/usine/definition.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
module Usine
|
2
|
-
class DefinitionEvaluator
|
3
|
-
attr_reader :attributes
|
4
|
-
attr_reader :sequences
|
5
|
-
attr_reader :scoped_sequences
|
6
|
-
|
7
|
-
def initialize(sequences = [])
|
8
|
-
@sequences = sequences
|
9
|
-
@scoped_sequences = []
|
10
|
-
@attributes = {}
|
11
|
-
end
|
12
|
-
|
13
|
-
def method_missing(method_symbol, *args, &block)
|
14
|
-
if block
|
15
|
-
@attributes[method_symbol] = block.call
|
16
|
-
else
|
17
|
-
@attributes[method_symbol] = generate(method_symbol)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def generate(attribute)
|
22
|
-
if sequence = scoped_sequences.detect { |x| x.attribute == attribute }
|
23
|
-
sequence.next
|
24
|
-
elsif sequence = sequences.detect { |x| x.attribute == attribute }
|
25
|
-
sequence.next
|
26
|
-
else
|
27
|
-
message = <<-MSG
|
28
|
-
Couldn’t find a sequence named: #{attribute}
|
29
|
-
Available sequences: #{scoped_sequences.concat(sequences).map(&:attribute).join(',')}
|
30
|
-
MSG
|
31
|
-
raise(UsineError::SequenceNotFound, message)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def sequence(name, initial_value = 1, &block)
|
36
|
-
@scoped_sequences << Sequence.new(name, initial_value, &block)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
data/lib/usine/exceptions.rb
DELETED
data/lib/usine/factory.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
module Usine
|
2
|
-
class FactoryEvaluator
|
3
|
-
attr_reader :mode
|
4
|
-
attr_reader :attributes
|
5
|
-
attr_reader :generated_attributes
|
6
|
-
attr_reader :factory
|
7
|
-
|
8
|
-
def self.call(factory, mode, attributes = {})
|
9
|
-
factory = new(factory, mode, attributes)
|
10
|
-
factory.process!
|
11
|
-
end
|
12
|
-
|
13
|
-
def definitions=(definitions)
|
14
|
-
@definitions = definitions
|
15
|
-
end
|
16
|
-
|
17
|
-
def definitions
|
18
|
-
@definitions ||= Usine.definitions
|
19
|
-
end
|
20
|
-
|
21
|
-
def sequences=(sequences)
|
22
|
-
@sequences = sequences
|
23
|
-
end
|
24
|
-
|
25
|
-
def sequences
|
26
|
-
@sequences ||= Usine.sequences
|
27
|
-
end
|
28
|
-
|
29
|
-
def initialize(factory, mode, attributes = {})
|
30
|
-
@mode = mode
|
31
|
-
@factory = factory
|
32
|
-
@attributes = attributes
|
33
|
-
@generated_attributes = {}
|
34
|
-
end
|
35
|
-
|
36
|
-
def use(definition_name, *args)
|
37
|
-
definition = definitions.detect do |definition|
|
38
|
-
definition.name == definition_name
|
39
|
-
end
|
40
|
-
|
41
|
-
if definition.nil?
|
42
|
-
message = <<-MSG
|
43
|
-
Couldn’t find a definition named: #{definition_name}
|
44
|
-
Available definitions: #{definitions.map(&:name).join(',')}
|
45
|
-
MSG
|
46
|
-
raise(UsineError::DefinitionNotFound, message)
|
47
|
-
end
|
48
|
-
|
49
|
-
evaluated_definition = DefinitionEvaluator.new(sequences)
|
50
|
-
evaluated_definition.instance_eval(&definition.block)
|
51
|
-
evaluated_definition.attributes
|
52
|
-
end
|
53
|
-
|
54
|
-
def method_missing(method_symbol, *args, &block)
|
55
|
-
if block
|
56
|
-
@generated_attributes[method_symbol] = self.instance_eval(&block)
|
57
|
-
else
|
58
|
-
@generated_attributes[method_symbol] = use(method_symbol, *args)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def process!
|
63
|
-
self.instance_eval(&factory.block)
|
64
|
-
@factory.operation.send(@mode, merged_attributes)
|
65
|
-
end
|
66
|
-
|
67
|
-
protected
|
68
|
-
|
69
|
-
def merged_attributes
|
70
|
-
Utils.merge_hashes(@generated_attributes, @attributes)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
data/lib/usine/sequence.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
module Usine
|
2
|
-
class Sequence
|
3
|
-
attr_reader :attribute
|
4
|
-
|
5
|
-
def initialize(attribute, *args, &block)
|
6
|
-
@attribute = attribute
|
7
|
-
@block = block
|
8
|
-
@value = args.first || 1
|
9
|
-
|
10
|
-
unless @value.respond_to?(:next)
|
11
|
-
raise(UsineError::SequenceInvalidInitialValue, "Invalid initial value, it must respond to #next")
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def next
|
16
|
-
@block.call(@value)
|
17
|
-
ensure
|
18
|
-
@value = @value.next
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|