enum_ext 0.1.8 → 0.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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +25 -10
- data/lib/enum_ext/version.rb +1 -1
- data/lib/enum_ext.rb +129 -57
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed6a02d91d85ab0c0580df99fc4747513053eef1
|
4
|
+
data.tar.gz: d66d1b253f9bd512c1eed331b980591b4c774222
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14ac092e452730ef84fcc313877de7fb83254c35ca009ba032e9a1794bb3e391141b4f553c0aa7884e2b69d332feb1c94f06e2527a87ca434657562ec0a4de4c
|
7
|
+
data.tar.gz: 171c5a7736a49e9c592c3d92005b93c312610698cc0c7e7d60aed13e5a712eed9728629473aa41f1b1f1d4dd40fd72c4a84227561217051620dd463f64ae1055
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -7,7 +7,7 @@ EnumExt extends rails enum adding localization template, mass-assign on scopes w
|
|
7
7
|
Add this line to your application's Gemfile:
|
8
8
|
|
9
9
|
```ruby
|
10
|
-
gem 'enum_ext'
|
10
|
+
gem 'enum_ext', '~> 0.2'
|
11
11
|
```
|
12
12
|
|
13
13
|
And then execute:
|
@@ -24,7 +24,8 @@ Or install it yourself as:
|
|
24
24
|
class SomeModel
|
25
25
|
extend EnumExt
|
26
26
|
|
27
|
-
|
27
|
+
humanize_enum ...
|
28
|
+
translate_enum ...
|
28
29
|
ext_enum_sets ...
|
29
30
|
mass_assign_enum ...
|
30
31
|
end
|
@@ -43,15 +44,12 @@ Or install it yourself as:
|
|
43
44
|
|
44
45
|
Now let's review some examples of possible enum extensions
|
45
46
|
|
46
|
-
###
|
47
|
+
### Humanization (humanize_enum)
|
47
48
|
|
48
49
|
class Request
|
49
50
|
...
|
50
51
|
localize_enum :status, {
|
51
52
|
|
52
|
-
#locale dependent example ( it dynamically use current locale ):
|
53
|
-
in_cart: -> { I18n.t("request.status.in_cart") },
|
54
|
-
|
55
53
|
#locale dependent example with internal pluralization and lambda:
|
56
54
|
payed: -> (t_self) { I18n.t("request.status.payed", count: t_self.sum ) }
|
57
55
|
|
@@ -81,10 +79,26 @@ If you need some substitution you can go like this:
|
|
81
79
|
request.t_status % {date: Time.now.to_s} >> Delivered at: 05.02.2016
|
82
80
|
|
83
81
|
If you need select status on form:
|
84
|
-
|
85
|
-
|
82
|
+
f.select :status, Request.t_statuses_options
|
83
|
+
|
84
|
+
Works with ext_enum_sets, slicing t_enum_set from original set of enum values ( enum - status, set_name - delivery_set )
|
85
|
+
|
86
|
+
f.select :status, Request.t_delivery_set_statuses_options
|
86
87
|
|
87
|
-
|
88
|
+
### Translate (translate_enum)
|
89
|
+
|
90
|
+
Enum is translated using scope 'active_record.attributes.class_name_underscore.enum', or the given one:\
|
91
|
+
|
92
|
+
translate_enum :status, 'active_record.request.enum'
|
93
|
+
|
94
|
+
Or it can be done with block either with translate or humanize:
|
95
|
+
|
96
|
+
translate_enum :status do
|
97
|
+
I18n.t( "active_record.request.enum.#{status}" )
|
98
|
+
end
|
99
|
+
|
100
|
+
Also since we place by default enum translation in same place as enum name translation
|
101
|
+
human_attribute_name is redefined so it will work fine in ActiveAdmin, but you need to add translation to locale.
|
88
102
|
|
89
103
|
### Enum to_i shortcut ( enum_i )
|
90
104
|
|
@@ -96,7 +110,6 @@ Defines method enum_name_i shortcut for Model.enum_names[elem.enum_name]
|
|
96
110
|
request.payed_i # 10
|
97
111
|
|
98
112
|
|
99
|
-
|
100
113
|
### Enum Sets (ext_enum_sets)
|
101
114
|
|
102
115
|
**Use-case** For example you have pay bills of different types, and you want to group some types in debit and credit "super-types", and have scope PayBill.debit, instance method with question mark as usual enum does pay_bill.debit?.
|
@@ -147,6 +160,7 @@ You can call ext_enum_sets more than one time defining a superposition of alread
|
|
147
160
|
outside_wharehouse: ( delivery_set_statuses - in_warehouse_statuses )... # any other array operations like &, + and so can be used
|
148
161
|
}
|
149
162
|
|
163
|
+
|
150
164
|
### Mass-assign ( mass_assign_enum )
|
151
165
|
|
152
166
|
Syntax sugar for mass-assigning enum values.
|
@@ -177,6 +191,7 @@ You can call ext_enum_sets more than one time defining a superposition of alread
|
|
177
191
|
order.requests.delivered.count # >> N + M
|
178
192
|
|
179
193
|
|
194
|
+
|
180
195
|
####Rem:
|
181
196
|
|
182
197
|
**mass_assign_enum** accepts additional options as last argument. Calling
|
data/lib/enum_ext/version.rb
CHANGED
data/lib/enum_ext.rb
CHANGED
@@ -12,62 +12,6 @@ require "enum_ext/version"
|
|
12
12
|
# end
|
13
13
|
#
|
14
14
|
module EnumExt
|
15
|
-
# Ex using localize_enum with Request
|
16
|
-
# class Request
|
17
|
-
# ...
|
18
|
-
# localize_enum :status, {
|
19
|
-
#
|
20
|
-
# #locale dependent example ( it dynamically use current locale ):
|
21
|
-
# in_cart: -> { I18n.t("request.status.in_cart") },
|
22
|
-
|
23
|
-
# #locale dependent example with pluralization and lambda:
|
24
|
-
# payed: -> (t_self) { I18n.t("request.status.payed", count: t_self.sum ) }
|
25
|
-
|
26
|
-
# #locale dependent example with pluralization and proc:
|
27
|
-
# payed: proc{ I18n.t("request.status.payed", count: self.sum ) }
|
28
|
-
#
|
29
|
-
# #locale independent:
|
30
|
-
# ready_for_shipment: "Ready to go!"
|
31
|
-
#
|
32
|
-
#
|
33
|
-
# }
|
34
|
-
# end
|
35
|
-
|
36
|
-
# Console:
|
37
|
-
# request.sum = 3
|
38
|
-
# request.payed!
|
39
|
-
# request.status # >> payed
|
40
|
-
# request.t_status # >> "Payed 3 dollars"
|
41
|
-
# Request.t_statuses # >> { in_cart: -> { I18n.t("request.status.in_cart") }, .... }
|
42
|
-
|
43
|
-
# if you need some substitution you can go like this
|
44
|
-
# localize_enum :status, {
|
45
|
-
# ..
|
46
|
-
# delivered: "Delivered at: %{date}"
|
47
|
-
# }
|
48
|
-
# request.delivered!
|
49
|
-
# request.t_status % {date: Time.now.to_s} # >> Delivered at: 05.02.2016
|
50
|
-
#
|
51
|
-
# Using in select:
|
52
|
-
# f.select :status, Request.t_statuses.invert.to_a
|
53
|
-
#
|
54
|
-
def localize_enum( enum_name, localizations )
|
55
|
-
self.instance_eval do
|
56
|
-
define_singleton_method( "t_#{enum_name.to_s.pluralize}" ) do
|
57
|
-
localizations.try(:with_indifferent_access) || localizations
|
58
|
-
end
|
59
|
-
define_method "t_#{enum_name}" do
|
60
|
-
t = localizations.try(:with_indifferent_access)[send(enum_name)]
|
61
|
-
if t.try(:lambda?)
|
62
|
-
t.try(:arity) == 1 && t.call( self ) || t.try(:call)
|
63
|
-
elsif t.is_a?(Proc)
|
64
|
-
instance_eval(&t)
|
65
|
-
else
|
66
|
-
t
|
67
|
-
end.to_s
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
15
|
|
72
16
|
def enum_i( enum_name )
|
73
17
|
define_method "#{enum_name}_i" do
|
@@ -75,6 +19,7 @@ module EnumExt
|
|
75
19
|
end
|
76
20
|
end
|
77
21
|
|
22
|
+
|
78
23
|
# Ex ext_enum_sets
|
79
24
|
# This method intend for creating and using some sets of enum values with similar to original enum syntax
|
80
25
|
# it creates: scopes for subsets like enum did, instance method with ? similar to enum methods, and methods like Request.statuses
|
@@ -120,18 +65,30 @@ module EnumExt
|
|
120
65
|
options.each do |set_name, enum_vals|
|
121
66
|
scope set_name, -> { where( enum_name => self.send( enum_name.to_s.pluralize ).slice( *enum_vals.map(&:to_s) ).values ) }
|
122
67
|
|
68
|
+
|
123
69
|
define_singleton_method( "#{set_name}_#{enum_name.to_s.pluralize}" ) do
|
124
70
|
enum_vals
|
125
71
|
end
|
126
72
|
|
73
|
+
# set?
|
127
74
|
define_method "#{set_name}?" do
|
128
75
|
self.send(enum_name) && ( enum_vals.include?( self.send(enum_name) ) || enum_vals.include?( self.send(enum_name).to_sym ))
|
129
76
|
end
|
130
77
|
|
78
|
+
# t_set_enums
|
131
79
|
define_singleton_method( "t_#{set_name}_#{enum_name.to_s.pluralize}" ) do
|
132
|
-
|
80
|
+
send( "t_#{enum_name.to_s.pluralize}" ).slice( *self.send("#{set_name}_#{enum_name.to_s.pluralize}") )
|
133
81
|
end
|
134
82
|
|
83
|
+
# t_set_enums_options
|
84
|
+
define_singleton_method( "t_#{set_name}_#{enum_name.to_s.pluralize}_options" ) do
|
85
|
+
send( "t_#{set_name}_#{enum_name.to_s.pluralize}" ).invert.to_a.map do | key_val |
|
86
|
+
key_val[0] = key_val[0].call if key_val[0].respond_to?(:call) && key_val[0].try(:arity) < 1
|
87
|
+
key_val
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# set_enums_i
|
135
92
|
define_singleton_method( "#{set_name}_#{enum_name.to_s.pluralize}_i" ) do
|
136
93
|
self.send( "#{enum_name.to_s.pluralize}" ).slice( *self.send("#{set_name}_#{enum_name.to_s.pluralize}") ).values
|
137
94
|
end
|
@@ -219,4 +176,119 @@ module EnumExt
|
|
219
176
|
end
|
220
177
|
end
|
221
178
|
|
179
|
+
# Ex using localize_enum with Request
|
180
|
+
# class Request
|
181
|
+
#
|
182
|
+
# if app doesn't need internationalization, it may use humanize_enum to make enum user friendly
|
183
|
+
#
|
184
|
+
# humanize_enum :status, {
|
185
|
+
# #locale dependent example with pluralization and lambda:
|
186
|
+
# payed: -> (t_self) { I18n.t("request.status.payed", count: t_self.sum ) }
|
187
|
+
#
|
188
|
+
# #locale dependent example with pluralization and proc:
|
189
|
+
# payed: proc{ I18n.t("request.status.payed", count: self.sum ) }
|
190
|
+
#
|
191
|
+
# #locale independent:
|
192
|
+
# ready_for_shipment: "Ready to go!"
|
193
|
+
# }
|
194
|
+
# end
|
195
|
+
#
|
196
|
+
# Example with block:
|
197
|
+
#
|
198
|
+
# humanize_enum :status do
|
199
|
+
# I18n.t("scope.#{status}")
|
200
|
+
# end
|
201
|
+
|
202
|
+
# Console:
|
203
|
+
# request.sum = 3
|
204
|
+
# request.payed!
|
205
|
+
# request.status # >> payed
|
206
|
+
# request.t_status # >> "Payed 3 dollars"
|
207
|
+
# Request.t_statuses # >> { in_cart: -> { I18n.t("request.status.in_cart") }, .... }
|
208
|
+
|
209
|
+
# if you need some substitution you can go like this
|
210
|
+
# localize_enum :status, {
|
211
|
+
# ..
|
212
|
+
# delivered: "Delivered at: %{date}"
|
213
|
+
# }
|
214
|
+
# request.delivered!
|
215
|
+
# request.t_status % {date: Time.now.to_s} # >> Delivered at: 05.02.2016
|
216
|
+
#
|
217
|
+
# Using in select:
|
218
|
+
# f.select :status, Request.t_statuses_options
|
219
|
+
#
|
220
|
+
# Rem: select options breaks when using lambda
|
221
|
+
|
222
|
+
def humanize_enum( *args, &block )
|
223
|
+
enum_name = args.shift
|
224
|
+
localizations = args.pop
|
225
|
+
enum_pural = enum_name.to_s.pluralize
|
226
|
+
|
227
|
+
self.instance_eval do
|
228
|
+
|
229
|
+
#t_enums
|
230
|
+
define_singleton_method( "t_#{enum_pural}" ) do
|
231
|
+
# if localization is abscent than block must be given
|
232
|
+
localizations.try(:with_indifferent_access) || localizations ||
|
233
|
+
send(enum_pural).keys.map {|en| [en, self.new( {enum_name => en} ).send("t_#{enum_name}")] }.to_h
|
234
|
+
end
|
235
|
+
|
236
|
+
#t_enums_options
|
237
|
+
define_singleton_method( "t_#{enum_pural}_options" ) do
|
238
|
+
send("t_#{enum_pural}").invert.to_a.map do | key_val |
|
239
|
+
# since all procs in t_enum are evaluated in context of a record than it's not always possible to create select options
|
240
|
+
key_val[0] = ( key_val[0].try(:call) || "Cannot create option for #{key_val[0]}" ) if key_val[0].respond_to?(:call) && key_val[0].try(:arity) < 1
|
241
|
+
key_val
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
#t_enum
|
246
|
+
define_method "t_#{enum_name}" do
|
247
|
+
t = block || localizations.try(:with_indifferent_access)[send(enum_name)]
|
248
|
+
if t.try(:lambda?)
|
249
|
+
t.try(:arity) == 1 && t.call( self ) || t.try(:call)
|
250
|
+
elsif t.is_a?(Proc)
|
251
|
+
instance_eval(&t)
|
252
|
+
else
|
253
|
+
t
|
254
|
+
end.to_s
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
alias localize_enum humanize_enum
|
259
|
+
|
260
|
+
# Simple way to translate enum.
|
261
|
+
# It use either given scope as second argument, or generated activerecord.attributes.model_name_underscore.enum_name
|
262
|
+
# If block is given than no scopes are taken in consider
|
263
|
+
def translate_enum( *args, &block )
|
264
|
+
enum_name = args.shift
|
265
|
+
t_scope = args.pop || "activerecord.attributes.#{self.name.underscore}.#{enum_name}"
|
266
|
+
|
267
|
+
translated_enums << enum_name.to_sym
|
268
|
+
|
269
|
+
if block_given?
|
270
|
+
humanize_enum( enum_name, &block )
|
271
|
+
else
|
272
|
+
humanize_enum( enum_name, send(enum_name.to_s.pluralize).keys.map{|en| [ en, Proc.new{ I18n.t("#{t_scope}.#{en}") }] }.to_h )
|
273
|
+
end
|
274
|
+
|
275
|
+
end
|
276
|
+
|
277
|
+
# It useful for Active Admin, since it use by default human_attribute_name
|
278
|
+
# to translate or humanize elements, if no translation given.
|
279
|
+
# So when enums translated it breaks default human_attribute_name since it's search I18n scope from
|
280
|
+
def human_attribute_name( name, options = {} )
|
281
|
+
enum_translated?(name) ? super( "t_#{name}", options ) : super( name, options )
|
282
|
+
end
|
283
|
+
|
284
|
+
# helper to determine is attribute is translated enum
|
285
|
+
def enum_translated?( name )
|
286
|
+
translated_enums.include?( name.to_sym )
|
287
|
+
end
|
288
|
+
|
289
|
+
private
|
290
|
+
def translated_enums
|
291
|
+
@translated_enums ||= Set.new
|
292
|
+
end
|
293
|
+
|
222
294
|
end
|
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
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- alekseyl
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-03-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|