discriminable 2.1.1 → 2.2.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: b312ea73ac2afbbe72341feffdf97fce4edeee0e918d54ae33ea4b0c822b08cb
4
- data.tar.gz: 7f56a7e7fe5b6668f37d1dc8c08730f5fd5bf6a06668b8402a5194b23cb9ba88
3
+ metadata.gz: 63543cd5b47a63a6870368d2d16c9570e7cd0cebb53cfd296d717884c37fb4c3
4
+ data.tar.gz: b4417f8e33ff2d24a71a9ec436a26b66c38cab59395ed7fbb1182c818ff48439
5
5
  SHA512:
6
- metadata.gz: 53c746dbd6c1db4286132420909652551a0471043f29e8a6a1dae37b74905253ae6bdd9f78904a941474e6cdee24cf90f33d85d2e220bdaf841f162c11a54383
7
- data.tar.gz: daa33d8edf5ebc3b336388f66f22b826a7fab98f022c27c80dfa5f5068e8d3b537cccf7f9e12f59fe22d5a4ab742aece66f907e33cfd5924864d972cea1201c9
6
+ metadata.gz: e053310353bf54fcfbef35b32b5de0015f9b28903cb6dc04631bc04cfbaeec274359c0dc34d687eca7a9813eee36590f2c745e90d3c9587e381fceb9bb38886d
7
+ data.tar.gz: dbf905a1c5a7c7c10154ad5cc9eb73b67d81cd65513e5ac7a1ab33086dbfaee92a885b511942ecc37db4b8528a75283d270ec807db9c4982defb7ba7f2c814a8
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [2.2.0](https://github.com/gregorw/discriminable/compare/v2.1.1...v2.2.0) (2022-04-16)
4
+
5
+
6
+ ### Features
7
+
8
+ * Alternative syntax respecting open-closed principle ([8a8f885](https://github.com/gregorw/discriminable/commit/8a8f8857dc24753dc08f21b2bfbb7b4317b7ed5c))
9
+
3
10
  ### [2.1.1](https://github.com/gregorw/discriminable/compare/v2.1.0...v2.1.1) (2022-04-15)
4
11
 
5
12
 
data/README.md CHANGED
@@ -29,20 +29,36 @@ If bundler is not being used to manage dependencies, install the gem by executin
29
29
  ## Usage
30
30
 
31
31
  ```ruby
32
- ActiveRecord::Schema.define do
33
- create_table :orders do |t|
34
- t.integer :state, limit: 1, default: 0
35
- end
32
+ class Order < ActiveRecord::Base
33
+ include Discriminable
34
+
35
+ enum state: { open: 0, completed: 1 }
36
+ discriminable state: { open: "Cart" }
36
37
  end
37
38
 
39
+ class Cart < Order
40
+ end
41
+
42
+ Cart.create
43
+ => #<Cart id: 1, state: "open">
44
+ Order.all
45
+ => #<ActiveRecord::Relation [#<Cart id: 1, state: "open">]>
46
+ ```
47
+
48
+ ### Alternative syntax
49
+
50
+ Instead of defining subclass names within the parent you may prefer to be open for extension but closed for modification (open-closed principle) using the alternative syntax.
51
+
52
+ ```ruby
38
53
  class Order < ActiveRecord::Base
39
54
  include Discriminable
40
55
 
41
56
  enum state: { open: 0, completed: 1 }
42
- discriminable state: { open: "Cart" }
57
+ discriminable_by :state
43
58
  end
44
59
 
45
60
  class Cart < Order
61
+ discriminable_as :open
46
62
  end
47
63
 
48
64
  Cart.create
data/Rakefile CHANGED
@@ -14,3 +14,8 @@ require "rubocop/rake_task"
14
14
  RuboCop::RakeTask.new
15
15
 
16
16
  task default: %i[test rubocop]
17
+
18
+ # Release task
19
+ # gem build *.gemspec
20
+ # gem push *.gem
21
+ # rm *.gem
data/TODO.md CHANGED
@@ -1,5 +1,6 @@
1
- - [ ] multiple values per subclass
2
- - [ ] default to first value when using hash syntax
3
- - [ ] open-closed principle
1
+ - [x] multiple values per subclass
2
+ - [x] default to first value when using hash syntax
3
+ - [x] open-closed principle
4
+ - [ ] use `type` column with enum, int, string, etc.
4
5
  - [ ] test permitted attributes
5
- - [ ] `self.abstract_class = true`
6
+ - [ ] `self.abstract_class = true`
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Discriminable
4
- VERSION = "2.1.1"
4
+ VERSION = "2.2.0"
5
5
  end
data/lib/discriminable.rb CHANGED
@@ -26,6 +26,8 @@ module Discriminable
26
26
  included do
27
27
  class_attribute :discriminable_map, instance_writer: false
28
28
  class_attribute :discriminable_inverse_map, instance_writer: false
29
+ class_attribute :discriminable_values, instance_writer: false
30
+ class_attribute :discriminable_as_descendant_value, instance_writer: false
29
31
  end
30
32
 
31
33
  # Specify the column to use for discrimination.
@@ -33,7 +35,7 @@ module Discriminable
33
35
  def discriminable(**options)
34
36
  raise "Subclasses should not override .discriminable" unless base_class?
35
37
 
36
- discriminator, map = options.first
38
+ attribute, map = options.first
37
39
 
38
40
  self.discriminable_map = map.with_indifferent_access
39
41
 
@@ -41,14 +43,41 @@ module Discriminable
41
43
  # { a: "C", b: "C" }.invert => { "C" => :b }
42
44
  # { a: "C", b: "C" }.to_a.reverse.to_h.invert => { "C" => :a }
43
45
  self.discriminable_inverse_map = map.to_a.reverse.to_h.invert
44
- self.inheritance_column = discriminator.to_s
46
+ self.inheritance_column = attribute.to_s
47
+ end
48
+
49
+ def discriminable_by(attribute)
50
+ raise "Subclasses should not override .discriminable_by" unless base_class?
51
+
52
+ self.discriminable_as_descendant_value = true
53
+ self.inheritance_column = attribute.to_s
54
+ end
55
+
56
+ def discriminable_as(*values)
57
+ raise "Only subclasses should specify .discriminable_as" if base_class?
58
+
59
+ self.discriminable_values = values.map do |value|
60
+ value.instance_of?(Symbol) ? value.to_s : value
61
+ end
45
62
  end
46
63
 
47
64
  def sti_name
65
+ if discriminable_as_descendant_value
66
+ self.discriminable_inverse_map ||= Hash.new do |map, value|
67
+ map[value] = name.constantize.discriminable_values&.first
68
+ end
69
+ end
70
+
48
71
  discriminable_inverse_map[name]
49
72
  end
50
73
 
51
74
  def sti_class_for(value)
75
+ if discriminable_as_descendant_value
76
+ self.discriminable_map ||= Hash.new do |map, v|
77
+ map[v] = descendants.detect { |d| d.discriminable_values.include? v }&.name
78
+ end
79
+ end
80
+
52
81
  return self unless (type_name = discriminable_map[value])
53
82
 
54
83
  super type_name
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: discriminable
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregor Wassmann
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-04-15 00:00:00.000000000 Z
11
+ date: 2022-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord