factory_bot_factory 0.0.5 → 1.2.1
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/Gemfile.lock +14 -6
- data/README.md +66 -51
- data/factory_bot_factory.gemspec +7 -3
- data/lib/factory_bot_factory/attribute.rb +38 -0
- data/lib/factory_bot_factory/base.rb +17 -5
- data/lib/factory_bot_factory/config.rb +18 -4
- data/lib/factory_bot_factory/converters/data_time_converter.rb +9 -0
- data/lib/factory_bot_factory/factories/active_record_factory.rb +9 -0
- data/lib/factory_bot_factory/factories/base_factory.rb +46 -22
- data/lib/factory_bot_factory/factories/hash_factory.rb +3 -1
- data/lib/factory_bot_factory/factories/model_factory.rb +2 -2
- data/lib/factory_bot_factory/factories/open_struct_factory.rb +3 -1
- data/lib/factory_bot_factory/file_writer.rb +31 -0
- data/lib/factory_bot_factory/line_writer.rb +15 -21
- data/lib/factory_bot_factory/logger.rb +41 -0
- data/lib/factory_bot_factory/version.rb +1 -1
- data/lib/factory_bot_factory.rb +10 -5
- metadata +46 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb075f366c70f4ed151ae1bc3239053c613a1a90dd0c015800c851b7f2286902
|
4
|
+
data.tar.gz: a3591e0ba67af0a20320b668e0a07de7b49e2a02d988aa82011cde91b7ef8d44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3a637beb971c843d05c64e2af01c3b9a05689bb61ad634cf870ce31538a6a54f717c9206e1be631db6c0b1b22e15c91d821254d5a8a6abf5f5d57b5eea8a48b
|
7
|
+
data.tar.gz: f64f65b6cc2f269ba47c9e95a8833ec720acffd36c9fefd1b18265782563f477fb85fb73bc0d656582d55b57e7f1eb2a23158cd222c26e1bbaf35e8e6aefdd84
|
data/Gemfile.lock
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
factory_bot_factory (
|
4
|
+
factory_bot_factory (1.2.0)
|
5
|
+
factory_bot (>= 4.8.2)
|
5
6
|
|
6
7
|
GEM
|
7
8
|
remote: https://rubygems.org/
|
8
9
|
specs:
|
10
|
+
activemodel (6.1.4.1)
|
11
|
+
activesupport (= 6.1.4.1)
|
12
|
+
activerecord (6.1.4.1)
|
13
|
+
activemodel (= 6.1.4.1)
|
14
|
+
activesupport (= 6.1.4.1)
|
9
15
|
activesupport (6.1.4.1)
|
10
16
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
11
17
|
i18n (>= 1.6, < 2)
|
@@ -26,7 +32,7 @@ GEM
|
|
26
32
|
pry (0.13.1)
|
27
33
|
coderay (~> 1.1)
|
28
34
|
method_source (~> 1.0)
|
29
|
-
rake (
|
35
|
+
rake (13.0.6)
|
30
36
|
rspec (3.10.0)
|
31
37
|
rspec-core (~> 3.10.0)
|
32
38
|
rspec-expectations (~> 3.10.0)
|
@@ -40,6 +46,7 @@ GEM
|
|
40
46
|
diff-lcs (>= 1.2.0, < 2.0)
|
41
47
|
rspec-support (~> 3.10.0)
|
42
48
|
rspec-support (3.10.2)
|
49
|
+
sqlite3 (1.4.2)
|
43
50
|
tzinfo (2.0.4)
|
44
51
|
concurrent-ruby (~> 1.0)
|
45
52
|
zeitwerk (2.4.2)
|
@@ -48,13 +55,14 @@ PLATFORMS
|
|
48
55
|
ruby
|
49
56
|
|
50
57
|
DEPENDENCIES
|
51
|
-
|
52
|
-
|
58
|
+
activerecord (> 5.0.0.1)
|
59
|
+
bundler (>= 2.2.10)
|
53
60
|
factory_bot_factory!
|
54
61
|
faker
|
55
62
|
pry (~> 0.13.1)
|
56
|
-
rake (
|
63
|
+
rake (>= 11.2.2)
|
57
64
|
rspec (~> 3.0)
|
65
|
+
sqlite3
|
58
66
|
|
59
67
|
BUNDLED WITH
|
60
|
-
|
68
|
+
2.2.27
|
data/README.md
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# Factory Bot Factory
|
2
2
|
|
3
|
+
[](https://rubygems.org/gems/factory_bot_factory) 
|
4
|
+
|
3
5
|
A Gem that helps you generate FactoryBot's Factory file from exsiting Hash, OpenStruct or ActiveModels.
|
4
6
|
|
5
|
-
|
7
|
+

|
6
8
|
|
7
9
|
## Installation
|
8
10
|
|
@@ -12,52 +14,40 @@ gem 'factory_bot_factory'
|
|
12
14
|
|
13
15
|
And then execute:
|
14
16
|
|
15
|
-
|
17
|
+
```
|
18
|
+
$ bundle
|
19
|
+
```
|
16
20
|
|
17
21
|
Or install it yourself as:
|
18
22
|
|
19
|
-
|
23
|
+
```
|
24
|
+
$ gem install factory_bot_factory
|
25
|
+
```
|
20
26
|
|
21
27
|
|
22
28
|
## Quick Demo
|
23
29
|
|
24
|
-
- Build a Hash Factory
|
25
|
-
|
26
30
|
```ruby
|
27
31
|
require 'factory_bot_factory'
|
28
32
|
|
29
|
-
|
30
|
-
puts FactoryBotFactory.build(
|
31
|
-
|
32
|
-
|
33
|
-
FactoryBot.define do
|
34
|
-
factory :order_hash, class: Hash do
|
35
|
-
id { 1 }
|
36
|
-
tags do
|
37
|
-
[
|
38
|
-
"tag1",
|
39
|
-
"tag2"
|
40
|
-
]
|
41
|
-
end
|
42
|
-
address do
|
43
|
-
{
|
44
|
-
"country": "US"
|
45
|
-
}
|
46
|
-
end
|
47
|
-
initialize_with { attributes }
|
48
|
-
end
|
49
|
-
end
|
33
|
+
puts FactoryBotFactory.build({ id: 1 })
|
34
|
+
puts FactoryBotFactory.build(OpenStruct.new(id: 1))
|
35
|
+
puts FactoryBotFactory.build(User.last)
|
36
|
+
puts FactoryBotFactory.build(User.new)
|
50
37
|
```
|
51
38
|
|
52
|
-
|
39
|
+
|
40
|
+
## More Options
|
41
|
+
|
42
|
+
- `nested_level` - Build Nested Hash Factory (only support Hash and OpenStruct)
|
53
43
|
|
54
44
|
```ruby
|
55
45
|
data = { id: 1, tags: ["tag1", "tag2"], address: { country: "US" } }
|
56
|
-
puts FactoryBotFactory.build(
|
46
|
+
puts FactoryBotFactory.build(data, nested_level: 2)
|
57
47
|
|
58
48
|
# output
|
59
49
|
FactoryBot.define do
|
60
|
-
factory :
|
50
|
+
factory :hash, class: Hash do
|
61
51
|
id { 1 }
|
62
52
|
tags do
|
63
53
|
[
|
@@ -65,52 +55,77 @@ FactoryBot.define do
|
|
65
55
|
"tag2"
|
66
56
|
]
|
67
57
|
end
|
68
|
-
address { build(:
|
58
|
+
address { build(:hash_address) }
|
69
59
|
initialize_with { attributes }
|
70
60
|
end
|
71
61
|
|
72
|
-
factory :
|
62
|
+
factory :hash_address, class: Hash do
|
73
63
|
country { "US" }
|
74
64
|
initialize_with { attributes }
|
75
65
|
end
|
76
66
|
end
|
77
67
|
```
|
78
68
|
|
79
|
-
- Export
|
69
|
+
- `file_path` - Export output as file somewhere
|
80
70
|
|
81
71
|
```ruby
|
82
|
-
FactoryBotFactory.build(
|
72
|
+
FactoryBotFactory.build(data, file_path: "spec/factories/hash.rb")
|
83
73
|
|
84
74
|
require 'factory_bot'
|
85
75
|
FactoryBot.reload
|
86
|
-
FactoryBot.build(:
|
87
|
-
|
76
|
+
FactoryBot.build(:hash, id: 2)
|
88
77
|
```
|
89
78
|
|
90
|
-
|
79
|
+
- `factory_name` - Specify Factory Name
|
91
80
|
|
92
|
-
- Hash
|
93
81
|
```ruby
|
94
|
-
FactoryBotFactory.build(
|
95
|
-
```
|
82
|
+
puts FactoryBotFactory.build({ id: 1 }, factory_name: 'order')
|
96
83
|
|
97
|
-
|
98
|
-
|
99
|
-
|
84
|
+
# output
|
85
|
+
FactoryBot.define do
|
86
|
+
factory :order, class: Hash do
|
87
|
+
id { 1 }
|
88
|
+
initialize_with { attributes }
|
89
|
+
end
|
90
|
+
end
|
100
91
|
```
|
101
92
|
|
102
|
-
-
|
93
|
+
- `klass` - Specify Output Data Structure: Hash, OpenStruct and your ActiveModel or ActiveRecord Model
|
94
|
+
|
95
|
+
You can convert your Hash object to OpenStruct factory.
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
puts FactoryBotFactory.build({ id: 1 }, factory_name: 'order', klass: OpenStruct)
|
99
|
+
|
100
|
+
# output
|
101
|
+
FactoryBot.define do
|
102
|
+
factory :order, class: OpenStruct do
|
103
|
+
id { 1 }
|
104
|
+
to_create {}
|
105
|
+
end
|
106
|
+
end
|
103
107
|
```
|
104
|
-
|
108
|
+
|
109
|
+
## Configuration
|
110
|
+
|
111
|
+
- Default factory path
|
112
|
+
|
113
|
+
By configuring `factory_path`, it allows file auto-generation without specifying `file_path`.
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
FactoryBotFactory.configure do |config|
|
117
|
+
config.factory_path = 'spec/factories'
|
118
|
+
end
|
105
119
|
```
|
106
120
|
|
107
|
-
|
121
|
+
- Customize your own converter:
|
108
122
|
|
109
|
-
|
123
|
+
Converter should respond to `call` method and return single or array of executable values.
|
110
124
|
|
111
125
|
```ruby
|
112
126
|
FactoryBotFactory.configure do |config|
|
113
|
-
config.
|
127
|
+
config.numeric_converter = Proc.new { |k, v| 'rand(99)' }
|
128
|
+
config.string_converter = Proc.new do |k, v|
|
114
129
|
if v.to_s.match?(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/)
|
115
130
|
'Random.uuid()'
|
116
131
|
elsif k.to_s.include?('name')
|
@@ -121,20 +136,20 @@ FactoryBotFactory.configure do |config|
|
|
121
136
|
end
|
122
137
|
end
|
123
138
|
|
124
|
-
FactoryBotFactory.build(
|
139
|
+
FactoryBotFactory.build({ name: 'My Name', id: "de9515ee-006e-4a28-8af3-e88a5c771b93", age: 10 })
|
125
140
|
|
126
141
|
# output
|
127
142
|
FactoryBot.define do
|
128
|
-
factory :
|
143
|
+
factory :hash, class: Hash do
|
129
144
|
name { Faker::Name.name }
|
130
145
|
id { Random.uuid() }
|
146
|
+
age { rand(99) }
|
131
147
|
initialize_with { attributes }
|
132
148
|
end
|
133
149
|
end
|
134
150
|
```
|
135
151
|
|
136
|
-
See
|
137
|
-
|
152
|
+
See more converters [Here](https://github.com/cdragon1116/factory_bot_factory/blob/main/lib/factory_bot_factory/config.rb#L3-L13)
|
138
153
|
|
139
154
|
## Contributing
|
140
155
|
|
data/factory_bot_factory.gemspec
CHANGED
@@ -23,11 +23,15 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.bindir = "exe"
|
24
24
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
25
|
spec.require_paths = ["lib"]
|
26
|
+
spec.required_ruby_version = '>= 1.8.6'
|
26
27
|
|
27
|
-
spec.add_development_dependency "bundler", "
|
28
|
-
spec.add_development_dependency
|
28
|
+
spec.add_development_dependency "bundler", ">= 2.2.10"
|
29
|
+
spec.add_development_dependency 'rake', '>= 11.2.2'
|
29
30
|
spec.add_development_dependency "pry", '~> 0.13.1'
|
30
31
|
spec.add_development_dependency "rspec", "~> 3.0"
|
31
|
-
spec.add_development_dependency "factory_bot"
|
32
32
|
spec.add_development_dependency "faker"
|
33
|
+
spec.add_development_dependency "activerecord", "> 5.0.0.1"
|
34
|
+
spec.add_development_dependency "sqlite3"
|
35
|
+
|
36
|
+
spec.add_dependency "factory_bot", '>= 4.8.2'
|
33
37
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module FactoryBotFactory
|
5
|
+
class Attribute
|
6
|
+
attr_reader :key, :value, :options
|
7
|
+
|
8
|
+
def initialize(key, value, options = {})
|
9
|
+
@key = key
|
10
|
+
@value = value
|
11
|
+
@options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
def build
|
15
|
+
options = [key, value, options]
|
16
|
+
|
17
|
+
values = if value.nil? || value == "null"
|
18
|
+
FactoryBotFactory.config.nil_converter.call(*options)
|
19
|
+
elsif value.is_a?(DateTime) || value.is_a?(Time)
|
20
|
+
FactoryBotFactory.config.date_time_converter.call(*options)
|
21
|
+
elsif value.is_a?(Date)
|
22
|
+
FactoryBotFactory.config.date_converter.call(*options)
|
23
|
+
elsif value.is_a?(String) || value.is_a?(Symbol)
|
24
|
+
FactoryBotFactory.config.string_converter.call(*options)
|
25
|
+
elsif value.is_a?(Numeric)
|
26
|
+
FactoryBotFactory.config.numeric_converter.call(*options)
|
27
|
+
elsif value.is_a?(BigDecimal)
|
28
|
+
FactoryBotFactory.config.big_decimal_converter.call(*options)
|
29
|
+
elsif value.is_a?(Hash)
|
30
|
+
FactoryBotFactory.config.hash_converter.call(*options)
|
31
|
+
elsif value.is_a?(Array)
|
32
|
+
FactoryBotFactory.config.array_converter.call(*options)
|
33
|
+
else value.is_a?(OpenStruct)
|
34
|
+
FactoryBotFactory.config.open_struct_converter.call(*options)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,23 +1,35 @@
|
|
1
1
|
module FactoryBotFactory
|
2
2
|
class Base
|
3
3
|
class << self
|
4
|
-
def build(
|
4
|
+
def build(data, options = {})
|
5
|
+
options[:klass] ||= data.class
|
6
|
+
options[:factory_name] ||= data.class.name.downcase
|
7
|
+
|
8
|
+
raise ArgumentError, "Unsupported data type. Supported format: Hash, OpenStruct, ActiveRecord instance." unless valid_data?(data)
|
5
9
|
raise NestedToDeepError, 'Only support 5 nested levels' if options[:nested_level].to_i > 5
|
6
10
|
|
7
|
-
factory(klass, data).new(options
|
8
|
-
rescue => e
|
9
|
-
puts "Please check your input data and make sure you pass supported type of factory."
|
11
|
+
factory(options[:klass], data).new(options).generate(data)
|
10
12
|
end
|
11
13
|
|
12
14
|
private
|
13
15
|
|
14
16
|
def factory(klass, data)
|
15
|
-
if
|
17
|
+
if active_record?(data) && klass == data.class
|
18
|
+
Object.const_get("FactoryBotFactory::ActiveRecordFactory")
|
19
|
+
elsif data.respond_to?(:attributes) && klass == data.class
|
16
20
|
Object.const_get("FactoryBotFactory::ModelFactory")
|
17
21
|
else
|
18
22
|
Object.const_get("FactoryBotFactory::#{klass}Factory")
|
19
23
|
end
|
20
24
|
end
|
25
|
+
|
26
|
+
def valid_data?(data)
|
27
|
+
data.is_a?(Hash) || data.is_a?(OpenStruct) || data.respond_to?(:attributes)
|
28
|
+
end
|
29
|
+
|
30
|
+
def active_record?(data)
|
31
|
+
Object.const_defined?("ActiveRecord::Base") && data.class.is_a?(ActiveRecord::Base)
|
32
|
+
end
|
21
33
|
end
|
22
34
|
end
|
23
35
|
end
|
@@ -3,16 +3,30 @@ module FactoryBotFactory
|
|
3
3
|
DEFAULT_CONVERTERS = {
|
4
4
|
hash_converter: Converters::HashConverter,
|
5
5
|
string_converter: Converters::StringConverter,
|
6
|
-
|
6
|
+
numeric_converter: Converters::NumericConverter,
|
7
|
+
big_decimal_converter: Converters::NumericConverter,
|
7
8
|
open_struct_converter: Converters::HashConverter,
|
8
|
-
nil_converter: Converters::NilConverter
|
9
|
+
nil_converter: Converters::NilConverter,
|
10
|
+
date_time_converter: Converters::DateTimeConverter,
|
11
|
+
date_converter: Converters::StringConverter,
|
12
|
+
array_converter: Converters::HashConverter
|
9
13
|
}
|
10
14
|
|
11
|
-
|
15
|
+
DEFAULT_OPTIONS = {
|
16
|
+
factory_path: nil,
|
17
|
+
print_output: false
|
18
|
+
}.merge(DEFAULT_CONVERTERS)
|
19
|
+
|
20
|
+
attr_accessor *DEFAULT_OPTIONS.keys
|
12
21
|
|
13
22
|
def initialize(options = {})
|
14
|
-
options =
|
23
|
+
options = DEFAULT_OPTIONS.merge(options)
|
15
24
|
options.each { |k, v| instance_variable_set(:"@#{k}", v) }
|
16
25
|
end
|
26
|
+
|
27
|
+
def factory_path=(path)
|
28
|
+
path = path[0..-2] if path&.end_with?("/")
|
29
|
+
@factory_path = path
|
30
|
+
end
|
17
31
|
end
|
18
32
|
end
|
@@ -1,52 +1,76 @@
|
|
1
|
+
require "factory_bot_factory/file_writer"
|
2
|
+
|
1
3
|
module FactoryBotFactory
|
2
4
|
class BaseFactory
|
5
|
+
|
6
|
+
attr_reader :file_path
|
7
|
+
|
3
8
|
def initialize(options = {})
|
4
9
|
@factory_name = options[:factory_name]
|
5
|
-
@file_path = options[:file_path]
|
10
|
+
@file_path = build_file_path(options[:file_path])
|
6
11
|
@nested_level = [(options[:nested_level] || 1), 5].min
|
7
12
|
@line_writer = LineWriter.new(options)
|
8
13
|
@factory_queue = []
|
9
14
|
end
|
10
15
|
|
11
16
|
def generate(data)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
push_to_factory_queue(@factory_name, data, @nested_level)
|
18
|
+
output = []
|
19
|
+
|
20
|
+
loop do
|
21
|
+
factory_option = @factory_queue.shift
|
22
|
+
output += build_factory(*factory_option)
|
23
|
+
break if @factory_queue.empty?
|
24
|
+
output << LineWriter::WHITE_SPACE
|
25
|
+
end
|
26
|
+
|
27
|
+
if @file_path
|
28
|
+
write_file(output)
|
29
|
+
else
|
30
|
+
output = LineWriter.wrap_definition { output }
|
24
31
|
end
|
25
32
|
|
26
|
-
output = output.join(LineWriter::NEW_LINE)
|
27
|
-
File.open(@file_path, 'w') {|f| f.write(output) } if @file_path
|
28
33
|
output
|
34
|
+
ensure
|
35
|
+
FactoryBot.reload if Object.const_defined?("FactoryBot")
|
36
|
+
puts(output) if FactoryBotFactory.config.print_output
|
29
37
|
end
|
30
38
|
|
31
39
|
private
|
32
40
|
|
33
|
-
def
|
41
|
+
def build_file_path(input_path = nil)
|
42
|
+
return input_path if input_path
|
43
|
+
return if FactoryBotFactory.config.factory_path.nil?
|
44
|
+
FactoryBotFactory.config.factory_path + "/#{@factory_name}.rb"
|
45
|
+
end
|
46
|
+
|
47
|
+
def write_file(output)
|
48
|
+
validate_existing_factory!
|
49
|
+
FileWriter.new(@file_path).write(output)
|
50
|
+
end
|
51
|
+
|
52
|
+
def validate_existing_factory!
|
53
|
+
return unless Object.const_defined?("FactoryBot") && FactoryBot.factories.registered?(@factory_name.to_s)
|
54
|
+
raise FactoryExistsError, "[FactoryBotFactory] Factory #{@factory_name} already exists. Please check your existing factories."
|
55
|
+
end
|
56
|
+
|
57
|
+
def build_factory(name, value, level, options)
|
34
58
|
raise "This method should be implemented in a subclass"
|
35
59
|
end
|
36
60
|
|
37
61
|
def build_nested_attribute(name, key, value, current_level, max_level)
|
38
|
-
return @line_writer.
|
62
|
+
return @line_writer.write(key, value) if current_level == max_level
|
39
63
|
|
40
64
|
if is_key_value_pair?(value)
|
41
|
-
push_to_factory_queue(name
|
42
|
-
@line_writer.
|
65
|
+
push_to_factory_queue("#{name}_#{key}", value, max_level - 1)
|
66
|
+
@line_writer.write_nested_line(name, key)
|
43
67
|
else
|
44
|
-
@line_writer.
|
68
|
+
@line_writer.write(key, value)
|
45
69
|
end
|
46
70
|
end
|
47
71
|
|
48
|
-
def push_to_factory_queue(name,
|
49
|
-
@factory_queue.push([
|
72
|
+
def push_to_factory_queue(name, value, max_level, options = {})
|
73
|
+
@factory_queue.push([name, value, max_level, options])
|
50
74
|
end
|
51
75
|
|
52
76
|
def is_key_value_pair?(value)
|
@@ -1,6 +1,8 @@
|
|
1
|
+
require 'factory_bot_factory/factories/base_factory.rb'
|
2
|
+
|
1
3
|
module FactoryBotFactory
|
2
4
|
class HashFactory < BaseFactory
|
3
|
-
def build_factory(name, value, level)
|
5
|
+
def build_factory(name, value, level, _options = {})
|
4
6
|
output = LineWriter.wrap_factory(name, 'Hash') do
|
5
7
|
inner_output = []
|
6
8
|
value = value.attributes if value.respond_to?(:attributes)
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module FactoryBotFactory
|
2
2
|
class ModelFactory < BaseFactory
|
3
|
-
def build_factory(name, value, level)
|
3
|
+
def build_factory(name, value, level, _options = {})
|
4
4
|
output = LineWriter.wrap_factory(name, value.class.name) do
|
5
5
|
inner_output = []
|
6
6
|
value.attributes.each do |key, value|
|
7
|
-
inner_output += build_nested_attribute(
|
7
|
+
inner_output += build_nested_attribute(name, key, value, 1, 1)
|
8
8
|
end
|
9
9
|
inner_output
|
10
10
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
+
require 'factory_bot_factory/factories/base_factory.rb'
|
2
|
+
|
1
3
|
module FactoryBotFactory
|
2
4
|
class OpenStructFactory < BaseFactory
|
3
|
-
def build_factory(name, value, level)
|
5
|
+
def build_factory(name, value, level, _options = {})
|
4
6
|
output = LineWriter.wrap_factory(name, 'OpenStruct') do
|
5
7
|
inner_output = []
|
6
8
|
value = value.attributes if value.respond_to?(:attributes)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'factory_bot_factory/logger'
|
2
|
+
|
3
|
+
module FactoryBotFactory
|
4
|
+
class FileWriter
|
5
|
+
attr_reader :file_paht, :output
|
6
|
+
|
7
|
+
def initialize(file_path)
|
8
|
+
@file_path = file_path
|
9
|
+
end
|
10
|
+
|
11
|
+
def write(output)
|
12
|
+
if File.file?(@file_path)
|
13
|
+
output = regroup_existing_lines(output)
|
14
|
+
message = "New Factory successfully write to an existing file."
|
15
|
+
else
|
16
|
+
output = LineWriter.wrap_definition { output }
|
17
|
+
message = "New Factory successfully write to a new file."
|
18
|
+
end
|
19
|
+
|
20
|
+
FactoryBot.reload if Object.const_defined?("FactoryBot")
|
21
|
+
|
22
|
+
File.open(@file_path, 'w') {|f| f.write(output) }
|
23
|
+
Logger.alert(message + "\nPlease check your file in #{@file_path}")
|
24
|
+
output
|
25
|
+
end
|
26
|
+
|
27
|
+
def regroup_existing_lines(output)
|
28
|
+
File.read(@file_path) + LineWriter::NEW_LINE + LineWriter.wrap_definition { output }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,34 +1,20 @@
|
|
1
|
+
require "factory_bot_factory/attribute"
|
2
|
+
|
1
3
|
module FactoryBotFactory
|
2
4
|
class LineWriter
|
3
5
|
NEW_LINE = "\n".freeze
|
4
6
|
WHITE_SPACE = "\s".freeze
|
5
7
|
INDENT_SPACE = 2
|
6
8
|
|
7
|
-
attr_reader :hash_converter, :string_converter, :numertic_converter, :open_struct_converter, :nil_converter
|
8
|
-
|
9
9
|
def initialize(options = {})
|
10
|
-
@options
|
10
|
+
@options = options
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
16
|
-
values = if value.nil? || value == "null"
|
17
|
-
FactoryBotFactory.config.nil_converter.call(*options)
|
18
|
-
elsif value.is_a?(String) || value.is_a?(Symbol)
|
19
|
-
FactoryBotFactory.config.string_converter.call(*options)
|
20
|
-
elsif value.is_a?(Numeric)
|
21
|
-
FactoryBotFactory.config.numertic_converter.call(*options)
|
22
|
-
elsif value.is_a?(Hash) || value.is_a?(Array)
|
23
|
-
FactoryBotFactory.config.hash_converter.call(*options)
|
24
|
-
else value.is_a?(OpenStruct)
|
25
|
-
FactoryBotFactory.config.open_struct_converter.call(*options)
|
26
|
-
end
|
27
|
-
|
28
|
-
wrap_block(key, values)
|
13
|
+
def write(key, value)
|
14
|
+
wrap_block(key, Attribute.new(key, value, @options).build)
|
29
15
|
end
|
30
16
|
|
31
|
-
def
|
17
|
+
def write_nested_line(prefix, key)
|
32
18
|
["#{key} { build(:#{prefix}_#{key}) }"]
|
33
19
|
end
|
34
20
|
|
@@ -49,11 +35,19 @@ module FactoryBotFactory
|
|
49
35
|
"#{WHITE_SPACE * INDENT_SPACE * level}#{value}"
|
50
36
|
end
|
51
37
|
|
38
|
+
def indent_lines(level, value)
|
39
|
+
value.map { |s| indent(level, s) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def join(lines)
|
43
|
+
lines.join(LineWriter::NEW_LINE)
|
44
|
+
end
|
45
|
+
|
52
46
|
def wrap_definition(&_block)
|
53
47
|
output = ["FactoryBot.define do"]
|
54
48
|
output += yield.map { |s| indent(1, s) }
|
55
49
|
output << "end"
|
56
|
-
output
|
50
|
+
output.join(LineWriter::NEW_LINE)
|
57
51
|
end
|
58
52
|
|
59
53
|
def wrap_factory(name, target, &_block)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module FactoryBotFactory
|
2
|
+
class Logger
|
3
|
+
PREFIX = "[FactoryBotFactory Logger]".freeze
|
4
|
+
|
5
|
+
def self.alert(message)
|
6
|
+
message = message.split("\n").map { |m| "#{PREFIX} #{m}" }.join("\n")
|
7
|
+
puts ColorString.new(message).yellow
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class ColorString < String
|
13
|
+
# colorization
|
14
|
+
def colorize(color_code)
|
15
|
+
"\e[#{color_code}m#{self}\e[0m"
|
16
|
+
end
|
17
|
+
|
18
|
+
def red
|
19
|
+
colorize(31)
|
20
|
+
end
|
21
|
+
|
22
|
+
def green
|
23
|
+
colorize(32)
|
24
|
+
end
|
25
|
+
|
26
|
+
def yellow
|
27
|
+
colorize(33)
|
28
|
+
end
|
29
|
+
|
30
|
+
def blue
|
31
|
+
colorize(34)
|
32
|
+
end
|
33
|
+
|
34
|
+
def pink
|
35
|
+
colorize(35)
|
36
|
+
end
|
37
|
+
|
38
|
+
def light_blue
|
39
|
+
colorize(36)
|
40
|
+
end
|
41
|
+
end
|
data/lib/factory_bot_factory.rb
CHANGED
@@ -2,21 +2,26 @@ require "json"
|
|
2
2
|
require "factory_bot_factory/version"
|
3
3
|
|
4
4
|
# Load all Factories and Converters
|
5
|
-
Dir.glob("#{File.dirname(__FILE__)}/factory_bot_factory/factories/*").each { |file| require(file) }
|
6
5
|
Dir.glob("#{File.dirname(__FILE__)}/factory_bot_factory/converters/*").each { |file| require(file) }
|
6
|
+
require "factory_bot_factory/config"
|
7
7
|
|
8
|
-
require 'factory_bot_factory/line_writer.rb'
|
9
8
|
require 'factory_bot_factory/base.rb'
|
10
|
-
require
|
9
|
+
require 'factory_bot_factory/line_writer.rb'
|
10
|
+
require 'factory_bot_factory/file_writer.rb'
|
11
|
+
Dir.glob("#{File.dirname(__FILE__)}/factory_bot_factory/factories/*").each { |file| require(file) }
|
12
|
+
|
11
13
|
|
12
14
|
module FactoryBotFactory
|
13
15
|
class Error < StandardError; end
|
14
16
|
class NestedToDeepError < Error; end
|
17
|
+
class FileExistsError < ::FactoryBotFactory::Error; end
|
18
|
+
class FactoryExistsError < ::FactoryBotFactory::Error; end
|
15
19
|
|
16
20
|
class << self
|
17
|
-
def build(
|
21
|
+
def build(data, options = {})
|
18
22
|
configure
|
19
|
-
|
23
|
+
|
24
|
+
Base.build(data, options)
|
20
25
|
end
|
21
26
|
|
22
27
|
def configure
|
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: factory_bot_factory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- cdragon
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-09-
|
11
|
+
date: 2021-09-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 2.2.10
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 2.2.10
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 11.2.2
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 11.2.2
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: pry
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '3.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: faker
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -81,7 +81,21 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: activerecord
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 5.0.0.1
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 5.0.0.1
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: sqlite3
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
101
|
- - ">="
|
@@ -94,6 +108,20 @@ dependencies:
|
|
94
108
|
- - ">="
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: factory_bot
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 4.8.2
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 4.8.2
|
97
125
|
description: A Gem that generate FactoryBot's Factory file from exsiting Hash, OpenStruct
|
98
126
|
or Models.
|
99
127
|
email: cdragon1116@gmail.com
|
@@ -114,17 +142,22 @@ files:
|
|
114
142
|
- bin/setup
|
115
143
|
- factory_bot_factory.gemspec
|
116
144
|
- lib/factory_bot_factory.rb
|
145
|
+
- lib/factory_bot_factory/attribute.rb
|
117
146
|
- lib/factory_bot_factory/base.rb
|
118
147
|
- lib/factory_bot_factory/config.rb
|
148
|
+
- lib/factory_bot_factory/converters/data_time_converter.rb
|
119
149
|
- lib/factory_bot_factory/converters/hash_converter.rb
|
120
150
|
- lib/factory_bot_factory/converters/nil_converter.rb
|
121
151
|
- lib/factory_bot_factory/converters/numeric_converter.rb
|
122
152
|
- lib/factory_bot_factory/converters/string_converter.rb
|
153
|
+
- lib/factory_bot_factory/factories/active_record_factory.rb
|
123
154
|
- lib/factory_bot_factory/factories/base_factory.rb
|
124
155
|
- lib/factory_bot_factory/factories/hash_factory.rb
|
125
156
|
- lib/factory_bot_factory/factories/model_factory.rb
|
126
157
|
- lib/factory_bot_factory/factories/open_struct_factory.rb
|
158
|
+
- lib/factory_bot_factory/file_writer.rb
|
127
159
|
- lib/factory_bot_factory/line_writer.rb
|
160
|
+
- lib/factory_bot_factory/logger.rb
|
128
161
|
- lib/factory_bot_factory/version.rb
|
129
162
|
homepage: https://github.com/cdragon1116/factory_bot_factory
|
130
163
|
licenses:
|
@@ -138,7 +171,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
138
171
|
requirements:
|
139
172
|
- - ">="
|
140
173
|
- !ruby/object:Gem::Version
|
141
|
-
version:
|
174
|
+
version: 1.8.6
|
142
175
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
176
|
requirements:
|
144
177
|
- - ">="
|