active_module 0.1.6 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
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: []