industrialist 0.4.0 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 858f0f4e068299c8eab65bf53cc4b78b5d582ad1a36a81bd85c41654c21e9855
4
- data.tar.gz: ed03501fc2ab8f74f5ac29d1e47675ac77977e5c859a5a9ddd9701b28afdbc70
3
+ metadata.gz: 7bf85f2b3f9c6e8cc3544f300a89d48a9c2f14474346b3241724cb332b10eaad
4
+ data.tar.gz: 6b94cbc0377996523a94f3a1a43c47b0cd04f80ddee3dba44ef4714a44e58dac
5
5
  SHA512:
6
- metadata.gz: 751a1bbef0a2f80b1936d0b23608880fd5a3cec7a4dcdeea0d8f705c96a4c86d37c5576364cf484159054be6845deadb3bb038fb298daa959d96fe7add723877
7
- data.tar.gz: 8ec6e11e6851d7f17a0f7e92e3ebb6e246daab3b747534cf365ea623a1d4ff3390a202cdb92d7e815320b3062439fe82a0981a06837e19c0f93d98822f35e170
6
+ metadata.gz: 4dc4590b03d9f2937814364ed9821f9eba370795e23733a4f8220d62763aed772083fd22761cbba1870d054c77a46faf3288b0603eb81aa44cf1949d55568737
7
+ data.tar.gz: d9f688cc1227649418fa59d4e0dc029dff07cf04db933199a40013a907f46b6fcda2de1c9be684332587889baf76915ba8e71e76cf49fa8a7aa8169e91310efc
data/.gitignore CHANGED
@@ -9,3 +9,5 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+
13
+ .DS_Store
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- industrialist (0.4.0)
4
+ industrialist (1.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -76,12 +76,11 @@ You can find a deeper dive into the motivations behind Industrialst [here](https
76
76
 
77
77
  ## Usage
78
78
 
79
- Industrialist creates factories for you. Just include the Manufacturable module in a base class and call `create_factory` with a name. Industrialist also allows children of the base class to register themselves with the factory by specifying their corresponding key.
79
+ Industrialist creates factories for you. Just extend the Manufacturable module in a base class. This will register a manufacturable type based on the class name. Children of the base class can register themselves with the factory by specifying their corresponding key. To build an instance specify the manufacturable type and key.
80
80
 
81
81
  ```ruby
82
82
  class Automobile
83
- include Industrialist::Manufacturable
84
- create_factory :AutomobileFactory
83
+ extend Industrialist::Manufacturable
85
84
  end
86
85
 
87
86
  class Sedan < Automobile
@@ -92,7 +91,7 @@ class Coupe < Automobile
92
91
  corresponds_to :coupe
93
92
  end
94
93
 
95
- AutomobileFactory.build(:sedan) # => #<Sedan:0x00007ff64d88ce58>
94
+ Industrialist.build(:automobile, :sedan) # => #<Sedan:0x00007ff64d88ce58>
96
95
  ```
97
96
 
98
97
  Manufacturable classes may also correspond to multiple keys:
@@ -107,29 +106,27 @@ end
107
106
  By default, Industrialist factories will return `nil` when built with an unregistered key. If you would instead prefer a default object, you can designate a `manufacturable_default`.
108
107
 
109
108
  ```ruby
110
- class Airplane
111
- include Industrialist::Manufacturable
112
- create_factory :AirplaneFactory
109
+ class Plane
110
+ extend Industrialist::Manufacturable
113
111
  end
114
112
 
115
- class Biplane < Airplane
113
+ class Biplane < Plane
116
114
  manufacturable_default
117
115
  corresponds_to :biplane
118
116
  end
119
117
 
120
- class FighterJet < Airplane
118
+ class FighterJet < Plane
121
119
  corresponds_to :fighter
122
120
  end
123
121
 
124
- AirplaneFactory.build(:plane) # => #<Biplane:0x00007ffcd4165610>
122
+ Industrialist.build(:plane, :bomber) # => #<Biplane:0x00007ffcd4165610>
125
123
  ```
126
124
 
127
- Finally, Industrialist will accept any Ruby object as a key, which is handy when you need to define more complex keys. For example, you could use a hash:
125
+ Industrialist can accept any Ruby object as a key, which is handy when you need to define more complex keys. For example, you could use a hash:
128
126
 
129
127
  ```ruby
130
128
  class Train
131
- include Industrialist::Manufacturable
132
- create_factory :TrainFactory
129
+ extend Industrialist::Manufacturable
133
130
  end
134
131
 
135
132
  class SteamEngine < Train
@@ -153,12 +150,24 @@ class Sleeper < Train
153
150
  end
154
151
 
155
152
  def train_car(role, type)
156
- TrainFactory.build(role => type)
153
+ Industrialist.build(:train, role => type)
157
154
  end
158
155
 
159
156
  train_car(:engine, :diesel) # => #<Diesel:0x00007ff64f846640>
160
157
  ```
161
158
 
159
+ For convenience, you can also define your own factory classes.
160
+
161
+ ```ruby
162
+ class AutomobileFactory
163
+ extend Industrialist::Factory
164
+
165
+ manufactures Automobile
166
+ end
167
+
168
+ AutomobileFactory.build(:sedan) # => #<Sedan:0x00007ff64d88ce58>
169
+ ```
170
+
162
171
  ## Installation
163
172
 
164
173
  Add this line to your application's Gemfile:
@@ -175,16 +184,13 @@ Or install it yourself as:
175
184
 
176
185
  $ gem install industrialist
177
186
 
178
- If you are using Industrialist with Rails, you'll need to preload your manufacturable objects in the development and test environments in an intializer, like this:
187
+ If you are using Industrialist with Rails, you'll need to
179
188
 
180
189
  ```ruby
181
- def require_factory(class_type)
182
- Dir[Rails.root.join('app', "#{class_type}", '**', '*.rb').to_s].each { |file| require file }
183
- end
184
-
185
- if %w(development test).include?(Rails.env)
186
- require_factory('automobiles')
187
- require_factory('books')
190
+ Industrialist.config do |config|
191
+ config.manufacturable_paths << Rails.root.join('app', 'planes')
192
+ config.manufacturable_paths << Rails.root.join('app', 'trains')
193
+ config.manufacturable_paths << Rails.root.join('app', 'automobiles')
188
194
  end
189
195
  ```
190
196
 
@@ -0,0 +1,7 @@
1
+ class Airplane
2
+ extend Industrialist::Manufacturable
3
+
4
+ def info
5
+ puts self.class.name
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'airplane'
2
+
3
+ class AirplaneFactory
4
+ extend Industrialist::Factory
5
+
6
+ manufactures Airplane
7
+ end
@@ -0,0 +1,6 @@
1
+ require_relative 'airplane'
2
+
3
+ class F16Tomcat < Airplane
4
+ corresponds_to :f16
5
+ corresponds_to :tomcat
6
+ end
@@ -0,0 +1,6 @@
1
+ require_relative 'airplane'
2
+
3
+ class P51Mustang < Airplane
4
+ corresponds_to :p51
5
+ corresponds_to :mustang
6
+ end
data/example/app.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'industrialist'
2
+
3
+ Industrialist.config do |config|
4
+ config.manufacturable_paths << "#{File.dirname(__FILE__)}/automobiles"
5
+ config.manufacturable_paths << "#{File.dirname(__FILE__)}/airplanes"
6
+ end
7
+
8
+ AutomobileFactory.build(:sedan).info
9
+ AutomobileFactory.build(:convertible).info
10
+ AutomobileFactory.build(:cabriolet).info
11
+
12
+ AirplaneFactory.build(:f16).info
13
+ AirplaneFactory.build(:tomcat).info
14
+ AirplaneFactory.build(:p51).info
15
+ AirplaneFactory.build(:mustang).info
@@ -0,0 +1,7 @@
1
+ class Automobile
2
+ extend Industrialist::Manufacturable
3
+
4
+ def info
5
+ puts self.class.name
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'automobile'
2
+
3
+ class AutomobileFactory
4
+ extend Industrialist::Factory
5
+
6
+ manufactures Automobile
7
+ end
@@ -0,0 +1,6 @@
1
+ require_relative 'automobile'
2
+
3
+ class Convertible < Automobile
4
+ corresponds_to :convertible
5
+ corresponds_to :cabriolet
6
+ end
@@ -0,0 +1,5 @@
1
+ require_relative 'automobile'
2
+
3
+ class Sedan < Automobile
4
+ corresponds_to :sedan
5
+ end
@@ -0,0 +1,14 @@
1
+ require 'industrialist/registrar'
2
+
3
+ module Industrialist
4
+ class Builder
5
+ def self.build(type, key, *args)
6
+ klass = Registrar.value_for(type, key)
7
+ Object.const_get(klass.name)&.new(*args) unless klass.nil?
8
+ end
9
+ end
10
+
11
+ def self.build(*args)
12
+ Builder.build(*args)
13
+ end
14
+ end
@@ -0,0 +1,27 @@
1
+ module Industrialist
2
+ class Config
3
+ class << self
4
+ attr_writer :require_method
5
+
6
+ def manufacturable_paths
7
+ @manufacturable_paths ||= []
8
+ end
9
+
10
+ def load_manufacturables
11
+ manufacturable_paths.each { |path| Dir["#{path}/**/*.rb"].each { |file| Kernel.public_send(require_method, file) } }
12
+ end
13
+
14
+ private
15
+
16
+ def require_method
17
+ @require_method || :require
18
+ end
19
+ end
20
+ end
21
+
22
+ def self.config
23
+ yield(Config)
24
+
25
+ Config.load_manufacturables
26
+ end
27
+ end
@@ -1,26 +1,15 @@
1
- module Industrialist
2
- class Factory
3
- DEFAULT_KEY = :__manufacturable_default__
4
-
5
- attr_reader :registry
6
-
7
- def initialize
8
- @registry = {}
9
- end
1
+ require 'industrialist/builder'
10
2
 
11
- def register(key, klass)
12
- registry[factory_key(key)] = klass
3
+ module Industrialist
4
+ module Factory
5
+ def manufactures(klass)
6
+ @type = Type.industrialize(klass)
13
7
  end
14
8
 
15
9
  def build(key, *args)
16
- klass = registry[factory_key(key)] || registry[DEFAULT_KEY]
17
- klass&.new(*args)
18
- end
19
-
20
- private
10
+ return if @type.nil?
21
11
 
22
- def factory_key(key)
23
- (key.respond_to?(:to_sym) && key.to_sym) || key
12
+ Builder.build(@type, key, *args)
24
13
  end
25
14
  end
26
15
  end
@@ -1,36 +1,18 @@
1
- require 'industrialist/factory'
2
- require 'industrialist/warning_helper'
1
+ require 'industrialist/registrar'
2
+ require 'industrialist/type'
3
3
 
4
4
  module Industrialist
5
5
  module Manufacturable
6
- ALREADY_INCLUDED_WARNING_MESSAGE = 'warning: overriding previously defined factory on this class hierarchy'.freeze
7
- MULTIPLE_DEFAULT_WARNING_MESSAGE = 'warning: overriding a previously registered default class'.freeze
8
-
9
- def self.included(base)
10
- WarningHelper.warning(ALREADY_INCLUDED_WARNING_MESSAGE) if base.class_variable_defined?(:@@factory)
11
-
12
- base.extend ClassMethods
13
- base.class_variable_set(:@@factory, Industrialist::Factory.new)
6
+ def self.extended(base)
7
+ base.class_variable_set(:@@type, Type.industrialize(base))
14
8
  end
15
9
 
16
- module ClassMethods
17
- def create_factory(identifier)
18
- Object.const_set(identifier, factory)
19
- end
20
-
21
- def corresponds_to(key)
22
- factory.register(key, self)
23
- end
24
-
25
- def manufacturable_default
26
- WarningHelper.warning(MULTIPLE_DEFAULT_WARNING_MESSAGE) if factory.registry[Industrialist::Factory::DEFAULT_KEY]
27
-
28
- factory.register(Industrialist::Factory::DEFAULT_KEY, self)
29
- end
10
+ def corresponds_to(key)
11
+ Registrar.register(self.class_variable_get(:@@type), key, self)
12
+ end
30
13
 
31
- def factory
32
- class_variable_get(:@@factory)
33
- end
14
+ def manufacturable_default
15
+ Registrar.register_default(self.class_variable_get(:@@type), self)
34
16
  end
35
17
  end
36
18
  end
@@ -0,0 +1,9 @@
1
+ require 'industrialist/config'
2
+
3
+ module Industrialist
4
+ class Railtie < Rails::Railtie
5
+ initializer "industrialist.configure_rails_initialization" do |app|
6
+ Industrialist::Config.require_method = app.config.eager_load ? :require : :require_dependency
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,56 @@
1
+ require 'industrialist/type'
2
+ require 'industrialist/warning_helper'
3
+
4
+ module Industrialist
5
+ class Registrar
6
+ DEFAULT_KEY = :__manufacturable_default__
7
+ REDEFINED_KEY_WARNING_MESSAGE = 'warning: overriding a previously registered class'.freeze
8
+ REDEFINED_DEFAULT_WARNING_MESSAGE = 'warning: overriding a previously registered default class'.freeze
9
+
10
+ class << self
11
+ def register(type, key, klass)
12
+ WarningHelper.warning(REDEFINED_KEY_WARNING_MESSAGE) if overriding?(type, key, klass)
13
+
14
+ registry[type][key] = klass
15
+ end
16
+
17
+ def register_default(type, klass)
18
+ WarningHelper.warning(REDEFINED_DEFAULT_WARNING_MESSAGE) if overriding?(type, DEFAULT_KEY, klass)
19
+
20
+ registry[type][DEFAULT_KEY] = klass
21
+ end
22
+
23
+ def value_for(type, key)
24
+ return unless registry.key?(type)
25
+
26
+ registry[type][key] || registry[type][DEFAULT_KEY]
27
+ end
28
+
29
+ def registered_types
30
+ registry.keys
31
+ end
32
+
33
+ def registered_keys(type)
34
+ registry[type].keys
35
+ end
36
+
37
+ private
38
+
39
+ def overriding?(type, key, klass)
40
+ !registry[type][key].nil? && registry[type][key].name != klass.name
41
+ end
42
+
43
+ def registry
44
+ @registry ||= Hash.new { |hash, key| hash[key] = {} }
45
+ end
46
+ end
47
+ end
48
+
49
+ def self.registered_types
50
+ Registrar.registered_types
51
+ end
52
+
53
+ def self.registered_keys(type)
54
+ Registrar.registered_keys(type)
55
+ end
56
+ end
@@ -0,0 +1,23 @@
1
+ module Industrialist
2
+ class Type
3
+ def self.industrialize(klass)
4
+ str = klass.name
5
+ str = separate_lowercase_or_number_from_uppercase_letters(str)
6
+ str = separate_numbers_from_letters(str)
7
+ str = separate_last_consecutive_uppercase_letter_when_followed_by_lowercase_letter(str)
8
+ str.downcase.to_sym
9
+ end
10
+
11
+ def self.separate_lowercase_or_number_from_uppercase_letters(string)
12
+ string.gsub(/[a-z0-9][A-Z]+/) { |s| "#{s[0]}_#{s[1..-1]}" }
13
+ end
14
+
15
+ def self.separate_numbers_from_letters(string)
16
+ string.gsub(/[a-zA-Z][0-9]+/) { |s| "#{s[0]}_#{s[1..-1]}" }
17
+ end
18
+
19
+ def self.separate_last_consecutive_uppercase_letter_when_followed_by_lowercase_letter(string)
20
+ string.gsub(/[A-Z][A-Z]+[a-z]/) { |s| "#{s[0..-3]}_#{s[-2..-1]}" }
21
+ end
22
+ end
23
+ end
@@ -1,3 +1,3 @@
1
1
  module Industrialist
2
- VERSION = '0.4.0'.freeze
2
+ VERSION = '1.0.0'.freeze
3
3
  end
@@ -1,10 +1,7 @@
1
1
  module Industrialist
2
2
  class WarningHelper
3
3
  def self.warning(message)
4
- most_recent_caller = caller(2..2).first.split(':')
5
- file_name = most_recent_caller[0]
6
- line_number = most_recent_caller[1]
7
- warn("#{file_name}:#{line_number}: #{message}")
4
+ warn("#{caller(3..3).first}: #{message}")
8
5
  end
9
6
  end
10
7
  end
data/lib/industrialist.rb CHANGED
@@ -1,2 +1,5 @@
1
1
  require "industrialist/version"
2
+ require "industrialist/config"
2
3
  require "industrialist/manufacturable"
4
+ require "industrialist/factory"
5
+ require 'industrialist/railtie' if defined?(Rails)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: industrialist
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alan Ridlehoover
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2019-03-24 00:00:00.000000000 Z
12
+ date: 2019-04-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -102,10 +102,24 @@ files:
102
102
  - Rakefile
103
103
  - bin/console
104
104
  - bin/setup
105
+ - example/airplanes/airplane.rb
106
+ - example/airplanes/airplane_factory.rb
107
+ - example/airplanes/f16_tomcat.rb
108
+ - example/airplanes/p51_mustang.rb
109
+ - example/app.rb
110
+ - example/automobiles/automobile.rb
111
+ - example/automobiles/automobile_factory.rb
112
+ - example/automobiles/convertible.rb
113
+ - example/automobiles/sedan.rb
105
114
  - industrialist.gemspec
106
115
  - lib/industrialist.rb
116
+ - lib/industrialist/builder.rb
117
+ - lib/industrialist/config.rb
107
118
  - lib/industrialist/factory.rb
108
119
  - lib/industrialist/manufacturable.rb
120
+ - lib/industrialist/railtie.rb
121
+ - lib/industrialist/registrar.rb
122
+ - lib/industrialist/type.rb
109
123
  - lib/industrialist/version.rb
110
124
  - lib/industrialist/warning_helper.rb
111
125
  homepage: https://github.com/entelo/industrialist