active_module 0.1.6 → 0.1.8

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: 1473d88ff3d53e8948747dc7827ad2836478a0c6db139c54e11f2a96df58e758
4
- data.tar.gz: 045e7b7689734cf7c98654ec1283a747063d1defba78c47e3efbd115c5046675
3
+ metadata.gz: b80aaae788c312746df8dcaba68bfda8f881fc2c22d7642b509546bdab198bc0
4
+ data.tar.gz: 84674ab108e9b639327f7531f678a12b8dbf31ab25c01088f8839458b71d1cac
5
5
  SHA512:
6
- metadata.gz: 67321659d14a0aff48e5917e2242d42773dbc6f86a8fa8cef935956bbda4717858128a405264ff39cde9bd06e223ee266b08a4f4b07a62f600ee3b6de8c54714
7
- data.tar.gz: bf7305eabb2c4d81e0514542c7172e440aaf5b17ea5d4bf732705100f8a92cc01f772aae9b3ba0f864c575f1040626d7730f5831d7d7889aec0ed88980f5271a
6
+ metadata.gz: a89843336735a230e13691069fd3a2e919403a140712476bb5176862fd0bb72df6ff069fa9d3ca9635c2dadc1a602863122a2ec384f8414754a560da02561698
7
+ data.tar.gz: f7b03c281aafba2a1bf187f7ed9b049c9dd3798bafdf411c3710964e2cbc087dedd72937c897925bdcbb9f4887e625f5d893b69640df853f738324b12b955e7d
data/README.md CHANGED
@@ -1,19 +1,21 @@
1
- # ActiveModule
2
1
 
3
- *"Let's turn modules and classes into first-class active record values!"*
2
+ # active_module
3
+ ![alt text](https://img.shields.io/badge/coverage-100%25-brightgreen)
4
+
5
+ #### *Modules and Classes as first-class active record values!*
4
6
 
5
7
  ActiveModel/ActiveRecord implementation of the Module attribute type.
6
8
 
7
- - Allows storing a reference to a `Module` or `Class` (because they are modules) in a `:string`
8
- database field in a safe and efficient way.
9
- - It automatically casts strings and symbols into modules when creating and querying objects.
10
- - Symbols or strings refer to the modules using unqualified names.
9
+ - Allows storing a reference to a `Module` or `Class` in a `:string` database field
10
+ - Automatically casts strings and symbols into modules when creating and querying objects
11
+ - Symbols or strings refer to the modules using unqualified names
12
+ - It is safe and efficient
11
13
 
12
14
  This is a very generic mechanism that enables many possible utilizations, for instance:
13
- - Strategy Pattern (composition-based polymorphism)
14
- - Rapid prototyping static domain objects
15
- - Static configuration management
16
- - Rich Java/C#-like enums
15
+ - **Composition-based polymorphism (Strategy design pattern)**
16
+ - **Rapid prototyping static domain objects**
17
+ - **Static configuration management**
18
+ - **Rich Java/C#-like enums**
17
19
 
18
20
  You can find examples of these in [Usage -> Examples :](#Examples)
19
21
 
@@ -36,8 +38,19 @@ object.module_field = "Module"
36
38
  object.module_field #=> Nested::Module:Module
37
39
  ```
38
40
 
39
- And compare them like this (optional):
41
+ Query them like this:
42
+ ```ruby
43
+ MyARObject.where(module_field: Nested::Module)
44
+ MyARObject.where(module_field: :Module)
45
+ MyARObject.where(module_field: "Module")
46
+ object.module_field #=> Nested::Module:Module
47
+ ```
48
+
49
+ And compare them like this:
50
+
40
51
  ```ruby
52
+ object.module_field == Nested::Module
53
+
41
54
  module MyNameSpace
42
55
  using ActiveModule::Comparison
43
56
 
@@ -51,7 +64,7 @@ end
51
64
  Add to your gemfile - and if you are using rails - that's all you need:
52
65
 
53
66
  ```ruby
54
- gem 'active_module', "~>0.1"
67
+ gem 'active_module', "~> 0.1"
55
68
  ```
56
69
 
57
70
  If you are not using rails, just issue this command after loading active record
@@ -77,7 +90,7 @@ create_table :my_ar_objects do |t|
77
90
  end
78
91
  ```
79
92
 
80
- Now given this module structure:
93
+ Now given this random module hierarchy:
81
94
  ```ruby
82
95
  class MyARObject < ActiveRecord::Base
83
96
  module MyModule1; end
@@ -154,13 +167,44 @@ module YourClassOrModuleThatWantsToCompare
154
167
  end
155
168
  ```
156
169
 
170
+ or like this, if you don't want to use the refinement:
171
+
172
+ ```ruby
173
+ ActiveModule::Comparison.compare(my_ar_object.module_field, :MyModule1)
174
+ ```
175
+
176
+ but in this last case it would probably make more sense to simply use a module literal:
177
+
178
+ ```ruby
179
+ my_ar_object.module_field == MyClass::MyModule1
180
+ ```
181
+
182
+
157
183
  ## Examples
158
184
 
159
- ### Strategy Pattern (composition-based polymorphism)
185
+ ### Composition-based polymorphism (Strategy design pattern)
160
186
 
161
187
  [The Strategy design pattern](https://en.wikipedia.org/wiki/Strategy_pattern) allows composition based polymorphism. This enables runtime polymorphism (by changing the strategy in runtime),
162
188
  and multiple-polymorphism (by composing an object of multiple strategies).
163
189
 
190
+ If you want to use classes this will do:
191
+ ```ruby
192
+ class MyARObject < ActiveRecord::Base
193
+ attribute :strategy_class, :active_module, possible_modules: StrategySuperclass.subclasses
194
+
195
+ def strategy
196
+ @strategy ||= strategy_class.new(some_args_from_the_instance)
197
+ end
198
+
199
+ def run_strategy!(args)
200
+ strategy.call(args)
201
+ end
202
+ end
203
+ ```
204
+
205
+ But if you are not in the mood to define a class hierarchy for it (or if you are performance-savy),
206
+ you may use modules instead:
207
+
164
208
  ```ruby
165
209
  class MyARObject < ActiveRecord::Base
166
210
  module Strategy1
@@ -179,16 +223,13 @@ class MyARObject < ActiveRecord::Base
179
223
  :active_module,
180
224
  possible_modules: [Strategy1, Strategy2]
181
225
 
182
- def run_strategy!
183
- # here we could pass arguments to the strategy, and if
184
- # in this case strategies were classes we could also
185
- # instantiate them
186
- strategy.call
226
+ def run_strategy!(some_args)
227
+ strategy.call(some_args, other_args)
187
228
  end
188
229
  end
189
230
 
190
231
  MyARObject.create!(module_field: :Strategy1).run_strategy! #=> "strategy1 called"
191
- MyARObject.create!(module_field: :Strategy1).run_strategy! #=> "strategy2 called"
232
+ MyARObject.create!(module_field: :Strategy2).run_strategy! #=> "strategy2 called"
192
233
  ```
193
234
 
194
235
 
@@ -250,6 +291,10 @@ this is how you could do so:
250
291
  # Provider domain Object
251
292
  module Provider
252
293
  # As if the domain model class
294
+ def self.all
295
+ [Ebay, Amazon]
296
+ end
297
+
253
298
  module Base
254
299
  def do_something!
255
300
  "do something with #{something_from_an_instance}"
@@ -274,11 +319,6 @@ module Provider
274
319
  "the amazon provider config"
275
320
  end
276
321
  end
277
-
278
- # As if the domain model class
279
- def self.all
280
- [Ebay, Amazon]
281
- end
282
322
  end
283
323
  ```
284
324
 
@@ -345,6 +385,18 @@ Java/C# enums allow defining methods on the enum, which are shared across all en
345
385
 
346
386
  ```ruby
347
387
  module PipelineStage
388
+ module_function
389
+
390
+ def all
391
+ [InitialContact, InNegotiations, LostDeal, PaidOut]
392
+ end
393
+
394
+ def cast(stage)
395
+ self.all.map(&:external_provider_code).find{|code| code == stage} ||
396
+ self.all.map(&:database_representation).find{|code| code == stage} ||
397
+ self.all.map(&:frontend_representation).find{|code| code == stage}
398
+ end
399
+
348
400
  module Base
349
401
  def external_provider_code
350
402
  @external_provider_code ||= self.name.underscore
@@ -374,18 +426,6 @@ module PipelineStage
374
426
  module PaidOut
375
427
  extend Base
376
428
  end
377
-
378
- module_function
379
-
380
- def all
381
- [InitialContact, InNegotiations, LostDeal, PaidOut]
382
- end
383
-
384
- def cast(stage)
385
- self.all.map(&:external_provider_code).find{|code| code == stage} ||
386
- self.all.map(&:database_representation).find{|code| code == stage} ||
387
- self.all.map(&:frontend_representation).find{|code| code == stage}
388
- end
389
429
  end
390
430
 
391
431
  class MyARObject < ActiveRecord::Base
@@ -7,10 +7,10 @@ module ActiveModule
7
7
 
8
8
  def =~(other)
9
9
  case other
10
- when ::String
11
- (@possible_names ||= possible_names).include?(other)
12
10
  when ::Symbol
13
- (@possible_names ||= possible_names).include?(other.to_s)
11
+ possible_symbol_names_set.include?(other)
12
+ when ::String
13
+ possible_symbol_names_set.include?(other.to_sym)
14
14
  else
15
15
  self == other
16
16
  end
@@ -14,6 +14,10 @@ module ActiveModule
14
14
  end
15
15
  end
16
16
 
17
+ def possible_symbol_names_set
18
+ @possible_symbol_names_set ||= Set.new(possible_names.map(&:to_sym))
19
+ end
20
+
17
21
  def qualified_name
18
22
  "::#{name}"
19
23
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveModule
4
- VERSION = "0.1.6"
4
+ VERSION = "0.1.8"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_module
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pedro Rolo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-12-17 00:00:00.000000000 Z
11
+ date: 2024-12-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: '9'
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: '7'
22
+ version: '7.1'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: '9'
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: '7'
32
+ version: '7.1'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: bundler
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -44,7 +44,7 @@ dependencies:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
46
  version: 1.15.0
47
- description: Let's turn modules and classes into first-class active record values!
47
+ description: ActiveModel/ActiveRecord module attribute type implementation
48
48
  email:
49
49
  - pedrorolo@gmail.com
50
50
  executables: []
@@ -89,5 +89,5 @@ requirements: []
89
89
  rubygems_version: 3.5.7
90
90
  signing_key:
91
91
  specification_version: 4
92
- summary: ActiveModel/ActiveRecord module attribute type implementation
92
+ summary: Modules and Classes as first-class active record values
93
93
  test_files: []