array_enum 1.0.1 → 1.4.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
  SHA256:
3
- metadata.gz: afc3f9133c5efe0de0320c4b83e650969ab9b647b29b242f2d44dfb58d2a726f
4
- data.tar.gz: 9a9ee4607992a52138f6fea70e0eb329554b50e675b37f8e700305b04ff161b9
3
+ metadata.gz: 5d2df08c37b57f1ab526c97e96687aaa26d6f4cdbbd7cf189a1671b4fc2ad309
4
+ data.tar.gz: a4a87c06b773f5b8210d67e869372e99e838853962789a5d030bd8ec2fbc9a9e
5
5
  SHA512:
6
- metadata.gz: 3f96c19d50fac52b7bc2041d4983c9880807944226074132ce3c16b3a7ad99a1f00648f501d5535b8edaba1a932216ff0fb6196531dae7c9d09e3eb0bb06f6b9
7
- data.tar.gz: 43e71fc9ba6e47fd70b4fadad42d6b901d03f5e92238201e6e157338212db3d710ffcbffbb10fa8be0cf5be444a4c584de6c09d2272d42ace912d32087224321
6
+ metadata.gz: 153d73f33212247cba61d862b31948bd66c50c352f2984fbfbe00c71ce77a8086a8925e3256bfa03013a32050442a6be7014da888493a3c422256ac85d24108a
7
+ data.tar.gz: 273ababe94efae433b8577e872cc44f0a69e85b482b9deda86dc83b39f0440d973e2755ca2bc85b7e36ab90d2313b77e0ed0dc94e932a4b681a26eeaf592a908
@@ -0,0 +1,59 @@
1
+ name: BUILD
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ ruby-version: [2.7, '3.0', 3.1]
14
+
15
+ services:
16
+ postgres:
17
+ image: postgres
18
+ ports:
19
+ - 5432:5432
20
+ env:
21
+ POSTGRES_PASSWORD: postgres
22
+ options: >-
23
+ --health-cmd pg_isready
24
+ --health-interval 10s
25
+ --health-timeout 5s
26
+ --health-retries 5
27
+
28
+ steps:
29
+ - name: Install libraries
30
+ run: |
31
+ sudo apt-get install -y libpq-dev postgresql-client
32
+
33
+ - name: Configure database
34
+ env:
35
+ PGPASSWORD: postgres
36
+ PGUSER: postgres
37
+ PGHOST: localhost
38
+ run: |
39
+ echo "Configuring PostgresSQL"
40
+ psql -c 'create database "array_enum_test";'
41
+
42
+ - name: Checkout code
43
+ uses: actions/checkout@v2
44
+
45
+ - name : Ruby Setup
46
+ uses: ruby/setup-ruby@v1
47
+ with:
48
+ ruby-version: ${{ matrix.ruby-version }}
49
+ bundler-cache: true
50
+
51
+ - name: Install dependencies
52
+ run: bundle install
53
+
54
+ - name: Run test
55
+ env:
56
+ PGPASSWORD: postgres
57
+ PGUSER: postgres
58
+ PGHOST: localhost
59
+ run: bundle exec rake -s test
@@ -0,0 +1,56 @@
1
+ name: CI
2
+
3
+ on: [pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ matrix:
10
+ ruby-version: [2.7, '3.0', 3.1]
11
+
12
+ services:
13
+ postgres:
14
+ image: postgres
15
+ ports:
16
+ - 5432:5432
17
+ env:
18
+ POSTGRES_PASSWORD: postgres
19
+ options: >-
20
+ --health-cmd pg_isready
21
+ --health-interval 10s
22
+ --health-timeout 5s
23
+ --health-retries 5
24
+
25
+ steps:
26
+ - name: Install libraries
27
+ run: |
28
+ sudo apt-get install -y libpq-dev postgresql-client
29
+
30
+ - name: Configure database
31
+ env:
32
+ PGPASSWORD: postgres
33
+ PGUSER: postgres
34
+ PGHOST: localhost
35
+ run: |
36
+ echo "Configuring PostgresSQL"
37
+ psql -c 'create database "array_enum_test";'
38
+
39
+ - name: Checkout code
40
+ uses: actions/checkout@v2
41
+
42
+ - name : Ruby Setup
43
+ uses: ruby/setup-ruby@v1
44
+ with:
45
+ ruby-version: ${{ matrix.ruby-version }}
46
+ bundler-cache: true
47
+
48
+ - name: Install dependencies
49
+ run: bundle install
50
+
51
+ - name: Run test
52
+ env:
53
+ PGPASSWORD: postgres
54
+ PGUSER: postgres
55
+ PGHOST: localhost
56
+ run: bundle exec rake -s test
data/Gemfile.lock CHANGED
@@ -1,33 +1,32 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- array_enum (1.0.1)
4
+ array_enum (1.4.0)
5
5
  activemodel
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activemodel (5.2.2)
11
- activesupport (= 5.2.2)
12
- activerecord (5.2.2)
13
- activemodel (= 5.2.2)
14
- activesupport (= 5.2.2)
15
- arel (>= 9.0)
16
- activesupport (5.2.2)
10
+ activemodel (6.1.3)
11
+ activesupport (= 6.1.3)
12
+ activerecord (6.1.3)
13
+ activemodel (= 6.1.3)
14
+ activesupport (= 6.1.3)
15
+ activesupport (6.1.3)
17
16
  concurrent-ruby (~> 1.0, >= 1.0.2)
18
- i18n (>= 0.7, < 2)
19
- minitest (~> 5.1)
20
- tzinfo (~> 1.1)
21
- arel (9.0.0)
22
- concurrent-ruby (1.1.4)
23
- i18n (1.5.1)
17
+ i18n (>= 1.6, < 2)
18
+ minitest (>= 5.1)
19
+ tzinfo (~> 2.0)
20
+ zeitwerk (~> 2.3)
21
+ concurrent-ruby (1.1.8)
22
+ i18n (1.8.9)
24
23
  concurrent-ruby (~> 1.0)
25
24
  minitest (5.11.3)
26
25
  pg (1.1.4)
27
- rake (12.3.2)
28
- thread_safe (0.3.6)
29
- tzinfo (1.2.5)
30
- thread_safe (~> 0.1)
26
+ rake (12.3.3)
27
+ tzinfo (2.0.4)
28
+ concurrent-ruby (~> 1.0)
29
+ zeitwerk (2.4.2)
31
30
 
32
31
  PLATFORMS
33
32
  ruby
@@ -41,4 +40,4 @@ DEPENDENCIES
41
40
  rake (>= 10.0)
42
41
 
43
42
  BUNDLED WITH
44
- 1.17.3
43
+ 2.2.3
data/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ [![Gem Version](https://badge.fury.io/rb/array_enum.svg)](https://badge.fury.io/rb/array_enum)
2
+ [![BUILD](https://github.com/freeletics/array_enum/actions/workflows/ci-on-merge.yml/badge.svg)](https://github.com/freeletics/array_enum/actions/workflows/ci-on-merge.yml)
3
+
4
+
1
5
  # ArrayEnum
2
6
 
3
7
  Extension for `ActiveRecord` that adds support for `PostgreSQL` array columns, mapping string values to integers.
@@ -11,7 +15,6 @@ Extension for `ActiveRecord` that adds support for `PostgreSQL` array columns, m
11
15
  ### ActiveRecord extension
12
16
 
13
17
  Database will store integers that after reading will map to string values.
14
- Additionally scope is generated with `with_` prefix that will query database for any matching passed value.
15
18
 
16
19
  ```ruby
17
20
  ActiveRecord::Schema.define do
@@ -23,12 +26,43 @@ end
23
26
  class User < ActiveRecord::Base
24
27
  extend ArrayEnum
25
28
 
26
- array_enum favourite_colors: {"red" => 1, "blue" => 2}
29
+ array_enum favourite_colors: {"red" => 1, "blue" => 2, "green" => 3}
27
30
  end
28
31
 
29
32
  user = User.create!(favourite_colors: ["red", "green"])
30
33
  user.favourite_colors # => ["red", "green"]
31
- User.with_favourite_colors("red") # => [user]
34
+ User.favourite_colors # => {"red" => 1, "blue" => 2, "green" => 3}
35
+ ```
36
+
37
+ Several scopes are made available on your model to find records based on a value or an array of values:
38
+
39
+ ```ruby
40
+ user1 = User.create!(favourite_colors: ["red", "green"])
41
+ user2 = User.create!(favourite_colors: ["red"])
42
+
43
+ # Find a record that has _all_ the provided values in the array enum attribute
44
+ User.with_favourite_colors("red") # => [user1, user2]
45
+ User.with_favourite_colors(%w[red green]) # => [user1]
46
+ User.with_favourite_colors(%w[red blue]) # => []
47
+ User.with_favourite_colors(%w[green blue]) # => []
48
+
49
+ # Find a record that has the provided values, and _only those values_, in the array enum attribute
50
+ User.only_with_favourite_colors("red") # => [user2]
51
+ User.only_with_favourite_colors(%w[red green]) # => [user1]
52
+ User.only_with_favourite_colors(%w[red blue]) # => []
53
+ User.only_with_favourite_colors(%w[green blue]) # => []
54
+
55
+ # Find a record that has _at least one_ of the provided values in the array enum attribute
56
+ User.with_any_of_favourite_colors("red") # => [user1, user2]
57
+ User.with_any_of_favourite_colors(%w[red green]) # => [user1, user2]
58
+ User.with_any_of_favourite_colors(%w[red blue]) # => [user1, user2]
59
+ User.with_any_of_favourite_colors(%w[green blue]) # => [user1]
60
+ ```
61
+
62
+ Attempting to find a record with a value that is not in the enum will fail:
63
+
64
+ ```ruby
65
+ User.with_favourite_colors("yellow") # => ArgumentError["yellow is not a valid value for favourite_colors"]
32
66
  ```
33
67
 
34
68
  ### Subset Validator
@@ -42,6 +76,8 @@ class CreateUser
42
76
  attr_accessor :favourite_colors
43
77
 
44
78
  validates :favourite_colors, subset: ["green", "blue"]
79
+ # or:
80
+ # validates :favourite_colors, subset: { in: ->(record) { Color.pluck(:name) } }
45
81
  end
46
82
 
47
83
  CreateUser.new(favourite_colors: ["black"]).valid? # => false
@@ -49,8 +85,6 @@ CreateUser.new(favourite_colors: ["black"]).valid? # => false
49
85
 
50
86
  ## Development
51
87
 
52
- [![Build Status](https://travis-ci.com/freeletics/array_enum.svg?branch=master)](https://travis-ci.com/freeletics/array_enum)
53
-
54
88
  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.
55
89
 
56
90
  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).
@@ -3,10 +3,12 @@ require "active_model/validator"
3
3
  class ArrayEnum::SubsetValidator < ActiveModel::EachValidator
4
4
  def validate_each(record, attribute, value)
5
5
  wrapped_value = [value].flatten # Handles nil value
6
- diff = wrapped_value.reject { |element| delimiter.include?(element) }
6
+ subset = delimiter.respond_to?(:call) ? delimiter.call(record) : delimiter
7
+
8
+ diff = wrapped_value.reject { |element| subset.include?(element) }
7
9
 
8
10
  unless diff.empty?
9
- record.errors.add(attribute, :inclusion, options.except(:in, :within).merge!(value: diff))
11
+ record.errors.add(attribute, :inclusion, **options.except(:in, :within).merge!(value: diff))
10
12
  end
11
13
  end
12
14
 
@@ -1,3 +1,3 @@
1
1
  module ArrayEnum
2
- VERSION = "1.0.1"
2
+ VERSION = "1.4.0"
3
3
  end
data/lib/array_enum.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require "array_enum/version"
2
2
  require "array_enum/subset_validator"
3
- require "array_enum/railtie" if defined?(Rails)
3
+ require "array_enum/railtie" if defined?(Rails::Railtie)
4
+ require "active_support/hash_with_indifferent_access"
5
+ require "active_support/core_ext/string/inflections"
4
6
 
5
7
  module ArrayEnum
6
8
  MISSING_VALUE_MESSAGE = "%{value} is not a valid value for %{attr}".freeze
@@ -9,21 +11,32 @@ module ArrayEnum
9
11
  def array_enum(definitions)
10
12
  definitions.each do |attr_name, mapping|
11
13
  attr_symbol = attr_name.to_sym
14
+ mapping_hash = ActiveSupport::HashWithIndifferentAccess.new(mapping)
12
15
 
13
- define_singleton_method("with_#{attr_name}".to_sym) do |values|
14
- db_values = Array(values).map do |value|
15
- mapping[value.to_s] || raise(ArgumentError, MISSING_VALUE_MESSAGE % {value: value, attr: attr_name})
16
+ define_singleton_method(attr_name.to_s.pluralize) do
17
+ mapping_hash
18
+ end
19
+
20
+ {
21
+ "with_#{attr_name}" => '@>',
22
+ "only_with_#{attr_name}" => '=',
23
+ "with_any_of_#{attr_name}" => '&&'
24
+ }.each do |method_name, comparison_operator|
25
+ define_singleton_method(method_name.to_sym) do |values|
26
+ db_values = Array(values).map do |value|
27
+ mapping_hash[value] || raise(ArgumentError, MISSING_VALUE_MESSAGE % {value: value, attr: attr_name})
28
+ end
29
+ where("#{attr_name} #{comparison_operator} ARRAY[:db_values]", db_values: db_values)
16
30
  end
17
- where("#{attr_name} @> ARRAY[:db_values]", db_values: db_values)
18
31
  end
19
32
 
20
33
  define_method(attr_symbol) do
21
- Array(self[attr_symbol]).map { |value| mapping.key(value) }
34
+ Array(self[attr_symbol]).map { |value| mapping_hash.key(value) }
22
35
  end
23
36
 
24
37
  define_method("#{attr_name}=".to_sym) do |values|
25
38
  self[attr_symbol] = Array(values).map do |value|
26
- mapping[value.to_s] || raise(ArgumentError, MISSING_VALUE_MESSAGE % {value: value, attr: attr_name})
39
+ mapping_hash[value] || raise(ArgumentError, MISSING_VALUE_MESSAGE % {value: value, attr: attr_name})
27
40
  end.uniq
28
41
  end
29
42
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: array_enum
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wojciech Wnętrzak
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-10 00:00:00.000000000 Z
11
+ date: 2022-01-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -103,8 +103,9 @@ executables: []
103
103
  extensions: []
104
104
  extra_rdoc_files: []
105
105
  files:
106
+ - ".github/workflows/ci-on-merge.yml"
107
+ - ".github/workflows/ci.yml"
106
108
  - ".gitignore"
107
- - ".travis.yml"
108
109
  - Gemfile
109
110
  - Gemfile.lock
110
111
  - LICENSE.txt
@@ -123,7 +124,7 @@ licenses:
123
124
  metadata:
124
125
  homepage_uri: https://github.com/freeletics/array_enum
125
126
  source_code_uri: https://github.com/freeletics/array_enum
126
- post_install_message:
127
+ post_install_message:
127
128
  rdoc_options: []
128
129
  require_paths:
129
130
  - lib
@@ -138,8 +139,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
139
  - !ruby/object:Gem::Version
139
140
  version: '0'
140
141
  requirements: []
141
- rubygems_version: 3.0.2
142
- signing_key:
142
+ rubygems_version: 3.2.3
143
+ signing_key:
143
144
  specification_version: 4
144
145
  summary: String to integer mapping for PostgreSQL array columns.
145
146
  test_files: []
data/.travis.yml DELETED
@@ -1,16 +0,0 @@
1
- dist: xenial
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.6.0
6
-
7
- addons:
8
- postgresql: "10"
9
-
10
- before_script:
11
- - psql -c 'create database "array_enum_test";' -U postgres
12
-
13
- script: "bundle exec rake"
14
-
15
- notifications:
16
- disabled: true