enu 0.0.1 → 0.0.2

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: 76d6598c2cfc01b242e4244a82ab4be85662394a803c9a1d06622e1b47330bf3
4
- data.tar.gz: 99f43dbaed015274a93c4647d7a2a497126035c965751189d943f18616e99e50
3
+ metadata.gz: dc1b4752d455a471be538cbdfef720a49b96d56d2f56ae5dedfa7a34ccfa25f6
4
+ data.tar.gz: 35fa945c3a4859a18460fb5cbe71babd6eae2a9dc12e7ef2ad509685592bc28a
5
5
  SHA512:
6
- metadata.gz: 890d0fbc649367e4e961042c506d39ef90f4da985e620b00d6c62e8ffed9ba95dd8f1ed351033b6cb1bc658b66c9fbf44a428aaacca89a7d32bf7ea0882ecc83
7
- data.tar.gz: da8a992dc56e7e2349c07ac9387a1b1126050fc897c2bbe73a29403daa2ce305abb24f6d631143a3098b5a171e6f9dbc12d40442b72874bcf8b436d153142e79
6
+ metadata.gz: 52dc8a9a2703e01f62b9fc1d2e09d3f9cc80c96b6cedfcfe4ff6c65c4949b9bb92b3bd96f6c7026e7f30625386223aaa24e021479d8b00e1c8b00b14d7ce7cce
7
+ data.tar.gz: 610af50ee26962f456e885b42475fc2831d396d1b5cd738df1b30ea43dbb40c62517b474e5eb819d0cee572dd1be21b2209cc9cec99c4907b84e80950ee9ef00
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- enu (0.0.1)
4
+ enu (0.0.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # Enu
2
2
 
3
- [![Build Status](https://travis-ci.org/dreikanter/enu.svg?branch=master)](https://travis-ci.org/dreikanter/enu)
3
+ ⚠️ WARNING! This implementation is experimental. Please do not use in production before stable release is announced.
4
4
 
5
- This gem introduce missing enum type for Ruby and Rails.
5
+ This gem introduces missing [enumerated type](https://en.wikipedia.org/wiki/Enumerated_type) for Ruby and Rails.
6
6
 
7
7
  Purpose and features:
8
8
 
9
9
  - Unify enum types definition for Rails model attributes, compatible with ActiveRecord's [enum declarations](https://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html).
10
- - Use constants instead of magic strings or numbers to define enum values.
11
- - Support explicit and implicit enum options definition.
10
+ - Use structured constants instead of magic strings or numbers to define enum values.
12
11
  - Keep track on enum references to simplify refactoring.
12
+ - Support explicit and implicit enum options definition.
13
13
  - Provide a standardized way to export enum definitions to client-side JavaScript modules, managed by either Webpack or Rails Assets Pipeline.
14
14
 
15
15
  ## Installation
@@ -34,11 +34,174 @@ $ gem install enu
34
34
 
35
35
  ## Usage
36
36
 
37
- [TODO]
37
+ ### Enum types definition
38
+
39
+ Here is a basic example:
40
+
41
+ ```ruby
42
+ # app/enums/post_status.rb
43
+ class PostStatus < Enu
44
+ option :draft
45
+ option :published
46
+ option :moderated
47
+ option :deleted
48
+ end
49
+ ```
50
+
51
+ This class defines an enum type for a blog post status which four optional states: `draft`, `published`, `moderated` and `deleted`. Each state automatically receives integer representation: 0 for `draft`, 1 for `published`, and so on. The first option will be treated as `default`.
52
+
53
+ ### Using enums
54
+
55
+ After enum type is defined, it is possible to use it in a Rails model:
56
+
57
+ ```ruby
58
+ # app/models/post.rb
59
+ #
60
+ # Table name: posts
61
+ #
62
+ # id :integer not null, primary key
63
+ # user_id :integer not null
64
+ # status :integer default(0), not null
65
+ # ...
66
+ #
67
+ class Post < ApplicationRecord
68
+ enum status: PostStatus.options
69
+ # ...
70
+ end
71
+ ```
72
+
73
+ `options` class method will return enum representation in the form of a `Hash`, compatible with [ActiveRecord::Enum](https://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html) declaration:
74
+
75
+ ```ruby
76
+ PostStatus.options # {"draft"=>0, "published"=>1, "moderated" => 2, "deleted"=>3}
77
+ ```
78
+
79
+ Use [enum helpers](https://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html) as usual:
80
+
81
+ ```ruby
82
+ Post.new.draft? # true
83
+ Post.new.published? # false
84
+
85
+ post = Post.create! # #<Post:...>
86
+ post.draft? # true
87
+ post.published! # true
88
+ post.status # "published"
89
+
90
+ Post.published.to_sql # "SELECT "posts".* FROM "posts" WHERE "posts"."status" = 1"
91
+ ```
92
+
93
+ ### Scoped constants
94
+
95
+ Sometimes native helper methods are not enough, and you need to address enum values directly. If this is the case, use scoped constants instead of magic strings values. Say, you need to update multiple attributes for a set of DB records with a single query:
96
+
97
+ ```ruby
98
+ # app/models/user.rb
99
+ #
100
+ # Table name: posts
101
+ #
102
+ # id :integer not null, primary key
103
+ # user_id :integer not null
104
+ # ...
105
+ #
106
+ class User < ApplicationRecord
107
+ has_many :posts
108
+
109
+ def nasty_spammer?
110
+ # ...
111
+ end
112
+ end
113
+
114
+ use = User.first
115
+
116
+ if user.nasty_spammer?
117
+ user.posts.update_all(
118
+ status: PostStatus.moderated,
119
+ moderated_by: current_user,
120
+ moderated_at: Time.new.utc,
121
+ moderation_reason: 'being a nasty spammer'
122
+ )
123
+ end
124
+ ```
125
+
126
+ Another example is a state machine definition with [aasm](https://github.com/aasm/aasm) gem:
127
+
128
+ ```ruby
129
+ class Post < ApplicationRecord
130
+ include AASM
131
+
132
+ enum status: PostStatus.options
133
+
134
+ aasm column: :status, enum: true do
135
+ state PostStatus.draft, initial: true
136
+ state PostStatus.published
137
+ state PostStatus.moderated
138
+ state PostStatus.deleted
139
+
140
+ # Draft posts can be published
141
+ event :publish do
142
+ transitions from: PostStatus.draft, to: PostStatus.published
143
+ end
144
+
145
+ # Published posts can be moderated
146
+ event :moderate do
147
+ transitions from: PostStatus.published, to: PostStatus.moderated
148
+ end
149
+
150
+ # Any post can be deleted (but only once)
151
+ event :dump do
152
+ transitions from: PostStatus.keys.without(:deleted), to: PostStatus.deleted
153
+ end
154
+ end
155
+ end
156
+ ```
157
+
158
+ Notice that `dump` event is using `PostStatus.keys` shortcut, instead of declaring a separate transition for each available post status. `Enu` provides `keys` and `values` class methods for each enum type.
159
+
160
+ Now the `Post#state` field has transition rules:
161
+
162
+ ```ruby
163
+ post = Post.create! # new record status will be initialized with "draft" value
164
+ post.status # => "draft"
165
+
166
+ post.publish! # performs sample transition and persist the new status
167
+ post.status # => "published"
168
+
169
+ post.dump!
170
+ post.moderate! # will raise an AASM::InvalidTransition, because deleted
171
+ # posts are not supposed to be moderated
172
+ ```
173
+
174
+ ### Code base navigation
175
+
176
+ Scoped constants will help to track enum type references in your codebase. Looking up an enum class name or a specific value, like `PostStatus.draft`, is a more efficient way to navigate your codebase, comparing to a situation when you use plain string literals or symbols, like in the [Rails Guides examples](https://guides.rubyonrails.org/active_record_querying.html#enums). Chances are search results for `draft` will be much noisier in a large codebase.
177
+
178
+ Notice the source file location. Keeping enum type definitions in a separate location is not mandatory, though, it will help to keep the source code organized. In a typical Rails application project [autoload](https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#autoload-paths-and-eager-load-paths) mechanism will resolve all constants in `app` subdirectories, so there is no need to worry about requiring anything manually.
179
+
180
+ This readme uses `PostStatus` for the sake of brevity. In a larger real-life code base, though, it is worth considering to organize sibling classes with a module, instead of polluting root namespace:
181
+
182
+ ```ruby
183
+ # app/enums/post_status.rb
184
+ module Enums
185
+ class PostStatus < Enu
186
+ # ...
187
+ end
188
+ end
189
+ ```
190
+
191
+ Default Rails autoload configuration will successfully resolve `Enums::PostStatus` constant.
192
+
193
+ #### Spring gotcha
194
+
195
+ There is a known issue with using custom directories in a Rails application. If you running your app with [Spring preloader](https://github.com/rails/spring) (which is true for default configuration), make sure to restart the preloader. Otherwise, Rails autoload will not resolve any constants under `app/enums/` or any other custom paths, and will keep raising `NameError`. This command will help:
196
+
197
+ ```bash
198
+ > bin/spring stop
199
+ Spring stopped.
200
+ ```
38
201
 
39
202
  ## Development
40
203
 
41
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
204
+ After checking out the repository, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
42
205
 
43
206
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
44
207
 
data/enu.gemspec CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ["Alex Musayev"]
9
9
  spec.email = ["alex.musayev@gmail.com"]
10
10
 
11
- spec.summary = "Missing enum type for Ruby and Rails"
11
+ spec.summary = "[Experimental] Missing enum type for Ruby and Rails"
12
12
  spec.description = ""
13
13
  spec.homepage = "https://github.com/dreikanter/enu"
14
14
  spec.license = "MIT"
data/lib/enu.rb CHANGED
@@ -54,4 +54,6 @@ class Enu
54
54
  return 0 if values.empty?
55
55
  values.max + 1
56
56
  end
57
+
58
+ private_class_method :next_value
57
59
  end
data/lib/enu/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Enu
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: enu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Musayev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-30 00:00:00.000000000 Z
11
+ date: 2019-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -223,5 +223,5 @@ requirements: []
223
223
  rubygems_version: 3.0.3
224
224
  signing_key:
225
225
  specification_version: 4
226
- summary: Missing enum type for Ruby and Rails
226
+ summary: "[Experimental] Missing enum type for Ruby and Rails"
227
227
  test_files: []