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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1a1510d12023a14d33c2e944a41354de1e7aee23
4
- data.tar.gz: 54ec02ec7bcc827fd6b3d5a731e8ba0ebe3f88a8
3
+ metadata.gz: ed6a02d91d85ab0c0580df99fc4747513053eef1
4
+ data.tar.gz: d66d1b253f9bd512c1eed331b980591b4c774222
5
5
  SHA512:
6
- metadata.gz: 797719321c75c6b9b9920075cbd7f18e60eab038cd3d92c16bbdb83f878044c7233f30869e491009926cae6b7fa79303d176abebe7854f58ab9101ebaaf53287
7
- data.tar.gz: 95558724f73fcd3311983c9f4932ebadb833d4b44056dea8110a0b1a4135c0ed1d9c84af02473afbf7d0c983d66f67de76a5e97b949039de946eeea6009f4816
6
+ metadata.gz: 14ac092e452730ef84fcc313877de7fb83254c35ca009ba032e9a1794bb3e391141b4f553c0aa7884e2b69d332feb1c94f06e2527a87ca434657562ec0a4de4c
7
+ data.tar.gz: 171c5a7736a49e9c592c3d92005b93c312610698cc0c7e7d60aed13e5a712eed9728629473aa41f1b1f1d4dd40fd72c4a84227561217051620dd463f64ae1055
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- enum_ext (0.1.7)
4
+ enum_ext (0.1.8)
5
5
  activerecord (>= 4.1)
6
6
 
7
7
  GEM
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
- localize_enum ...
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
- ### Localization (localize_enum)
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
- f.select :status, Request.t_statuses.invert.to_a
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
- Works with ext_enum_sets, slicing t_enum_set from original set of enum values
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
@@ -1,3 +1,3 @@
1
1
  module EnumExt
2
- VERSION = "0.1.8"
2
+ VERSION = "0.2.0"
3
3
  end
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
- self.send( "t_#{enum_name.to_s.pluralize}" ).slice( *self.send("#{set_name}_#{enum_name.to_s.pluralize}") )
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.1.8
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: 2016-11-10 00:00:00.000000000 Z
11
+ date: 2017-03-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord