enumerize 2.1.2 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +10 -9
  3. data/CHANGELOG.md +50 -3
  4. data/Gemfile +2 -3
  5. data/Gemfile.global +1 -2
  6. data/Gemfile.mongo_mapper +2 -3
  7. data/Gemfile.rails60 +6 -0
  8. data/Gemfile.rails61 +6 -0
  9. data/README.md +37 -1
  10. data/Rakefile +2 -0
  11. data/lib/enumerize.rb +9 -0
  12. data/lib/enumerize/activemodel.rb +47 -0
  13. data/lib/enumerize/activerecord.rb +33 -3
  14. data/lib/enumerize/attribute.rb +19 -11
  15. data/lib/enumerize/attribute_map.rb +2 -0
  16. data/lib/enumerize/base.rb +6 -6
  17. data/lib/enumerize/hooks/formtastic.rb +4 -1
  18. data/lib/enumerize/hooks/sequel_dataset.rb +2 -0
  19. data/lib/enumerize/hooks/simple_form.rb +4 -1
  20. data/lib/enumerize/hooks/uniqueness.rb +5 -1
  21. data/lib/enumerize/integrations/rails_admin.rb +3 -1
  22. data/lib/enumerize/integrations/rspec.rb +2 -0
  23. data/lib/enumerize/integrations/rspec/matcher.rb +7 -2
  24. data/lib/enumerize/module.rb +2 -0
  25. data/lib/enumerize/module_attributes.rb +2 -0
  26. data/lib/enumerize/mongoid.rb +16 -0
  27. data/lib/enumerize/predicatable.rb +3 -1
  28. data/lib/enumerize/predicates.rb +2 -0
  29. data/lib/enumerize/scope/activerecord.rb +12 -0
  30. data/lib/enumerize/scope/mongoid.rb +11 -0
  31. data/lib/enumerize/scope/sequel.rb +12 -0
  32. data/lib/enumerize/sequel.rb +9 -4
  33. data/lib/enumerize/set.rb +2 -0
  34. data/lib/enumerize/utils.rb +12 -0
  35. data/lib/enumerize/value.rb +14 -15
  36. data/lib/enumerize/version.rb +1 -1
  37. data/lib/sequel/plugins/enumerize.rb +18 -0
  38. data/spec/enumerize/integrations/rspec/matcher_spec.rb +13 -10
  39. data/spec/spec_helper.rb +2 -0
  40. data/test/activemodel_test.rb +114 -0
  41. data/test/activerecord_test.rb +127 -5
  42. data/test/attribute_map_test.rb +2 -0
  43. data/test/attribute_test.rb +7 -0
  44. data/test/base_test.rb +35 -33
  45. data/test/formtastic_test.rb +25 -0
  46. data/test/module_attributes_test.rb +2 -0
  47. data/test/mongo_mapper_test.rb +12 -3
  48. data/test/mongoid_test.rb +30 -4
  49. data/test/multiple_test.rb +19 -11
  50. data/test/predicates_test.rb +12 -10
  51. data/test/rails_admin_test.rb +7 -5
  52. data/test/sequel_test.rb +62 -12
  53. data/test/set_test.rb +6 -4
  54. data/test/simple_form_test.rb +25 -0
  55. data/test/support/mock_controller.rb +2 -0
  56. data/test/support/shared_enums.rb +43 -0
  57. data/test/support/view_test_helper.rb +14 -1
  58. data/test/test_helper.rb +2 -0
  59. data/test/value_test.rb +33 -5
  60. metadata +15 -9
  61. data/Gemfile.rails42 +0 -7
  62. data/Gemfile.rails51 +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f5a43e5546fd78ed42c35abfccc3314e52b7671f
4
- data.tar.gz: 727be0571656833f27ee73ff8d65d6455c7511e4
2
+ SHA256:
3
+ metadata.gz: 15a8427afecf01652e67b4758c05a499ba541254799d8ca61f0146f942647388
4
+ data.tar.gz: ee769906574712f378ca8dfb8aaadcfcc5993a485531cf520b44c41420e8fa84
5
5
  SHA512:
6
- metadata.gz: 88cfa3f67475bf8d18279b7f53124051237c3a5bfe302e88860f5c405834cd95ebe9cfca67eb0d721c52ca746a15458cf284d2a376b049ede0b6b69379f667a6
7
- data.tar.gz: f57a1bca5a058f2074d834968418865455f4e0ccf3aa2441064f05cb5901a4eb8ec4776cd2e95c938635a41659723679108d873caa338e8487879e91fbcafb25
6
+ metadata.gz: 46edf9a1fed39c9122247957a64dab6a773f5d0a8d0176204e48bd9d28074019480c1ae3cf16ccc3ad7a185d64fb7cf92d9f1a5ec63a581a388d1dd4620ac651
7
+ data.tar.gz: 206734dd6819196fbdff49e89626d30e45cd29154a63151f8631c87d13d15c7bd2bae90916b411a7f7d71287fa5be5a742f281392348f3c330401dde9d4b72c2
@@ -1,18 +1,21 @@
1
+ dist: focal
1
2
  language: ruby
2
3
  sudo: false
3
4
  services:
4
- - postgresql
5
5
  - mongodb
6
+ addons:
7
+ postgresql: "13"
6
8
  gemfile:
7
9
  - Gemfile
8
- - Gemfile.rails42
9
- - Gemfile.rails51
10
+ - Gemfile.rails60
11
+ - Gemfile.rails61
10
12
  - Gemfile.mongo_mapper
11
13
  rvm:
12
- - 2.2.7
13
- - 2.3.3
14
- - 2.4.1
15
- - jruby-9.1.8.0
14
+ - 2.5.8
15
+ - 2.6.6
16
+ - 2.7.1
17
+ before_install:
18
+ - gem install bundler
16
19
  env:
17
20
  global:
18
21
  - DB_USER=postgres
@@ -22,8 +25,6 @@ env:
22
25
  - DB=postgresql
23
26
  matrix:
24
27
  fast_finish: true
25
- allow_failures:
26
- - rvm: jruby-9.1.8.0
27
28
  exclude:
28
29
  - gemfile: Gemfile.mongo_mapper
29
30
  env: DB=postgresql
@@ -1,9 +1,56 @@
1
- ## master
1
+ ## 2.4.0 (December 12, 2020)
2
2
 
3
3
  ### enhancements
4
4
 
5
+ * Show warning when enumerized value name conflicts with existing object's methods. (by [@aki77](https://github.com/aki77))
6
+ * Add RSpec support for shallow scopes. (by [@nashby](https://github.com/nashby))
7
+ * Drop support for Ruby older than 2.5. Support only Ruby 2.5+. (by [@nashby](https://github.com/nashby))
8
+ * Drop support for Rails 4. Support only Rails 5.2+. (by [@nashby](https://github.com/nashby))
9
+ * Add support for Rails 6.1 (by [@y-yagi](https://github.com/y-yagi))
10
+
11
+ ### bug fix
12
+
13
+ * Fix exception when using predicate methods on enumerized value transformed into invalid value. (by [@guigs](https://github.com/guigs))
14
+ * Fix issue with RSpec#with_predicates matcher when custom values are used as attribute. (by [@nashby](https://github.com/nashby))
15
+
16
+ ## 2.3.1 (May 2, 2019)
17
+
18
+ ### enhancements
19
+
20
+ * Add ability to skip validations by passing `:skip_validations` option. (by [@chumakoff](https://github.com/chumakoff))
21
+ * Add option `scope: shallow` to extend scopes based on enumerized attribute values (by [@moofkit](https://github.com/moofkit/))
22
+
23
+ ### bug fix
24
+
25
+ * Fix issue with ActiveRecord and Mongoid `reload` method when enumberized attributes weren't synced from DB. (by [@nashby](https://github.com/nashby) and [@FunkyloverOne](https://github.com/FunkyloverOne))
26
+ * Fix issue with ActiveRecord `reload` method not working for ActiveRecord::Store attributes due to `1b776c`. (by [@rickcsong](https://github.com/rickcsong))
27
+
28
+ ## 2.2.2 (March 6, 2018)
29
+
30
+ ### bug fix
31
+
32
+ * Support non-ActiveModel objects in SimpleForm/Formtastic integration. (by [@nashby](https://github.com/nashby))
33
+
34
+ ## 2.2.1 (February 15, 2018)
35
+
5
36
  ### bug fix
6
37
 
38
+ * Fix issue with SimpleForm/Formtastic forms without object. (by [@nashby](https://github.com/nashby))
39
+
40
+ ## 2.2.0 (February 13, 2018)
41
+
42
+ ### enhancements
43
+
44
+ * Add integration with active_interaction. (by [@runephilosof](https://github.com/runephilosof))
45
+ * Allow using `plugin :enumerize` with Sequel. (by [@jnylen](https://github.com/jnylen))
46
+ * Support ActiveModel::Attributes from Rails 5.2. (by [@troter](https://github.com/troter))
47
+ * Support Sequel 5.2.0. (by [@troter](https://github.com/troter))
48
+
49
+ ### bug fix
50
+
51
+ * Fix RailsAdmin integration when enumerated field used on edit form and enumerated value wasn't set. (by [@nashby](https://github.com/nashby))
52
+ * Fallback to a raw passed value instead of nil if AR type can't find value in the attribute. (by [@nashby](https://github.com/nashby))
53
+
7
54
  ## 2.1.2 (May 18, 2017)
8
55
 
9
56
  ### bug fix
@@ -41,11 +88,11 @@
41
88
  * Drop support for Rails 4.0 and 4.1. Support only Rails 4.2 and newer. (by [@lest](https://github.com/lest))
42
89
  * Support Rails 5.0. (by [@nashby](https://github.com/nashby) and [@lest](https://github.com/lest))
43
90
  * Allow to pass enumerize values to `ActiveRecord#update_all` (by [@DmitryTsepelev](https://github.com/DmitryTsepelev) and [@ianwhite](https://github.com/ianwhite))
44
-
91
+
45
92
  ```ruby
46
93
  User.update_all(status: :blocked)
47
94
  ```
48
-
95
+
49
96
  ### bug fix
50
97
 
51
98
  * Rescue MissingAttributeError on attribute writing. (by [@embs](https://github.com/embs))
data/Gemfile CHANGED
@@ -1,7 +1,6 @@
1
1
  eval_gemfile('Gemfile.global')
2
2
 
3
3
  gem 'minitest', '~> 5.8'
4
- gem 'rails', '5.0.2', require: false
5
- gem 'activerecord-jdbcsqlite3-adapter', github: 'jruby/activerecord-jdbc-adapter', branch: 'rails-5', platform: :jruby
6
- gem 'activerecord-jdbcpostgresql-adapter', github: 'jruby/activerecord-jdbc-adapter', branch: 'rails-5', platform: :jruby
4
+ gem 'rails', '~> 5.2.4', require: false
7
5
  gem 'mongoid'
6
+ gem 'sqlite3', '~> 1.3.6', :platform => [:ruby, :mswin, :mingw]
@@ -5,8 +5,7 @@ gemspec
5
5
  gem 'rake'
6
6
  gem 'rspec', :require => false
7
7
 
8
- gem 'sqlite3', :platform => [:ruby, :mswin, :mingw]
9
- gem 'pg', :platform => [:ruby, :mswin, :mingw]
8
+ gem 'pg', '~> 1.2.3', :platform => [:ruby, :mswin, :mingw]
10
9
  gem 'sequel'
11
10
 
12
11
  platforms :rbx do
@@ -1,7 +1,6 @@
1
1
  eval_gemfile('Gemfile.global')
2
2
 
3
3
  gem 'minitest', '~> 5.8'
4
- gem 'rails', '4.2.8', :require => false
5
- gem 'activerecord-jdbcsqlite3-adapter', platform: :jruby
6
- gem 'activerecord-jdbcpostgresql-adapter', platform: :jruby
4
+ gem 'rails', '~> 5.2.4', :require => false
7
5
  gem 'mongo_mapper'
6
+ gem 'sqlite3', '~> 1.3.6', :platform => [:ruby, :mswin, :mingw]
@@ -0,0 +1,6 @@
1
+ eval_gemfile('Gemfile.global')
2
+
3
+ gem 'minitest', '~> 5.8'
4
+ gem 'rails', '~> 6.0.0', require: false
5
+ gem 'mongoid', github: 'mongodb/mongoid'
6
+ gem 'sqlite3', :platform => [:ruby, :mswin, :mingw]
@@ -0,0 +1,6 @@
1
+ eval_gemfile('Gemfile.global')
2
+
3
+ gem 'minitest', '~> 5.8'
4
+ gem 'rails', github: 'rails/rails', branch: '6-1-stable', require: false
5
+ gem 'mongoid', github: 'mongodb/mongoid'
6
+ gem 'sqlite3', :platform => [:ruby, :mswin, :mingw]
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Enumerize [![TravisCI](https://secure.travis-ci.org/brainspec/enumerize.svg?branch=master)](http://travis-ci.org/brainspec/enumerize) [![Gemnasium](https://gemnasium.com/brainspec/enumerize.svg)](https://gemnasium.com/brainspec/enumerize)
1
+ # Enumerize [![TravisCI](https://secure.travis-ci.org/brainspec/enumerize.svg?branch=master)](http://travis-ci.org/brainspec/enumerize)
2
2
 
3
3
  Enumerated attributes with I18n and ActiveRecord/Mongoid/MongoMapper/Sequel support
4
4
 
@@ -16,6 +16,10 @@ Or install it yourself as:
16
16
 
17
17
  $ gem install enumerize
18
18
 
19
+ ## Supported Versions
20
+ - Ruby 2.5+
21
+ - Rails 5.2+
22
+
19
23
  ## Usage
20
24
 
21
25
  Basic:
@@ -54,6 +58,18 @@ class User < ActiveRecord::Base
54
58
  end
55
59
  ```
56
60
 
61
+ :warning: By default, `enumerize` adds `inclusion` validation to the model. You can skip validations by passing `skip_validations` option. :warning:
62
+
63
+ ```ruby
64
+ class User < ActiveRecord::Base
65
+ extend Enumerize
66
+
67
+ enumerize :sex, in: [:male, :female], skip_validations: lambda { |user| user.new_record? }
68
+
69
+ enumerize :role, in: [:user, :admin], skip_validations: true
70
+ end
71
+ ```
72
+
57
73
  Mongoid:
58
74
 
59
75
  ```ruby
@@ -252,6 +268,24 @@ User.having_status(:blocked).with_sex(:male, :female)
252
268
  # SELECT "users".* FROM "users" WHERE "users"."status" IN (2) AND "users"."sex" IN ('male', 'female')
253
269
  ```
254
270
 
271
+ Shallow scopes:
272
+
273
+ Adds named scopes to the class directly
274
+
275
+ ```ruby
276
+ class User < ActiveRecord::Base
277
+ extend Enumerize
278
+ enumerize :sex, :in => [:male, :female], scope: :shallow
279
+ enumerize :status, :in => { active: 1, blocked: 2 }, scope: :shallow
280
+ end
281
+
282
+ User.male
283
+ # SELECT "users".* FROM "users" WHERE "users"."sex" = 'male'
284
+
285
+ User.active
286
+ # SELECT "users".* FROM "users" WHERE "users"."status" = 1
287
+ ```
288
+
255
289
  :warning: It is not possible to define a scope when using the `:multiple` option. :warning:
256
290
 
257
291
  Array-like attributes with plain ruby objects:
@@ -315,6 +349,8 @@ and if you want it as radio buttons:
315
349
  <% end %>
316
350
  ```
317
351
 
352
+ Please note that Enumerize overwrites the I18n keys of SimpleForm collections. The enumerized keys are used instead of the SimpleForm ones for inputs concerning enumerized attributes. If you don't want this just pass `:collection` option to the `input` call.
353
+
318
354
  ### Formtastic
319
355
 
320
356
  If you are using Formtastic gem you also don't need to specify input type (`:select` by default) and collection:
data/Rakefile CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env rake
2
+ # frozen_string_literal: true
3
+
2
4
  require "bundler/gem_tasks"
3
5
 
4
6
  require 'rake/testtask'
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support/concern'
4
+ require 'active_support/core_ext/object/blank'
2
5
  require 'enumerize/version'
3
6
 
4
7
  module Enumerize
@@ -10,8 +13,10 @@ module Enumerize
10
13
  autoload :Module, 'enumerize/module'
11
14
  autoload :Predicates, 'enumerize/predicates'
12
15
  autoload :Predicatable, 'enumerize/predicatable'
16
+ autoload :Utils, 'enumerize/utils'
13
17
  autoload :ModuleAttributes, 'enumerize/module_attributes'
14
18
 
19
+ autoload :ActiveModelAttributesSupport, 'enumerize/activemodel'
15
20
  autoload :ActiveRecordSupport, 'enumerize/activerecord'
16
21
  autoload :SequelSupport, 'enumerize/sequel'
17
22
  autoload :MongoidSupport, 'enumerize/mongoid'
@@ -31,6 +36,10 @@ module Enumerize
31
36
  base.send :include, Enumerize::Base
32
37
  base.extend Enumerize::Predicates
33
38
 
39
+ if defined?(::ActiveModel::Attributes)
40
+ base.extend Enumerize::ActiveModelAttributesSupport
41
+ end
42
+
34
43
  if defined?(::ActiveRecord::Base)
35
44
  base.extend Enumerize::ActiveRecordSupport
36
45
  base.extend Enumerize::Scope::ActiveRecord
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Enumerize
4
+ module ActiveModelAttributesSupport
5
+ def enumerize(name, options={})
6
+ super
7
+
8
+ _enumerize_module.dependent_eval do
9
+ if self.included_modules.include? ::ActiveModel::Attributes
10
+ include InstanceMethods
11
+
12
+ attribute name, Enumerize::ActiveModelAttributesSupport::Type.new(enumerized_attributes[name])
13
+ end
14
+ end
15
+ end
16
+
17
+ module InstanceMethods
18
+ # https://github.com/brainspec/enumerize/issues/74
19
+ def write_attribute(attr_name, value, *options)
20
+ if self.class.enumerized_attributes[attr_name]
21
+ _enumerized_values_for_validation[attr_name.to_s] = value
22
+ end
23
+
24
+ super
25
+ end
26
+ end
27
+
28
+ class Type < ActiveModel::Type::Value
29
+ def type
30
+ :enumerize
31
+ end
32
+
33
+ def initialize(attr)
34
+ @attr = attr
35
+ end
36
+
37
+ def serialize(value)
38
+ v = @attr.find_value(value)
39
+ v && v.value
40
+ end
41
+
42
+ def deserialize(value)
43
+ @attr.find_value(value)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Enumerize
2
4
  module ActiveRecordSupport
3
5
  def enumerize(name, options={})
@@ -19,8 +21,14 @@ module Enumerize
19
21
  require 'enumerize/hooks/uniqueness'
20
22
 
21
23
  unless options[:multiple]
22
- decorate_attribute_type(name, :enumerize) do |subtype|
23
- Type.new(enumerized_attributes[name], subtype)
24
+ if ::ActiveRecord.version >= ::Gem::Version.new("6.1.0.alpha")
25
+ decorate_attribute_type(name.to_s) do |subtype|
26
+ Type.new(enumerized_attributes[name], subtype)
27
+ end
28
+ else
29
+ decorate_attribute_type(name, :enumerize) do |subtype|
30
+ Type.new(enumerized_attributes[name], subtype)
31
+ end
24
32
  end
25
33
  end
26
34
  end
@@ -50,6 +58,28 @@ module Enumerize
50
58
 
51
59
  became
52
60
  end
61
+
62
+ def reload(options = nil)
63
+ reloaded = super
64
+
65
+ reloaded.class.enumerized_attributes.each do |attr|
66
+ begin
67
+ # Checks first if the enumerized attribute is in ActiveRecord::Store
68
+ store_attr, _ = reloaded.class.stored_attributes.detect do |store_attr, keys|
69
+ keys.include?(attr.name)
70
+ end
71
+
72
+ if store_attr.present?
73
+ reloaded.send("#{attr.name}=", reloaded.send(store_attr).with_indifferent_access[attr.name])
74
+ else
75
+ reloaded.send("#{attr.name}=", reloaded[attr.name])
76
+ end
77
+ rescue ActiveModel::MissingAttributeError
78
+ end
79
+ end
80
+
81
+ reloaded
82
+ end
53
83
  end
54
84
 
55
85
  module RelationMethods
@@ -76,7 +106,7 @@ module Enumerize
76
106
 
77
107
  def serialize(value)
78
108
  v = @attr.find_value(value)
79
- v && v.value
109
+ (v && v.value) || value
80
110
  end
81
111
 
82
112
  alias type_cast_for_database serialize
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Enumerize
2
4
  class Attribute
3
- attr_reader :klass, :name, :values, :default_value, :i18n_scope
5
+ attr_reader :klass, :name, :values, :default_value, :i18n_scope, :skip_validations_value
4
6
 
5
7
  def initialize(klass, name, options={})
6
8
  raise ArgumentError, ':in option is required' unless options[:in]
@@ -11,21 +13,23 @@ module Enumerize
11
13
  @klass = klass
12
14
  @name = name.to_sym
13
15
 
14
- value_class = options.fetch(:value_class, Value)
15
- @values = Array(options[:in]).map { |v| value_class.new(self, *v) }
16
-
17
- @value_hash = Hash[@values.map { |v| [v.value.to_s, v] }]
18
- @value_hash.merge! Hash[@values.map { |v| [v.to_s, v] }]
19
-
20
16
  if options[:i18n_scope]
21
17
  raise ArgumentError, ':i18n_scope option accepts only String or Array of strings' unless Array(options[:i18n_scope]).all? { |s| s.is_a?(String) }
22
18
  @i18n_scope = options[:i18n_scope]
23
19
  end
24
20
 
21
+ value_class = options.fetch(:value_class, Value)
22
+ @values = Array(options[:in]).map { |v| value_class.new(self, *v).freeze }
23
+
24
+ @value_hash = Hash[@values.map { |v| [v.value.to_s, v] }]
25
+ @value_hash.merge! Hash[@values.map { |v| [v.to_s, v] }]
26
+
25
27
  if options[:default]
26
28
  @default_value = find_default_value(options[:default])
27
29
  raise ArgumentError, 'invalid default value' unless @default_value
28
30
  end
31
+
32
+ @skip_validations_value = options.fetch(:skip_validations, false)
29
33
  end
30
34
 
31
35
  def find_default_value(value)
@@ -44,11 +48,15 @@ module Enumerize
44
48
  values.map { |value| find_value(value) }.compact
45
49
  end
46
50
 
51
+ def each_value
52
+ values.each { |value| yield value }
53
+ end
54
+
47
55
  def i18n_scopes
48
56
  @i18n_scopes ||= if i18n_scope
49
- scopes = Array(i18n_scope)
57
+ Array(i18n_scope)
50
58
  elsif @klass.respond_to?(:model_name)
51
- scopes = ["enumerize.#{@klass.model_name.i18n_key}.#{name}"]
59
+ ["enumerize.#{@klass.model_name.i18n_key}.#{name}"]
52
60
  else
53
61
  []
54
62
  end
@@ -164,7 +172,7 @@ module Enumerize
164
172
 
165
173
  def #{name}=(values)
166
174
  @_#{name}_enumerized_set = Enumerize::Set.new(self, self.class.enumerized_attributes[:#{name}], values)
167
- raw_values = #{name}.values.map(&:value)
175
+ raw_values = self.#{name}.values.map(&:value)
168
176
 
169
177
  if defined?(super)
170
178
  super raw_values
@@ -176,7 +184,7 @@ module Enumerize
176
184
 
177
185
  _enumerized_values_for_validation['#{name}'] = values.respond_to?(:map) ? values.reject(&:blank?).map(&:to_s) : values
178
186
 
179
- #{name}
187
+ self.#{name}
180
188
  end
181
189
  RUBY
182
190
  end