enum_ext 0.4.5 → 0.5.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: 80643636a5677570fda77c8f10be37f8debfe0f168d237905d948b462db5b010
4
- data.tar.gz: 7b83c471065ca2742ff94828cde7aff2da1e77c51a967d55b16ea75a8469be4a
3
+ metadata.gz: e43e1644acff1729643340c16a085e015c66a76949a313fe3d95c229261fe165
4
+ data.tar.gz: a5ccf00bf5bdc65d3e26d0d115e52dad86afe41cab4e71c5758ee43cbf9ff31f
5
5
  SHA512:
6
- metadata.gz: 726f5f1be15a7c7ca0bcc30a6c363d0eb9d2eb836b326ca87c49e632b3947bc06ad07dad2c9e481a49e1ca1a93b8f87b101d5b4214474041881ae37b0d37c0af
7
- data.tar.gz: ff01e3501cbe245923cc625e926a06329fcc6090b30a41ce0002e52dd14ac16afe1cf3bcf0ad5e717de84c5673bc9e2be9893394dfcecbcfcc0694ce70fc7a0d
6
+ metadata.gz: d521069cf6f12ee8ed5117a3a521fdc6f4c7e5e7e798a8fea32efaa28ebe549bf23c6e939f15ff0857b193a3162bfa386e8b5784e3f9b69fdabf861a22701a99
7
+ data.tar.gz: 263fe623bce43c3f1da806ef0904d36494918f1d168c77a1197e181337bd0d88cf51e30a0850b501d42156402a0131aa10ba5688026b5e1d09e7633bb2b1610c
data/CHANGELOG.md CHANGED
@@ -1,4 +1,34 @@
1
- # 0.4.
1
+ # 0.5.0
2
+ * with/without definitions will go standalone now, you need explicitly address them. Ex:
3
+ ```
4
+ multi_enum_scopes :test_type
5
+ # OR
6
+ enum test_type: [..], ext: [:multi_enum_scopes]
7
+ ```
8
+ * easier supersets definitions, no raw level class methods and multiple method call needed anymore for additive supersets:
9
+
10
+ ```ruby
11
+ ext_enum_sets :test_type, raw_level: [:unit_test, :spec]
12
+ ext_enum_sets :test_type,
13
+ fast: raw_level_test_types | [:controller]
14
+ # Now it could be defined like this:
15
+ ext_enum_sets :test_type,
16
+ raw_level: [:unit_test, :spec],
17
+ fast: [:raw_level, :controller]
18
+ ```
19
+ Rem you still need couple `ext_enum_sets` calls if you want to use (`-` / `&` / `^`) array operators except for (`+` / `|`)
20
+
21
+ * Definitions now stored as IndifferentHash just as enum originally does
22
+ and as an Array of strings not a symbols even if defined as ones
23
+ * Some deprecations warning added
24
+
25
+ # 0.4.6
26
+ * allows enum to enable simple helpers directly at enum definition. Ex:
27
+ ```
28
+ enum test_type: [:value], ext: [:enum_i, :mass_assign_enum]
29
+ ```
30
+
31
+ # 0.4.5
2
32
  * ext_enum_sets will add class method: ext_enum_pluralised, containing all extended enum sets as a single Hash
3
33
 
4
34
  # 0.4.4
data/Gemfile.lock CHANGED
@@ -1,75 +1,77 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- enum_ext (0.4.4)
4
+ enum_ext (0.4.5)
5
5
  activerecord (>= 5.2.4.3)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- actionpack (6.0.3.4)
11
- actionview (= 6.0.3.4)
12
- activesupport (= 6.0.3.4)
13
- rack (~> 2.0, >= 2.0.8)
10
+ actionpack (6.1.7)
11
+ actionview (= 6.1.7)
12
+ activesupport (= 6.1.7)
13
+ rack (~> 2.0, >= 2.0.9)
14
14
  rack-test (>= 0.6.3)
15
15
  rails-dom-testing (~> 2.0)
16
16
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
17
- actionview (6.0.3.4)
18
- activesupport (= 6.0.3.4)
17
+ actionview (6.1.7)
18
+ activesupport (= 6.1.7)
19
19
  builder (~> 3.1)
20
20
  erubi (~> 1.4)
21
21
  rails-dom-testing (~> 2.0)
