enum_ext 0.1.8 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|