strategic 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/README.md +42 -19
  4. data/lib/strategic.rb +3 -0
  5. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f8ddc7e63dc608ac0a7e97ebb9110431c9a490e7ec07abed6936bb347b6105e8
4
- data.tar.gz: 4ca98f38d3933fc5f33ac460dc2767a2769cfbe0a870c9f48bfb427ca2a4c1c4
3
+ metadata.gz: 5d1b5e48f559fa9befbe74660a5894d73aa99e9acb9ab31daf6d592e50d5200e
4
+ data.tar.gz: b0064808d6119cd5e860762c82483d457c30c4a5d22b703060fbef323a781086
5
5
  SHA512:
6
- metadata.gz: '067224647109cf8198006ddce287755a1ec9997ff67fc8a3099d4f172ba6549a8e9ef4f8bf285d44996aa3a5d6ef4949892dffab5a1d26918d17cdc27cbd6e0b'
7
- data.tar.gz: 1046857c6fd46e0615ab559bbb4e84bc8ba70f7d7995bd621e7d182316d603d22e4d99e2fefc1adce3d2682769519e0cc9189bef7ce614d0aca8354271994e05
6
+ metadata.gz: 351e5f342baf23c732723b97e0040f85d65378bf4e5fdfcde2385a9b16870a303f638da34765569d0392180295997088e1f7730b3a970210ebdd22bb388b712a
7
+ data.tar.gz: b5b269f698ae134d412dc9d8ff5e16d397da76480c88f9b92e984079f5edbaed3002f409e71ac4686e010fbd0a0bdcc460b70a42a7c503ea95e2001b665dd7a5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Change Log
2
2
 
3
+ ## 1.0.1
4
+
5
+ - Fix error "undefined method `new' for Strategic::Strategy:Module" that occurs when setting an empty string strategy (must return nil or default strategy)
6
+ - Fix issue with `ancestors` method not available on all constants (only ones that are classes/modules)
7
+
3
8
  ## 1.0.0
4
9
 
5
10
  - Improve design to better match the authentic Gang of Four Strategy Pattern with `Strategic::Strategy` module, removing the need for inheritance.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Strategic 1.0.0
1
+ # Strategic 1.0.1
2
2
  ## Painless Strategy Pattern in Ruby and Rails
3
3
  [![Gem Version](https://badge.fury.io/rb/strategic.svg)](http://badge.fury.io/rb/strategic)
4
4
  [![rspec](https://github.com/AndyObtiva/strategic/actions/workflows/ruby.yml/badge.svg)](https://github.com/AndyObtiva/strategic/actions/workflows/ruby.yml)
@@ -92,7 +92,7 @@ tax_calculator = TaxCalculator.new_with_strategy('us', args)
92
92
  tax = tax_calculator.tax_for(39.78)
93
93
  ```
94
94
 
95
- **Default strategy for a strategy name that has no strategy class is the superclass: `TaxCalculator`**
95
+ Default strategy for a strategy name that has no strategy class is `nil`
96
96
 
97
97
  You may set a default strategy on a strategic model via class method `default_strategy`
98
98
 
@@ -116,7 +116,7 @@ If no strategy is selected and you try to invoke a method that belongs to strate
116
116
  Add the following to bundler's `Gemfile`.
117
117
 
118
118
  ```ruby
119
- gem 'strategic', '~> 1.0.0'
119
+ gem 'strategic', '~> 1.0.1'
120
120
  ```
121
121
 
122
122
  ### Option 2: Manual
@@ -124,7 +124,7 @@ gem 'strategic', '~> 1.0.0'
124
124
  Or manually install and require library.
125
125
 
126
126
  ```bash
127
- gem install strategic -v1.0.0
127
+ gem install strategic -v1.0.1
128
128
  ```
129
129
 
130
130
  ```ruby
@@ -145,21 +145,44 @@ Steps:
145
145
 
146
146
  ## API
147
147
 
148
- - `StrategicClass::strategy_names`: returns list of strategy names (strings) discovered by convention (nested under a namespace matching the superclass name)
149
- - `StrategicClass::strategies`: returns list of strategies discovered by convention (nested under a namespace matching the superclass name)
150
- - `StrategicClass::new_with_strategy(string_or_class_or_object, *args, &block)`: instantiates a strategy based on a string/class/object and strategy constructor args
151
- - `StrategicClass::strategy_class_for(string_or_class_or_object)`: selects a strategy class based on a string (e.g. 'us' selects UsStrategy) or alternatively a class/object if you have a mirror hierarchy for the strategy hierarchy
152
- - `StrategicClass::default_strategy`: (used in model class body) sets default strategy as a strategy name string (e.g. 'us' selects UsStrategy) or alternatively a class/object if you have a mirror hierarchy for the strategy hierarchy
153
- - `StrategicClass::strategy_matcher`: (used in model class body) custom matcher for all strategies (e.g. `strategy_matcher {|string| string.start_with?('C') && string.end_with?('o')}`)
154
- - `StrategicClass#strategy=`: sets strategy
155
- - `StrategicClass#strategy`: returns current strategy
156
- - `StrategyClass::strategy_name`: returns parsed strategy name of current strategy class
157
- - `StrategyClass::strategy_matcher`: (used in model class body) custom matcher for a specific strategy (e.g. `strategy_matcher {|string| string.start_with?('C') && string.end_with?('o')}`)
158
- - `StrategyClass::strategy_exclusion`: (used in model class body) exclusion from custom matcher (e.g. `strategy_exclusion 'Cio'`)
159
- - `StrategyClass::strategy_alias`: (used in model class body) alias for strategy in addition to strategy's name derived from class name by convention (e.g. `strategy_alias 'USA'` for `UsStrategy`)
160
- - `StrategyClass#context`: returns strategy context (the strategic model instance)
161
-
162
- Example with customizations via class body methods:
148
+ ### Strategic model
149
+
150
+ #### Class Body Methods
151
+
152
+ These methods can be delcared in a strategic model class body.
153
+
154
+ - `::default_strategy`: sets default strategy as a strategy name string (e.g. 'us' selects UsStrategy) or alternatively a class/object if you have a mirror hierarchy for the strategy hierarchy
155
+ - `::strategy_matcher`: custom matcher for all strategies (e.g. `strategy_matcher {|string| string.start_with?('C') && string.end_with?('o')}`)
156
+
157
+ #### Class Methods
158
+
159
+ - `::strategy_names`: returns list of strategy names (strings) discovered by convention (nested under a namespace matching the superclass name)
160
+ - `::strategies`: returns list of strategies discovered by convention (nested under a namespace matching the superclass name)
161
+ - `::new_with_strategy(string_or_class_or_object, *args, &block)`: instantiates a strategy based on a string/class/object and strategy constructor args
162
+ - `::strategy_class_for(string_or_class_or_object)`: selects a strategy class based on a string (e.g. 'us' selects UsStrategy) or alternatively a class/object if you have a mirror hierarchy for the strategy hierarchy
163
+
164
+ #### Instance Methods
165
+
166
+ - `#strategy=`: sets strategy
167
+ - `#strategy`: returns current strategy
168
+
169
+ ### Strategy
170
+
171
+ #### Class Body Methods
172
+
173
+ - `::strategy_matcher`: custom matcher for a specific strategy (e.g. `strategy_matcher {|string| string.start_with?('C') && string.end_with?('o')}`)
174
+ - `::strategy_exclusion`: exclusion from custom matcher (e.g. `strategy_exclusion 'Cio'`)
175
+ - `::strategy_alias`: alias for strategy in addition to strategy's name derived from class name by convention (e.g. `strategy_alias 'USA'` for `UsStrategy`)
176
+
177
+ #### Class Methods
178
+
179
+ - `::strategy_name`: returns parsed strategy name of current strategy class
180
+
181
+ #### Instance Methods
182
+
183
+ - `#context`: returns strategy context (the strategic model instance)
184
+
185
+ ### Example with Customizations via Class Body Methods
163
186
 
164
187
  ```ruby
165
188
  class TaxCalculator
data/lib/strategic.rb CHANGED
@@ -77,6 +77,7 @@ module Strategic
77
77
  else
78
78
  strategy_class_name = string_or_class_or_object.class.name
79
79
  end
80
+ return nil if strategy_class_name.to_s.strip.empty?
80
81
  begin
81
82
  class_name = "::#{self.name}::#{Strategic.classify(strategy_class_name)}Strategy"
82
83
  class_eval(class_name)
@@ -94,6 +95,8 @@ module Strategic
94
95
  def strategies
95
96
  constants.map do |constant_symbol|
96
97
  const_get(constant_symbol)
98
+ end.select do |constant|
99
+ constant.respond_to?(:ancestors)
97
100
  end.select do |constant|
98
101
  constant.ancestors.include?(Strategic::Strategy) && constant.name.split('::').last.end_with?('Strategy') && constant.name.split('::').last != 'Strategy' # has to be something like PrefixStrategy
99
102
  end.sort_by(&:strategy_name)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strategic
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-29 00:00:00.000000000 Z
11
+ date: 2021-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -167,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
167
  - !ruby/object:Gem::Version
168
168
  version: '0'
169
169
  requirements: []
170
- rubygems_version: 3.2.3
170
+ rubygems_version: 3.2.22
171
171
  signing_key:
172
172
  specification_version: 4
173
173
  summary: Painless Strategy Pattern for Ruby and Rails