22
22
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
23
- activemodel (6.0.3.4)
24
- activesupport (= 6.0.3.4)
25
- activerecord (6.0.3.4)
26
- activemodel (= 6.0.3.4)
27
- activesupport (= 6.0.3.4)
28
- activesupport (6.0.3.4)
23
+ activemodel (6.1.7)
24
+ activesupport (= 6.1.7)
25
+ activerecord (6.1.7)
26
+ activemodel (= 6.1.7)
27
+ activesupport (= 6.1.7)
28
+ activesupport (6.1.7)
29
29
  concurrent-ruby (~> 1.0, >= 1.0.2)
30
- i18n (>= 0.7, < 2)
31
- minitest (~> 5.1)
32
- tzinfo (~> 1.1)
33
- zeitwerk (~> 2.2, >= 2.2.2)
30
+ i18n (>= 1.6, < 2)
31
+ minitest (>= 5.1)
32
+ tzinfo (~> 2.0)
33
+ zeitwerk (~> 2.3)
34
34
  builder (3.2.4)
35
35
  byebug (11.1.3)
36
- concurrent-ruby (1.1.7)
36
+ concurrent-ruby (1.1.10)
37
37
  crass (1.0.6)
38
38
  erubi (1.10.0)
39
- i18n (1.8.5)
39
+ i18n (1.12.0)
40
40
  concurrent-ruby (~> 1.0)
41
- loofah (2.8.0)
41
+ loofah (2.19.1)
42
42
  crass (~> 1.0.2)
43
43
  nokogiri (>= 1.5.9)
44
44
  method_source (1.0.0)
45
- mini_portile2 (2.4.0)
45
+ mini_portile2 (2.8.0)
46
46
  minitest (5.14.2)
47
- nokogiri (1.10.10)
48
- mini_portile2 (~> 2.4.0)
49
- rack (2.2.3)
47
+ nokogiri (1.13.10)
48
+ mini_portile2 (~> 2.8.0)
49
+ racc (~> 1.4)
50
+ racc (1.6.1)
51
+ rack (2.2.4)
50
52
  rack-test (1.1.0)
51
53
  rack (>= 1.0, < 3)
52
54
  rails-dom-testing (2.0.3)
53
55
  activesupport (>= 4.2.0)
54
56
  nokogiri (>= 1.6)
55
- rails-html-sanitizer (1.3.0)
56
- loofah (~> 2.3)
57
- rails-i18n (6.0.0)
57
+ rails-html-sanitizer (1.4.4)
58
+ loofah (~> 2.19, >= 2.19.1)
59
+ rails-i18n (7.0.6)
58
60
  i18n (>= 0.7, < 2)
59
- railties (>= 6.0.0, < 7)
60
- railties (6.0.3.4)
61
- actionpack (= 6.0.3.4)
62
- activesupport (= 6.0.3.4)
61
+ railties (>= 6.0.0, < 8)
62
+ railties (6.1.7)
63
+ actionpack (= 6.1.7)
64
+ activesupport (= 6.1.7)
63
65
  method_source
64
- rake (>= 0.8.7)
65
- thor (>= 0.20.3, < 2.0)
66
+ rake (>= 12.2)
67
+ thor (~> 1.0)
66
68
  rake (13.0.1)
67
69
  sqlite3 (1.4.2)
70
+ stubberry (0.3.0)
68
71
  thor (1.0.1)
69
- thread_safe (0.3.6)
70
- tzinfo (1.2.8)
71
- thread_safe (~> 0.1)
72
- zeitwerk (2.4.2)
72
+ tzinfo (2.0.5)
73
+ concurrent-ruby (~> 1.0)
74
+ zeitwerk (2.6.6)
73
75
 
74
76
  PLATFORMS
75
77
  ruby
@@ -82,6 +84,7 @@ DEPENDENCIES
82
84
  rails-i18n (>= 4)
83
85
  rake (>= 10.0)
84
86
  sqlite3
87
+ stubberry
85
88
 
86
89
  BUNDLED WITH
87
90
  2.1.4
data/README.md CHANGED
@@ -22,19 +22,22 @@ Or install it yourself as:
22
22
  To use enum extension extend main model class with EnumExt module,
23
23
  and customize your enums the way you need:
24
24
 
25
- class SomeModel
26
- extend EnumExt
25
+ ```ruby
27
26
 
28
- enum_i ...
29
- humanize_enum ...
30
- translate_enum ...
31
- ext_enum_sets ...
32
- mass_assign_enum ...
27
+ class SomeModel
28
+ extend EnumExt
29
+
30
+ enum kinds: {}, ext: [:enum_i, :enum_mass_assign, ]
31
+ humanize_enum #...
32
+ translate_enum #...
33
+ ext_enum_sets #...
33
34
  end
35
+ ```
34
36
 
35
37
  Let's assume that we have model Request representing some buying requests with enum **status**, and we have model Order with requests,
36
38
  representing single purchase, like this:
37
39
 
40
+ ```ruby
38
41
  class Request
39
42
  extend EnumExt
40
43
  belongs_to :order
@@ -44,6 +47,7 @@ Or install it yourself as:
44
47
  class Order
45
48
  has_many :requests
46
49
  end
50
+ ```
47
51
 
48
52
  Now let's review some examples of possible enum extensions
49
53
 
@@ -51,19 +55,18 @@ Or install it yourself as:
51
55
 
52
56
  if app doesn't need internationalization, it may use humanize_enum to make enum user friendly
53
57
 
54
- ```
58
+ ```ruby
55
59
  humanize_enum :status, {
56
60
  #locale dependent example with pluralization and lambda:
57
- in_cart: -> (t_self) { I18n.t("request.status.in_cart", count: t_self.sum ) }
61
+ in_cart: -> (t_self) { I18n.t("request.status.in_cart", count: t_self.sum ) },
58
62
 
59
63
  #locale dependent example with pluralization and proc:
60
- paid: Proc.new{ I18n.t("request.status.paid", count: self.sum ) }
64
+ paid: Proc.new{ I18n.t("request.status.paid", count: self.sum ) },
61
65
 
62
66
  #locale independent:
63
67
  ready_for_shipment: "Ready to go!"
64
68
  }
65
- end
66
- ```
69
+ ```
67
70
 
68
71
  This humanize_enum adds to instance:
69
72
  - t_in_cart, t_paid, t_ready_for_shipment
@@ -76,28 +79,28 @@ Or install it yourself as:
76
79
 
77
80
  Example with block:
78
81
 
79
- ```
80
- humanize_enum :status do
81
- I18n.t("scope.#{status}")
82
- end
82
+ ```ruby
83
+ humanize_enum :status do
84
+ I18n.t("scope.#{status}")
85
+ end
83
86
  ```
84
87
 
85
88
  Example for select:
86
89
 
87
- ```
90
+ ```ruby
88
91
  f.select :status, Request.t_statuses_options
89
92
  ```
90
93
 
91
94
  in Active Admin filters
92
- ```
95
+ ```ruby
93
96
  filter :status, as: :select, label: 'Status', collection: Request.t_statuses_options_i
94
97
  ```
95
98
 
96
99
 
97
- Rem: select options may break when using lambda() or proc with instance method, but will survive with block
100
+ **Rem:** select options may break when using lambda() or proc with instance method, but will survive with block
98
101
 
99
102
  Console:
100
- ```
103
+ ```ruby
101
104
  request.sum = 3
102
105
  request.paid!
103
106
  request.status # >> paid
@@ -110,47 +113,55 @@ Or install it yourself as:
110
113
  ### Translate (translate_enum)
111
114
 
112
115
  Enum is translated using scope 'active_record.attributes.class_name_underscore.enum_plural', or the given one:
113
-
114
- translate_enum :status, 'active_record.request.enum'
115
-
116
+ ```ruby
117
+ translate_enum :status, 'active_record.request.enum'
118
+ ```
116
119
  Or it can be done with block either with translate or humanize:
117
-
118
- translate_enum :status do
119
- I18n.t( "active_record.request.enum.#{status}" )
120
- end
121
120
 
122
- ### Enum to_i shortcut ( enum_i )
121
+ ```ruby
122
+ translate_enum :status do
123
+ I18n.t( "active_record.request.enum.#{status}" )
124
+ end
125
+ ```
123
126
 
124
- Defines method enum_name_i shortcut for Model.enum_names[elem.enum_name]
127
+ ### Enum to_i shortcut ( enum_i )
128
+ Defines method enum_name_i shortcut for Model.enum_names[elem.enum_name] or enum_name_before_type_cast
125
129
 
126
130
  **Ex**
127
- enum_i :status
128
- ...
131
+ ```ruby
132
+ enum status: [:in_cart, :waiting_for_payment, :paid, :ready_for_shipment, :on_delivery, :delivered],
133
+ ext: [:enum_i]
134
+ # some place else:
129
135
  request.paid_i # 10
130
-
136
+ ```
131
137
 
132
138
  ### Enum Sets (ext_enum_sets)
133
139
 
134
- **Use-case** For example you have pay bills of different types, and you want to group some types in debit and credit "super-types",
135
- and have scope PayBill.debit, instance method with question mark as usual enum does pay_bill.debit?.
140
+ **Use-case** whenever you need superset of enums to behave like a enum.
136
141
 
137
- You can do this with method **ext_enum_sets** it creates: scopes for subsets, instance method with ? and some class methods helpers
142
+ You can do this with method **ext_enum_sets** it creates:
143
+ - scopes for subsets,
144
+ - instance methods with `?`
145
+ - and some class methods helpers
138
146
 
139
- For this call:
140
- ```
141
- ext_enum_sets :status, {
142
- delivery_set: [:ready_for_shipment, :on_delivery, :delivered] # for shipping department for example
143
- in_warehouse: [:ready_for_shipment] # this just for superposition example below
144
- }
145
- ```
147
+ For instance:
148
+
149
+ ```ruby
150
+ ext_enum_sets :status, {
151
+ delivery_set: [:ready_for_shipment, :on_delivery, :delivered], # for shipping department for example
152
+ in_warehouse: [:ready_for_shipment]
153
+ }
154
+ ```
155
+
146
156
  it will generate:
157
+
147
158
  ```
148
159
  instance:
149
160
  - methods: delivery_set?, in_warehouse?
150
161
 
151
162
  class:
152
163
  - named scopes: delivery_set, in_warehouse
153
- - parametrized scopes: with_statuses, without_statuses
164
+ - parametrized scopes: with_statuses, without_statuses ( available as a standalone extension now, and will not be included by default in a versionafter 0.5.0)
154
165
  class helpers:
155
166
  - delivery_set_statuses (=[:ready_for_shipment, :on_delivery, :delivered] ), in_warehouse_statuses
156
167
  - delivery_set_statuses_i (= [3,4,5]), in_warehouse_statuses_i (=[3])
@@ -160,32 +171,45 @@ class:
160
171
  - t_delivery_set_statuses_options_i (= [['translation or humanization', 3] ...]) same as above but with integer as value ( for example to use in Active admin filters )
161
172
  ```
162
173
 
163
- ```
164
- Console:
174
+ ```ruby
165
175
  request.on_delivery!
166
176
  request.delivery_set? # >> true
167
-
177
+
168
178
  Request.delivery_set.exists?(request) # >> true
169
179
  Request.in_warehouse.exists?(request) # >> false
170
-
171
- Request.delivery_set_statuses # >> [:ready_for_shipment, :on_delivery, :delivered]
172
-
173
- Request.with_statuses( :payed, :delivery_set ) # >> :payed and [:ready_for_shipment, :on_delivery, :delivered] requests
174
- Request.without_statuses( :payed ) # >> scope for all requests with statuses not eq to :payed
175
- Request.without_statuses( :payed, :in_warehouse ) # >> scope all requests with statuses not eq to :payed or :ready_for_shipment
176
- ```
177
-
178
- Rem:
179
- ext_enum_sets can be called twice defining a superposition of already defined sets ( considering previous example ):
180
180
 
181
+ Request.delivery_set_statuses # >> ["ready_for_shipment", "on_delivery", "delivered"]
182
+ ```
183
+ Rem:
184
+ ext_enum_sets can be called multiple times defining a superposition of already defined sets ( considering previous example ):
185
+
186
+ ```ruby
187
+ ext_enum_sets :status, {
188
+ outside_wharehouse: ( delivery_set_statuses - in_warehouse_statuses )#... any other array operations like &, + and so can be used
189
+ }
181
190
  ```
191
+
192
+ Rem: you can refer previously defined set as usual kind in the same method call:
193
+
194
+ ```ruby
182
195
  ext_enum_sets :status, {
183
- outside_wharehouse: ( delivery_set_statuses - in_warehouse_statuses )... any other array operations like &, + and so can be used
184
- }
196
+ delivery_set: [:ready_for_shipment, :on_delivery, :delivered],
197
+ not_in_cart: [:paid, :delivery_set] #
198
+ }
185
199
  ```
186
200
 
187
-
188
- ### Mass-assign ( mass_assign_enum )
201
+ ### Multi enum scopes
202
+
203
+ ```ruby
204
+ enum status: [:in_cart, :waiting_for_payment, :paid, :ready_for_shipment, :on_delivery, :delivered],
205
+ ext: [:multi_enum_scopes]
206
+
207
+ # some place else:
208
+ Request.with_statuses( :payed, :delivery_set ) # >> status IN (:payed, :ready_for_shipment, :on_delivery, :delivered)
209
+ Request.without_statuses( :payed, :in_warehouse ) # >> status NOT IN (:payed, :ready_for_shipment)
210
+ ```
211
+
212
+ ### Mass-assign ( enum_mass_assign )
189
213
 
190
214
  Syntax sugar for mass-assigning enum values.
191
215
 
@@ -194,23 +218,25 @@ class:
194
218
  some_scope.update_all(status: Request.statuses[:new_status], update_at: Time.now)
195
219
  ```
196
220
  If you need callbacks you can do like this: some_scope.each(&:new_stat!) but if you don't need callbacks and you
197
- have hundreds and thousands of records to change at once you need update_all
221
+ have hundreds and thousands of records to change at once you better call update_all
198
222
 
199
- ```
200
- mass_assign_enum( :status )
223
+ ```ruby
224
+ enum status: [:in_cart, :waiting_for_payment, :paid, :ready_for_shipment, :on_delivery, :delivered],
225
+ ext: [:mass_assign_enum]
201
226
  ```
202
227
 
203
228
  Console:
204
229
 
205
- ```
230
+ ```ruby
206
231
  request1.in_cart!
207
232
  request2.waiting_for_payment!
208
- Request.non_paid.paid!
209
- request1.paid? # >> true
210
- request2.paid? # >> true
233
+ Request.not_paid.paid!
234
+
235
+ request1.reload.paid? # >> true
236
+ request2.paid? # >> true
211
237
  request1.updated_at # >> ~ Time.now
212
238
 
213
- order.requests.already_paid.count # >> N
239
+ order.requests.already_paid.count # >> N
214
240
  order.requests.delivered.count # >> M
215
241
  order.requests.already_paid.delivered!
216
242
  order.requests.already_paid.count # >> 0
data/enum_ext.gemspec CHANGED
@@ -27,4 +27,5 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency 'rails-i18n', '>=4'
28
28
  spec.add_development_dependency 'sqlite3'
29
29
  spec.add_development_dependency 'byebug'
30
+ spec.add_development_dependency 'stubberry'
30
31
  end
@@ -1,3 +1,3 @@
1
1
  module EnumExt
2
- VERSION = "0.4.5"
2
+ VERSION = "0.5.0"
3
3
  end
data/lib/enum_ext.rb CHANGED
@@ -1,4 +1,5 @@
1
- require 'enum_ext/version'
1
+ require "enum_ext/version"
2
+ require "enum_ext/humanize"
2
3
 
3
4
  # Let's assume we have model Request with enum status, and we have model Order with requests like this:
4
5
  # class Request
@@ -10,11 +11,78 @@ require 'enum_ext/version'
10
11
  # class Order
11
12
  # has_many :requests
12
13
  # end
13
- #
14
+
15
+ puts <<~DEPRECATION
16
+ ---------------------DEPRECATION WARNING---------------------------
17
+ There are TWO MAJOR breaking changes coming into the next version :
18
+ First deprecation: all major DSL moving major class methods to
19
+ enum, just for the sake of clarity:
20
+
21
+ Ex for enum named kinds it could look like this:
22
+
23
+ Class.ext_sets_to_kinds --> Class.kinds.set_to_basic
24
+ Class.ext_kinds --> Class.kinds.sets
25
+ Class.all_kinds_defs --> Class.kinds.all
26
+ Class.t_kinds_options --> Class.kinds.t_options
27
+ Class.t_named_set_kinds_options --> Class.kinds.t_named_set_options
28
+
29
+ Enum extensions preferable way will be using param to original enum call:
30
+ Ex:
31
+ #Instead of three method calls:
32
+ enum kind: {}
33
+ enum_i :kind
34
+ enum_mass_assign :kind
35
+
36
+ #You should go with ext option instead:
37
+ enum kinds: {}, ext: [:enum_i, :enum_mass_assign]
38
+ DEPRECATION
39
+
14
40
  module EnumExt
15
41
 
16
- # defines shortcut for getting integer value of enum.
42
+ class << self
43
+ def define_set_to_enum_method( extended_class, enum_plural)
44
+ # ext_sets_to_kinds( :ready_for_shipment, :delivery_set ) --> [:ready_for_shipment, :on_delivery, :delivered]
45
+ extended_class.define_singleton_method("ext_sets_to_#{enum_plural}") do |*enum_or_sets|
46
+ return [] if enum_or_sets.blank?
47
+ enum_or_sets_strs = enum_or_sets.map(&:to_s)
48
+
49
+ next_level_deeper = try("ext_#{enum_plural}").slice( *enum_or_sets_strs ).values.flatten
50
+ (enum_or_sets_strs & send(enum_plural).keys | send("ext_sets_to_#{enum_plural}", *next_level_deeper)).uniq
51
+ end
52
+ end
53
+
54
+ def define_summary_methods(extended_class, enum_plural)
55
+ extended_class.define_singleton_method("ext_#{enum_plural}") do
56
+ @enum_ext_summary ||= ActiveSupport::HashWithIndifferentAccess.new
57
+ end unless respond_to?("ext_#{enum_plural}")
58
+
59
+ extended_class.define_singleton_method("all_#{enum_plural}") do
60
+ {
61
+ **send(enum_plural),
62
+ "ext_#{enum_plural}": {
63
+ **send("ext_#{enum_plural}")
64
+ }
65
+ } unless respond_to?("all_#{enum_plural}")
66
+ end
67
+ end
68
+ end
69
+
70
+ # extending enum with inplace settings
71
+ # enum status: {}, ext: [:enum_i, :mass_assign_enum, :enum_multi_scopes]
72
+ # enum_i and mass_assign_enum ara
73
+ def enum(definitions)
74
+ extensions = definitions.delete(:ext)
75
+
76
+ super(definitions).tap do
77
+ definitions.each do |name,|
78
+ [*extensions].each{|ext_method| send(ext_method, name) }
79
+ end
80
+ end
81
+ end
82
+
83
+ # Defines instance method a shortcut for getting integer value of an enum.
17
84
  # for enum named 'status' will generate:
85
+ #
18
86
  # instance.status_i
19
87
  def enum_i( enum_name )
20
88
  define_method "#{enum_name}_i" do
@@ -22,9 +90,35 @@ module EnumExt
22
90
  end
23
91
  end
24
92
 
93
+ # Defines two scopes for one for an inclusion: `WHERE enum IN( enum1, enum2 )`,
94
+ # and the second for an exclusion: `WHERE enum NOT IN( enum1, enum2 )`
95
+ #
96
+ # Ex:
97
+ # Request.with_statuses( :payed, :delivery_set ) # >> :payed and [:ready_for_shipment, :on_delivery, :delivered] requests
98
+ # Request.without_statuses( :payed ) # >> scope for all requests with statuses not eq to :payed
99
+ # Request.without_statuses( :payed, :in_warehouse ) # >> scope all requests with statuses not eq to :payed or :ready_for_shipment
100
+ def multi_enum_scopes(enum_name)
101
+ enum_plural = enum_name.to_s.pluralize
102
+
103
+ self.instance_eval do
104
+ # with_enums scope
105
+ scope "with_#{enum_plural}", -> (*enum_list) {
106
+ where( enum_name => send("ext_sets_to_#{enum_plural}", enum_list) )
107
+ } if !respond_to?("with_#{enum_plural}") && respond_to?(:scope)
108
+
109
+ # without_enums scope
110
+ scope "without_#{enum_plural}", -> (*enum_list) {
111
+ where.not( enum_name => send("ext_sets_to_#{enum_plural}", enum_list) )
112
+ } if !respond_to?("without_#{enum_plural}") && respond_to?(:scope)
113
+
114
+ EnumExt.define_set_to_enum_method(self, enum_plural)
115
+ EnumExt.define_summary_methods(self, enum_plural)
116
+ end
117
+ end
25
118
 
26
119
  # ext_enum_sets
27
120
  # This method intend for creating and using some sets of enum values
121
+ #
28
122
  # it creates: scopes for subsets,
29
123
  # instance method with ?,
30
124
  # and some class methods helpers
@@ -58,53 +152,44 @@ module EnumExt
58
152
  # Request.in_warehouse.exists?(request) # >> false
59
153
  #
60
154
  # Request.delivery_set_statuses # >> [:ready_for_shipment, :on_delivery, :delivered]
61
- #
62
- # Request.with_statuses( :payed, :delivery_set ) # >> :payed and [:ready_for_shipment, :on_delivery, :delivered] requests
63
- # Request.without_statuses( :payed ) # >> scope for all requests with statuses not eq to :payed
64
- # Request.without_statuses( :payed, :in_warehouse ) # >> scope all requests with statuses not eq to :payed or :ready_for_shipment
65
- #
66
155
 
67
156
  #Rem:
68
157
  # ext_enum_sets can be called twice defining a superposition of already defined sets ( considering previous example ):
69
158
  # ext_enum_sets :status, {
70
- # outside_wharehouse: ( delivery_set_statuses - in_warehouse_statuses )... any other array operations like &, + and so can be used
159
+ # outside_warehouse: ( delivery_set_statuses - in_warehouse_statuses )... any other array operations like &, + and so can be used
71
160
  # }
72
161
  def ext_enum_sets( enum_name, options = {} )
73
162
  enum_plural = enum_name.to_s.pluralize
74
163
 
75
164
  self.instance_eval do
76
- define_singleton_method("ext_#{enum_plural}") do
77
- @enum_ext_summary ||= {}
78
- end unless respond_to?("ext_#{enum_plural}")
79
-
80
- send("ext_#{enum_plural}").merge!( options )
165
+ EnumExt.define_set_to_enum_method(self, enum_plural)
166
+ EnumExt.define_summary_methods(self, enum_plural)
81
167
 
82
- # with_enums scope
83
- scope "with_#{enum_plural}", -> (sets_arr) {
84
- where( enum_name => self.send( enum_plural ).slice(
85
- *sets_arr.map{|set_name| self.try( "#{set_name}_#{enum_plural}" ) || set_name }.flatten.uniq.map(&:to_s) ).values )
86
- } if !respond_to?("with_#{enum_plural}") && respond_to?(:scope)
168
+ puts(<<~DEPRECATION) unless respond_to?("with_#{enum_plural}")
169
+ ----------------DEPRECATION WARNING----------------
170
+ - with/without_#{enum_plural} are served now via multi_enum_scopes method,
171
+ and will be removed from the ext_enum_sets in the next version!
172
+ DEPRECATION
173
+ multi_enum_scopes(enum_name)
87
174
 
88
- # without_enums scope
89
- scope "without_#{enum_plural}", -> (sets_arr) {
90
- where.not( id: self.send("with_#{enum_plural}", sets_arr) )
91
- } if !respond_to?("without_#{enum_plural}") && respond_to?(:scope)
175
+ send("ext_#{enum_plural}").merge!( options.transform_values{ _1.map(&:to_s) } )
92
176
 
93
177
  options.each do |set_name, enum_vals|
94
178
  # set_name scope
95
- scope set_name, -> { where( enum_name => self.send( enum_plural ).slice( *enum_vals.map(&:to_s) ).values ) } if respond_to?(:scope)
179
+ scope set_name, -> { where( enum_name => send("#{set_name}_#{enum_plural}") ) } if respond_to?(:scope)
96
180
 
97
- # class.enum_set_values
181
+ # class.enum_set_values
98
182
  define_singleton_method( "#{set_name}_#{enum_plural}" ) do
99
- enum_vals
183
+ send("ext_sets_to_#{enum_plural}", *enum_vals)
100
184
  end
101
185
 
102
- # class.enum_set_enums_i
103
- define_singleton_method( "#{set_name}_#{enum_plural}_i" ) do
104
- self.send( "#{enum_plural}" ).slice( *self.send("#{set_name}_#{enum_plural}") ).values
186
+ # instance.set_name?
187
+ define_method "#{set_name}?" do
188
+ send(enum_name) && self.class.send( "#{set_name}_#{enum_plural}" ).include?( send(enum_name) )
105
189
  end
106
190
 
107
191
  # t_... - are translation dependent methods
192
+ # This one is a narrow case helpers just a quick subset of t_ enums options for a set
108
193
  # class.t_enums_options
109
194
  define_singleton_method( "t_#{set_name}_#{enum_plural}_options" ) do
110
195
  return [["Enum translations call missed. Did you forget to call translate #{enum_name}"]*2] unless respond_to?( "t_#{enum_plural}_options_raw" )
@@ -119,28 +204,25 @@ module EnumExt
119
204
  send("t_#{enum_plural}_options_raw_i", send("t_#{set_name}_#{enum_plural}") )
120
205
  end
121
206
 
122
- # instance.set_name?
123
- define_method "#{set_name}?" do
124
- self.send(enum_name) && ( enum_vals.include?( self.send(enum_name) ) || enum_vals.include?( self.send(enum_name).to_sym ))
125
- end
126
-
127
207
  # protected?
128
- # class.t_setname_enums ( translations or humanizations subset for a given set )
208
+ # class.t_set_name_enums ( translations or humanizations subset for a given set )
129
209
  define_singleton_method( "t_#{set_name}_#{enum_plural}" ) do
130
210
  return [(["Enum translations call missed. Did you forget to call translate #{enum_name}"]*2)].to_h unless respond_to?( "t_#{enum_plural}" )
131
211
 
132
- send( "t_#{enum_plural}" ).slice( *self.send("#{set_name}_#{enum_plural}") )
212
+ send( "t_#{enum_plural}" ).slice( *send("#{set_name}_#{enum_plural}") )
133
213
  end
134
214
  end
135
215
  end
136
216
  end
137
217
 
138
218
  # Ex mass_assign_enum
219
+ #
139
220
  # Used for mass assigning for collection without callbacks it creates bang methods for collections using update_all.
140
221
  # it's often case when you need bulk update without callbacks, so it's gets frustrating to repeat:
141
222
  # some_scope.update_all(status: Request.statuses[:new_status], update_at: Time.now)
142
- # If you need callbacks you can do like this: some_scope.each(&:new_stat!) but if you don't need callbacks and you have lots of records
143
- # to change at once you need update_all
223
+ #
224
+ # If you need callbacks you can do like this: some_scope.each(&:new_stat!) but if you don't need callbacks
225
+ # and you have lots of records to change at once you need update_all
144
226
  #
145
227
  # mass_assign_enum( :status )
146
228
  #
@@ -151,14 +233,13 @@ module EnumExt
151
233
  # request1.in_cart!
152
234
  # request2.waiting_for_payment!
153
235
  # Request.with_statuses( :in_cart, :waiting_for_payment ).payed!
154
- # request1.paid? # >> true
155
- # request2.paid? # >> true
236
+ # request1.paid? # >> true
237
+ # request2.paid? # >> true
156
238
  # request1.updated_at # >> Time.now
157
- # defined?(Request::MassAssignEnum) # >> true
158
239
  #
159
- # order.requests.paid.all?(&:paid?) # >> true
240
+ # order.requests.paid.all?(&:paid?) # >> true
160
241
  # order.requests.paid.delivered!
161
- # order.requests.map(&:status).uniq #>> [:delivered]
242
+ # order.requests.map(&:status).uniq #>> [:delivered]
162
243
 
163
244
  def mass_assign_enum( *enums_names )
164
245
  enums_names.each do |enum_name|
@@ -171,10 +252,12 @@ module EnumExt
171
252
  end
172
253
  end
173
254
  end
255
+ alias_method :enum_mass_assign, :mass_assign_enum
174
256
 
175
257
  # if app doesn't need internationalization, it may use humanize_enum to make enum user friendly
258
+ #
176
259
  # class Request
177
- # humanize_enum :status, {
260
+ # humanize_enum :status, {
178
261
  # #locale dependent example with pluralization and lambda:
179
262
  # payed: -> (t_self) { I18n.t("request.status.payed", count: t_self.sum ) }
180
263
  #
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: enum_ext
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - alekseyl
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-02-22 00:00:00.000000000 Z
11
+ date: 2023-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: stubberry
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  description: Enum extension, ads enum sets, mass-assign, localization, and some sugar
112
126
  helpers.
113
127
  email: