strategic 1.0.0 → 1.0.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.
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