enum_ext 0.4.5 → 0.5.0

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: 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: