u-attributes 2.8.0 → 3.0.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 +4 -4
- data/.github/workflows/ci.yml +56 -17
- data/.gitignore +8 -0
- data/Appraisals +84 -0
- data/Gemfile +11 -34
- data/README.md +326 -36
- data/Rakefile +30 -1
- data/bin/matrix +16 -0
- data/bin/setup +4 -0
- data/gemfiles/rails_8_1.gemfile +15 -0
- data/gemfiles/rails_edge.gemfile +15 -0
- data/lib/micro/attributes/version.rb +1 -1
- data/u-attributes.gemspec +2 -1
- metadata +22 -9
- data/bin/prepare_coverage +0 -27
- data/bin/test +0 -48
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '01848f333334d9af69fbd608407e9e287ba9411305c2307fba64bb5bd85d076c'
|
|
4
|
+
data.tar.gz: f1778463cfdeeb64595a2a803fe93b720f587b65c62a95abf4693d7a10227330
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1bb8672adcf5c2221ead65d0fbcb1523a74d960c20056c8e989404d63a6941ed5bb0a51a3e4acae4dc635ad24ff5e446ba349cc65b5e6b38a9093f51ea93b50c
|
|
7
|
+
data.tar.gz: 135eb428c82e85a8a5a197c3f9e1170df2c9dcd33aa6e89162a292c79055299bf5db614497dbc51fb926ba16dec2028a5791e5d3faf9103f46746d9c059db0ae
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -1,27 +1,66 @@
|
|
|
1
|
+
name: Ruby
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
pull_request:
|
|
1
9
|
|
|
2
|
-
name: build
|
|
3
|
-
on: [push]
|
|
4
10
|
jobs:
|
|
5
11
|
test:
|
|
6
12
|
runs-on: ubuntu-latest
|
|
13
|
+
name: Ruby ${{ matrix.ruby }}
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
7
16
|
strategy:
|
|
17
|
+
fail-fast: false
|
|
8
18
|
matrix:
|
|
9
|
-
ruby: [2.
|
|
19
|
+
ruby: ["2.7", "3.0", "3.1", "3.2", "3.3", "3.4", "4.0", head]
|
|
10
20
|
steps:
|
|
11
|
-
- uses: actions/checkout@
|
|
12
|
-
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
with:
|
|
23
|
+
persist-credentials: false
|
|
24
|
+
- name: Set up Ruby
|
|
25
|
+
uses: ruby/setup-ruby@v1
|
|
13
26
|
with:
|
|
14
27
|
ruby-version: ${{ matrix.ruby }}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
- name:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
- name: Install bundler
|
|
29
|
+
run: gem install bundler -v 2.4.22
|
|
30
|
+
if: ${{ matrix.ruby == '2.7' || matrix.ruby == '3.0' }}
|
|
31
|
+
- name: Bundle install
|
|
32
|
+
run: bundle install
|
|
33
|
+
- name: Setup project
|
|
34
|
+
run: bundle exec appraisal install
|
|
35
|
+
- name: Run baseline tests (no activemodel)
|
|
36
|
+
run: bundle exec rake test
|
|
37
|
+
- name: Run tests for Rails 6.0
|
|
38
|
+
run: bundle exec appraisal rails-6-0 rake test
|
|
39
|
+
if: ${{ matrix.ruby == '2.7' || matrix.ruby == '3.0' }}
|
|
40
|
+
- name: Run tests for Rails 6.1
|
|
41
|
+
run: bundle exec appraisal rails-6-1 rake test
|
|
42
|
+
if: ${{ matrix.ruby == '2.7' || matrix.ruby == '3.0' }}
|
|
43
|
+
- name: Run tests for Rails 7.0
|
|
44
|
+
run: bundle exec appraisal rails-7-0 rake test
|
|
45
|
+
if: ${{ matrix.ruby == '2.7' || matrix.ruby == '3.0' || matrix.ruby == '3.1' || matrix.ruby == '3.2' || matrix.ruby == '3.3' }}
|
|
46
|
+
- name: Run tests for Rails 7.1
|
|
47
|
+
run: bundle exec appraisal rails-7-1 rake test
|
|
48
|
+
if: ${{ matrix.ruby == '2.7' || matrix.ruby == '3.0' || matrix.ruby == '3.1' || matrix.ruby == '3.2' || matrix.ruby == '3.3' }}
|
|
49
|
+
- name: Run tests for Rails 7.2
|
|
50
|
+
run: bundle exec appraisal rails-7-2 rake test
|
|
51
|
+
if: ${{ matrix.ruby == '3.1' || matrix.ruby == '3.2' || matrix.ruby == '3.3' || matrix.ruby == '3.4' }}
|
|
52
|
+
- name: Run tests for Rails 8.0
|
|
53
|
+
run: bundle exec appraisal rails-8-0 rake test
|
|
54
|
+
if: ${{ matrix.ruby == '3.2' || matrix.ruby == '3.3' || matrix.ruby == '3.4' }}
|
|
55
|
+
- name: Run tests for Rails 8.1
|
|
56
|
+
run: bundle exec appraisal rails-8-1 rake test
|
|
57
|
+
if: ${{ matrix.ruby == '3.3' || matrix.ruby == '3.4' || matrix.ruby == '4.0' }}
|
|
58
|
+
- name: Run tests for Rails edge
|
|
59
|
+
run: bundle exec appraisal rails-edge rake test
|
|
60
|
+
if: ${{ matrix.ruby == '4.0' || matrix.ruby == 'head' }}
|
|
61
|
+
- name: Upload coverage to Qlty
|
|
62
|
+
uses: qltysh/qlty-action/coverage@v2
|
|
63
|
+
if: ${{ matrix.ruby == '3.4' && !github.base_ref }}
|
|
25
64
|
with:
|
|
26
|
-
|
|
27
|
-
|
|
65
|
+
token: ${{ secrets.QLTY_COVERAGE_TOKEN }}
|
|
66
|
+
files: coverage/.resultset.json
|
data/.gitignore
CHANGED
data/Appraisals
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
if RUBY_VERSION < "3.1"
|
|
2
|
+
appraise "rails-6-0" do
|
|
3
|
+
group :test do
|
|
4
|
+
gem "logger", "~> 1.6", ">= 1.6.6"
|
|
5
|
+
gem "stringio", "~> 3.2"
|
|
6
|
+
|
|
7
|
+
gem "minitest", "5.26.1"
|
|
8
|
+
gem "activemodel", "~> 6.0.0"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
appraise "rails-6-1" do
|
|
13
|
+
group :test do
|
|
14
|
+
gem "logger", "~> 1.6", ">= 1.6.6"
|
|
15
|
+
gem "stringio", "~> 3.2"
|
|
16
|
+
|
|
17
|
+
gem "minitest", "5.26.1"
|
|
18
|
+
gem "activemodel", "~> 6.1.0"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
if RUBY_VERSION >= "2.7" && RUBY_VERSION < "3.4"
|
|
24
|
+
appraise "rails-7-0" do
|
|
25
|
+
group :test do
|
|
26
|
+
gem "logger", "~> 1.6", ">= 1.6.6"
|
|
27
|
+
gem "stringio", "~> 3.2"
|
|
28
|
+
gem "securerandom", "~> 0.3.2"
|
|
29
|
+
|
|
30
|
+
gem "minitest", "5.26.1"
|
|
31
|
+
gem "activemodel", "~> 7.0.0"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
appraise "rails-7-1" do
|
|
36
|
+
group :test do
|
|
37
|
+
gem "logger", "~> 1.6", ">= 1.6.6"
|
|
38
|
+
gem "stringio", "~> 3.2"
|
|
39
|
+
gem "securerandom", "~> 0.3.2"
|
|
40
|
+
|
|
41
|
+
gem "minitest", "5.26.1"
|
|
42
|
+
gem "activemodel", "~> 7.1.0"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
if RUBY_VERSION >= "3.1" && RUBY_VERSION < "4.0"
|
|
48
|
+
appraise "rails-7-2" do
|
|
49
|
+
group :test do
|
|
50
|
+
gem "minitest", "~> 5.27"
|
|
51
|
+
gem "activemodel", "~> 7.2.0"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
if RUBY_VERSION >= "3.2" && RUBY_VERSION < "4.0"
|
|
57
|
+
appraise "rails-8-0" do
|
|
58
|
+
group :test do
|
|
59
|
+
gem "ostruct", "~> 0.6.3"
|
|
60
|
+
gem "minitest", "~> 5.27"
|
|
61
|
+
gem "activemodel", "~> 8.0.0"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
if RUBY_VERSION >= "3.3.0"
|
|
67
|
+
minitest_version = (RUBY_VERSION >= "4.0.0") ? "~> 6.0" : "~> 5.27"
|
|
68
|
+
|
|
69
|
+
appraise "rails-8-1" do
|
|
70
|
+
group :test do
|
|
71
|
+
gem "ostruct", "~> 0.6.3"
|
|
72
|
+
gem "minitest", minitest_version
|
|
73
|
+
gem "activemodel", "~> 8.1.0"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
appraise "rails-edge" do
|
|
78
|
+
group :test do
|
|
79
|
+
gem "ostruct", "~> 0.6.3"
|
|
80
|
+
gem "minitest", minitest_version
|
|
81
|
+
gem "activemodel", github: "rails/rails", branch: "main"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
data/Gemfile
CHANGED
|
@@ -1,41 +1,18 @@
|
|
|
1
|
-
source
|
|
1
|
+
source "https://rubygems.org"
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
# Specify your gem's dependencies in u-attributes.gemspec
|
|
6
|
+
gemspec
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
when '3.2' then '3.2.22'
|
|
9
|
-
when '4.0' then '4.0.13'
|
|
10
|
-
when '4.1' then '4.1.16'
|
|
11
|
-
when '4.2' then '4.2.11'
|
|
12
|
-
when '5.0' then '5.0.7'
|
|
13
|
-
when '5.1' then '5.1.7'
|
|
14
|
-
when '5.2' then '5.2.4'
|
|
15
|
-
when '6.0' then '6.0.3.4'
|
|
16
|
-
when '6.1' then '6.1.2'
|
|
17
|
-
end
|
|
8
|
+
gem "rake", "~> 13.0"
|
|
18
9
|
|
|
19
|
-
|
|
20
|
-
case RUBY_VERSION
|
|
21
|
-
when /\A2.[23]/ then '0.17.1'
|
|
22
|
-
when /\A2.4/ then '~> 0.18.5'
|
|
23
|
-
else '~> 0.21.2'
|
|
24
|
-
end
|
|
10
|
+
gem "u-case", "~> 4.5", ">= 4.5.1"
|
|
25
11
|
|
|
26
12
|
group :test do
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
gem 'minitest', '~> 5.0'
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
gem 'simplecov', simplecov_version, require: false
|
|
13
|
+
gem "logger"
|
|
14
|
+
gem "stringio"
|
|
15
|
+
gem "minitest", "~> 5.0"
|
|
16
|
+
gem "ostruct", "~> 0.6.3" if RUBY_VERSION >= "3.5"
|
|
17
|
+
gem "simplecov", "~> 0.22.0", require: false
|
|
36
18
|
end
|
|
37
|
-
|
|
38
|
-
gem 'rake', '~> 13.0'
|
|
39
|
-
|
|
40
|
-
# Specify your gem's dependencies in u-attributes.gemspec
|
|
41
|
-
gemspec
|
data/README.md
CHANGED
|
@@ -1,28 +1,16 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="./assets/u-attributes_logo_v1.png" alt=
|
|
3
|
-
|
|
2
|
+
<h1 align="center" id="-attributes"><img src="./assets/u-attributes_logo_v1.png" alt="μ-attributes" height="60"></h1>
|
|
4
3
|
<p align="center"><i>Create "immutable" objects with no setters, just getters.</i></p>
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<img
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
<a href="https://github.com/serradura/u-attributes/actions/workflows/ci.yml">
|
|
16
|
-
<img alt="Build Status" src="https://github.com/serradura/u-attributes/actions/workflows/ci.yml/badge.svg">
|
|
17
|
-
</a>
|
|
18
|
-
|
|
19
|
-
<a href="https://codeclimate.com/github/serradura/u-attributes/maintainability">
|
|
20
|
-
<img alt="Maintainability" src="https://api.codeclimate.com/v1/badges/b562e6b877a9edf4dbf6/maintainability">
|
|
21
|
-
</a>
|
|
22
|
-
|
|
23
|
-
<a href="https://codeclimate.com/github/serradura/u-attributes/test_coverage">
|
|
24
|
-
<img alt="Test Coverage" src="https://api.codeclimate.com/v1/badges/b562e6b877a9edf4dbf6/test_coverage">
|
|
25
|
-
</a>
|
|
4
|
+
<p align="center">
|
|
5
|
+
<a href="https://badge.fury.io/rb/u-attributes"><img src="https://badge.fury.io/rb/u-attributes.svg" alt="Gem Version" height="18"></a>
|
|
6
|
+
<a href="https://github.com/serradura/u-attributes/actions/workflows/ci.yml"><img alt="Build Status" src="https://github.com/serradura/u-attributes/actions/workflows/ci.yml/badge.svg"></a>
|
|
7
|
+
<br/>
|
|
8
|
+
<a href="https://qlty.sh/gh/serradura/projects/u-attributes"><img src="https://qlty.sh/gh/serradura/projects/u-attributes/maintainability.svg" alt="Maintainability" /></a>
|
|
9
|
+
<a href="https://qlty.sh/gh/serradura/projects/u-attributes"><img src="https://qlty.sh/gh/serradura/projects/u-attributes/coverage.svg" alt="Code Coverage" /></a>
|
|
10
|
+
<br/>
|
|
11
|
+
<img src="https://img.shields.io/badge/Ruby%20%3E%3D%202.7%2C%20%3C%3D%20Head-ruby.svg?colorA=444&colorB=333" alt="Ruby">
|
|
12
|
+
<img src="https://img.shields.io/badge/Rails%20%3E%3D%206.0%2C%20%3C%3D%20Edge-rails.svg?colorA=444&colorB=333" alt="Rails">
|
|
13
|
+
</p>
|
|
26
14
|
</p>
|
|
27
15
|
|
|
28
16
|
This gem allows you to define "immutable" objects, when using it your objects will only have getters and no setters.
|
|
@@ -32,9 +20,9 @@ So, if you change [[1](#with_attribute)] [[2](#with_attributes)] an attribute of
|
|
|
32
20
|
|
|
33
21
|
Version | Documentation
|
|
34
22
|
---------- | -------------
|
|
35
|
-
unreleased | https://github.com/serradura/u-
|
|
36
|
-
|
|
37
|
-
|
|
23
|
+
unreleased | https://github.com/serradura/u-attributes/blob/main/README.md
|
|
24
|
+
3.0.0 | https://github.com/serradura/u-attributes/blob/v3.x/README.md
|
|
25
|
+
2.8.0 | https://github.com/serradura/u-attributes/blob/v2.x/README.md
|
|
38
26
|
|
|
39
27
|
# Table of contents <!-- omit in toc -->
|
|
40
28
|
- [Installation](#installation)
|
|
@@ -46,6 +34,8 @@ unreleased | https://github.com/serradura/u-case/blob/main/README.md
|
|
|
46
34
|
- [Is it possible to define an attribute as required?](#is-it-possible-to-define-an-attribute-as-required)
|
|
47
35
|
- [`Micro::Attributes#attribute`](#microattributesattribute)
|
|
48
36
|
- [`Micro::Attributes#attribute!`](#microattributesattribute-1)
|
|
37
|
+
- [Attribute visibility (`private:`, `protected:`)](#attribute-visibility-private-protected)
|
|
38
|
+
- [Freezing attribute values (`freeze:`)](#freezing-attribute-values-freeze)
|
|
49
39
|
- [How to define multiple attributes?](#how-to-define-multiple-attributes)
|
|
50
40
|
- [`Micro::Attributes.with(:initialize)`](#microattributeswithinitialize)
|
|
51
41
|
- [`#with_attribute()`](#with_attribute)
|
|
@@ -70,6 +60,7 @@ unreleased | https://github.com/serradura/u-case/blob/main/README.md
|
|
|
70
60
|
- [`Micro::Attributes.without`](#microattributeswithout)
|
|
71
61
|
- [Picking all the features](#picking-all-the-features)
|
|
72
62
|
- [Extensions](#extensions)
|
|
63
|
+
- [Accept extension](#accept-extension)
|
|
73
64
|
- [`ActiveModel::Validation` extension](#activemodelvalidation-extension)
|
|
74
65
|
- [`.attribute()` options](#attribute-options)
|
|
75
66
|
- [Diff extension](#diff-extension)
|
|
@@ -86,16 +77,29 @@ unreleased | https://github.com/serradura/u-case/blob/main/README.md
|
|
|
86
77
|
Add this line to your application's Gemfile and `bundle install`:
|
|
87
78
|
|
|
88
79
|
```ruby
|
|
89
|
-
gem 'u-attributes'
|
|
80
|
+
gem 'u-attributes', '~> 3.0'
|
|
90
81
|
```
|
|
91
82
|
|
|
92
83
|
# Compatibility
|
|
93
84
|
|
|
94
|
-
| u-attributes
|
|
95
|
-
|
|
|
96
|
-
| unreleased
|
|
97
|
-
|
|
|
98
|
-
|
|
|
85
|
+
| u-attributes | branch | ruby | activemodel |
|
|
86
|
+
| ---------------- | ------ | -------- | -------------- |
|
|
87
|
+
| unreleased | main | >= 2.7 | >= 6.0 |
|
|
88
|
+
| 3.0.0 | v3.x | >= 2.7 | >= 6.0 |
|
|
89
|
+
| 2.8.0 | v2.x | >= 2.2.0 | >= 3.2, <= 8.1 |
|
|
90
|
+
|
|
91
|
+
This library is tested (CI matrix) against:
|
|
92
|
+
|
|
93
|
+
| Ruby / Rails | 6.0 | 6.1 | 7.0 | 7.1 | 7.2 | 8.0 | 8.1 | Edge |
|
|
94
|
+
|--------------|-----|-----|-----|-----|-----|-----|-----|------|
|
|
95
|
+
| 2.7 | ✅ | ✅ | ✅ | ✅ | | | | |
|
|
96
|
+
| 3.0 | ✅ | ✅ | ✅ | ✅ | | | | |
|
|
97
|
+
| 3.1 | | | ✅ | ✅ | ✅ | | | |
|
|
98
|
+
| 3.2 | | | ✅ | ✅ | ✅ | ✅ | | |
|
|
99
|
+
| 3.3 | | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
100
|
+
| 3.4 | | | | | ✅ | ✅ | ✅ | ✅ |
|
|
101
|
+
| 4.x | | | | | | | ✅ | ✅ |
|
|
102
|
+
| Head | | | | | | | ✅ | ✅ |
|
|
99
103
|
|
|
100
104
|
> **Note**: The activemodel is an optional dependency, this module [can be enabled](#activemodelvalidation-extension) to validate the attributes.
|
|
101
105
|
|
|
@@ -157,8 +161,10 @@ person.name # John Doe
|
|
|
157
161
|
|
|
158
162
|
#### How to extract attributes from an object or hash?
|
|
159
163
|
|
|
160
|
-
You can extract attributes using the `extract_attributes_from` method
|
|
161
|
-
|
|
164
|
+
You can extract attributes using the `extract_attributes_from` method. For each attribute name it
|
|
165
|
+
will first call the reader method (`object.attribute_key`) when available, and fall back to the
|
|
166
|
+
hash accessor (`object[attribute_key]`) otherwise. The reader method has priority because it lets
|
|
167
|
+
the source object encapsulate any computed/derived value.
|
|
162
168
|
|
|
163
169
|
```ruby
|
|
164
170
|
class Person
|
|
@@ -251,6 +257,106 @@ person.attribute!('foo') { |value| value } # NameError (undefined attribute `foo
|
|
|
251
257
|
|
|
252
258
|
[⬆️ Back to Top](#table-of-contents-)
|
|
253
259
|
|
|
260
|
+
### Attribute visibility (`private:`, `protected:`)
|
|
261
|
+
|
|
262
|
+
By default every attribute reader is `public`. Use the `private: true` or `protected: true`
|
|
263
|
+
options to restrict the reader's visibility — useful for things like passwords, tokens, and any
|
|
264
|
+
internal value you don't want to expose on the public API.
|
|
265
|
+
|
|
266
|
+
Private/protected attributes are also excluded from the public attribute set (`#attributes`,
|
|
267
|
+
`.attributes`, `#attribute?`), so they don't leak through serialization or enumeration. To check
|
|
268
|
+
or fetch them explicitly, pass `true` as the second argument to `#attribute?` (or use
|
|
269
|
+
`#attribute!`).
|
|
270
|
+
|
|
271
|
+
```ruby
|
|
272
|
+
require 'digest'
|
|
273
|
+
|
|
274
|
+
class User::SignUpParams
|
|
275
|
+
include Micro::Attributes.with(:initialize)
|
|
276
|
+
|
|
277
|
+
TrimString = ->(value) { String(value).strip }
|
|
278
|
+
|
|
279
|
+
attribute :email, default: TrimString
|
|
280
|
+
attributes :password, :password_confirmation, default: TrimString, private: true
|
|
281
|
+
|
|
282
|
+
def password_digest
|
|
283
|
+
return unless password == password_confirmation
|
|
284
|
+
|
|
285
|
+
Digest::SHA256.hexdigest(password)
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
User::SignUpParams.attributes # ["email", "password", "password_confirmation"]
|
|
290
|
+
User::SignUpParams.attributes_by_visibility # { public: ["email"], private: ["password", "password_confirmation"], protected: [] }
|
|
291
|
+
|
|
292
|
+
user = User::SignUpParams.new(
|
|
293
|
+
email: 'email@example.com',
|
|
294
|
+
password: 'secret',
|
|
295
|
+
password_confirmation: 'secret'
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
user.attributes # { "email" => "email@example.com" }
|
|
299
|
+
|
|
300
|
+
user.attribute?('email') # true
|
|
301
|
+
user.attribute?('password') # false (not in the public set)
|
|
302
|
+
user.attribute?('password', true) # true (use the second arg to look at all attributes)
|
|
303
|
+
|
|
304
|
+
user.attribute('password') # nil (returns nil instead of leaking the value)
|
|
305
|
+
user.attribute!('password') # NameError ("tried to access a private attribute `password")
|
|
306
|
+
|
|
307
|
+
user.password # NoMethodError (private method `password' called for ...)
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
- `private:` and `protected:` map directly to Ruby's method-visibility semantics on the reader.
|
|
311
|
+
- The visibility configuration is preserved on inheritance.
|
|
312
|
+
- Works with the `:keys_as_symbol` extension (`attributes_by_visibility` will return the keys in
|
|
313
|
+
the configured type).
|
|
314
|
+
|
|
315
|
+
The class-level `attributes_by_visibility` method returns a hash with `:public`, `:private`, and
|
|
316
|
+
`:protected` keys so you can introspect how each attribute was declared.
|
|
317
|
+
|
|
318
|
+
[⬆️ Back to Top](#table-of-contents-)
|
|
319
|
+
|
|
320
|
+
### Freezing attribute values (`freeze:`)
|
|
321
|
+
|
|
322
|
+
Use the `freeze:` option to make sure the value stored in the attribute can't be mutated after
|
|
323
|
+
the object is built. Three modes are supported:
|
|
324
|
+
|
|
325
|
+
| Value | Behavior |
|
|
326
|
+
| -------------- | --------------------------------------------------------------------- |
|
|
327
|
+
| `true` | Calls `value.freeze` on the incoming value. The original is frozen. |
|
|
328
|
+
| `:after_dup` | `value.dup.freeze` — freezes a shallow copy; the original stays free. |
|
|
329
|
+
| `:after_clone` | `value.clone.freeze` — same as above but uses `#clone` (preserves singleton methods, frozen state, tainted state, etc.). |
|
|
330
|
+
|
|
331
|
+
```ruby
|
|
332
|
+
class Person
|
|
333
|
+
include Micro::Attributes.with(:initialize)
|
|
334
|
+
|
|
335
|
+
attribute :name, freeze: true
|
|
336
|
+
attribute :address, freeze: :after_dup
|
|
337
|
+
attribute :payload, freeze: :after_clone
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
raw_name = +"Rodrigo"
|
|
341
|
+
|
|
342
|
+
person = Person.new(
|
|
343
|
+
name: raw_name,
|
|
344
|
+
address: 'Av. Paulista',
|
|
345
|
+
payload: { id: 1 }
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
person.name.frozen? # true
|
|
349
|
+
raw_name.frozen? # true -> freeze: true mutates the original
|
|
350
|
+
|
|
351
|
+
person.address.frozen? # true
|
|
352
|
+
'Av. Paulista'.frozen? # depends on the source string; the duplicate is what's frozen
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
`freeze:` is applied after the default value resolution, so the frozen value reflects whatever
|
|
356
|
+
the attribute ends up holding (raw value, default, or callable-default result).
|
|
357
|
+
|
|
358
|
+
[⬆️ Back to Top](#table-of-contents-)
|
|
359
|
+
|
|
254
360
|
## How to define multiple attributes?
|
|
255
361
|
|
|
256
362
|
Use `.attributes` with a list of attribute names.
|
|
@@ -272,7 +378,24 @@ person.name # nil
|
|
|
272
378
|
person.age # 32
|
|
273
379
|
```
|
|
274
380
|
|
|
275
|
-
|
|
381
|
+
You can also pass a trailing options hash and every attribute in the list will be declared with
|
|
382
|
+
those options. This is the canonical way to declare several attributes that share the same
|
|
383
|
+
configuration (default value, visibility, freezing, validations, etc.).
|
|
384
|
+
|
|
385
|
+
```ruby
|
|
386
|
+
class User::SignUpParams
|
|
387
|
+
include Micro::Attributes.with(:initialize, :accept)
|
|
388
|
+
|
|
389
|
+
TrimString = ->(value) { String(value).strip }
|
|
390
|
+
|
|
391
|
+
attribute :email, default: TrimString
|
|
392
|
+
attributes :password, :password_confirmation, reject: :empty?, default: TrimString, private: true
|
|
393
|
+
end
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
> **Note:** Unlike `.attribute`, this method accepts a shared options hash but defines all listed
|
|
397
|
+
> attributes with the same configuration. If you need different defaults/options per attribute,
|
|
398
|
+
> use `#attribute()` once per attribute.
|
|
276
399
|
|
|
277
400
|
[⬆️ Back to Top](#table-of-contents-)
|
|
278
401
|
|
|
@@ -641,6 +764,19 @@ Micro::Attributes.without(:diff) # will load :activemodel_validations, :keys_as_
|
|
|
641
764
|
Micro::Attributes.without(initialize: :strict) # will load :activemodel_validations, :diff and :keys_as_symbol
|
|
642
765
|
```
|
|
643
766
|
|
|
767
|
+
You can also pair `:accept` with any other feature, and switch into strict mode by passing the
|
|
768
|
+
hash form `accept: :strict`:
|
|
769
|
+
|
|
770
|
+
```ruby
|
|
771
|
+
Micro::Attributes.with(:accept)
|
|
772
|
+
|
|
773
|
+
Micro::Attributes.with(:accept, :diff, :initialize)
|
|
774
|
+
|
|
775
|
+
Micro::Attributes.with(:accept, :activemodel_validations, :diff, :keys_as_symbol)
|
|
776
|
+
|
|
777
|
+
Micro::Attributes.with(:diff, :keys_as_symbol, initialize: :strict, accept: :strict)
|
|
778
|
+
```
|
|
779
|
+
|
|
644
780
|
## Picking all the features
|
|
645
781
|
|
|
646
782
|
```ruby
|
|
@@ -648,13 +784,167 @@ Micro::Attributes.with_all_features
|
|
|
648
784
|
|
|
649
785
|
# This method returns the same of:
|
|
650
786
|
|
|
651
|
-
Micro::Attributes.with(:activemodel_validations, :diff, :keys_as_symbol, initialize: :strict)
|
|
787
|
+
Micro::Attributes.with(:accept, :activemodel_validations, :diff, :keys_as_symbol, initialize: :strict)
|
|
652
788
|
```
|
|
653
789
|
|
|
654
790
|
[⬆️ Back to Top](#table-of-contents-)
|
|
655
791
|
|
|
656
792
|
## Extensions
|
|
657
793
|
|
|
794
|
+
### Accept extension
|
|
795
|
+
|
|
796
|
+
The `:accept` extension adds a lightweight, dependency-free validation mechanism. Use the
|
|
797
|
+
`accept:` / `reject:` options on an attribute to validate the assigned value, and inspect the
|
|
798
|
+
result through `#attributes_errors`, `#accepted_attributes`, and `#rejected_attributes`.
|
|
799
|
+
|
|
800
|
+
```ruby
|
|
801
|
+
class User
|
|
802
|
+
include Micro::Attributes.with(:initialize, :accept)
|
|
803
|
+
|
|
804
|
+
attribute :age, accept: Integer, allow_nil: true
|
|
805
|
+
attribute :name, accept: -> v { v.is_a?(String) && !v.empty? }, default: 'John Doe'
|
|
806
|
+
attribute :email, accept: :present?
|
|
807
|
+
end
|
|
808
|
+
|
|
809
|
+
user = User.new({})
|
|
810
|
+
|
|
811
|
+
user.attributes_errors? # false
|
|
812
|
+
user.accepted_attributes? # true
|
|
813
|
+
user.rejected_attributes? # false
|
|
814
|
+
|
|
815
|
+
User.new(age: 'twenty', email: nil).tap do |bad|
|
|
816
|
+
bad.attributes_errors? # true
|
|
817
|
+
bad.attributes_errors # { "age" => "expected to be a kind of Integer", "email" => "expected to be present?" }
|
|
818
|
+
bad.accepted_attributes # ["name"]
|
|
819
|
+
bad.rejected_attributes # ["age", "email"]
|
|
820
|
+
end
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
#### What can `accept:` / `reject:` receive?
|
|
824
|
+
|
|
825
|
+
| Type | `accept:` means | `reject:` means |
|
|
826
|
+
| --------------- | -------------------------------------------- | ------------------------------------------------ |
|
|
827
|
+
| `Class`/`Module`| `value.kind_of?(expected)` must be true | `value.kind_of?(expected)` must be false |
|
|
828
|
+
| Predicate `:sym?` (ends with `?`) | `value.public_send(:sym?)` must be true | `value.public_send(:sym?)` must be false |
|
|
829
|
+
| Anything callable (proc, lambda, object responding to `#call`) | result of `expected.call(value)` must be truthy | result of `expected.call(value)` must be falsy |
|
|
830
|
+
|
|
831
|
+
Default rejection messages follow the pattern below; you can override them with
|
|
832
|
+
`rejection_message:` (see further down).
|
|
833
|
+
|
|
834
|
+
```ruby
|
|
835
|
+
attribute :name, accept: :present? # "expected to be present?"
|
|
836
|
+
attribute :name, reject: :empty? # "expected to not be empty?"
|
|
837
|
+
attribute :name, accept: String # "expected to be a kind of String"
|
|
838
|
+
attribute :name, reject: String # "expected to not be a kind of String"
|
|
839
|
+
attribute :name, accept: ->(v) { v } # "is invalid"
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
#### `allow_nil:` option
|
|
843
|
+
|
|
844
|
+
Skip validation when the incoming value is `nil`.
|
|
845
|
+
|
|
846
|
+
```ruby
|
|
847
|
+
class User
|
|
848
|
+
include Micro::Attributes.with(:initialize, :accept)
|
|
849
|
+
|
|
850
|
+
attribute :age, accept: Integer, allow_nil: true
|
|
851
|
+
end
|
|
852
|
+
|
|
853
|
+
User.new(age: nil).attributes_errors? # false
|
|
854
|
+
User.new(age: 21).attributes_errors? # false
|
|
855
|
+
User.new(age: 'x').attributes_errors? # true
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
#### `rejection_message:` option
|
|
859
|
+
|
|
860
|
+
Customize the error message either with a String or with a callable. A callable receives the
|
|
861
|
+
attribute name as its first argument, so the same builder can be reused across attributes (handy
|
|
862
|
+
for i18n).
|
|
863
|
+
|
|
864
|
+
```ruby
|
|
865
|
+
class User
|
|
866
|
+
include Micro::Attributes.with(:initialize, :accept)
|
|
867
|
+
|
|
868
|
+
attribute :name, accept: String, rejection_message: 'must be a string'
|
|
869
|
+
attribute :age, accept: Integer, rejection_message: ->(key) { "#{key} must be an integer" }
|
|
870
|
+
end
|
|
871
|
+
|
|
872
|
+
User.new(name: 1, age: 'x').attributes_errors
|
|
873
|
+
# => { "name" => "must be a string", "age" => "age must be an integer" }
|
|
874
|
+
```
|
|
875
|
+
|
|
876
|
+
Callable validators can also expose a `#rejection_message` method themselves, and it will be used
|
|
877
|
+
as the default message for that validator:
|
|
878
|
+
|
|
879
|
+
```ruby
|
|
880
|
+
class FilledString
|
|
881
|
+
def call(value)
|
|
882
|
+
value.is_a?(String) && !value.empty?
|
|
883
|
+
end
|
|
884
|
+
|
|
885
|
+
def rejection_message
|
|
886
|
+
->(key) { "#{key} can't be an empty string" }
|
|
887
|
+
end
|
|
888
|
+
end
|
|
889
|
+
|
|
890
|
+
class User
|
|
891
|
+
include Micro::Attributes.with(:initialize, :accept)
|
|
892
|
+
|
|
893
|
+
attribute :name, accept: FilledString.new
|
|
894
|
+
end
|
|
895
|
+
```
|
|
896
|
+
|
|
897
|
+
#### Strict mode (`accept: :strict`)
|
|
898
|
+
|
|
899
|
+
Use `Micro::Attributes.with(accept: :strict)` to raise as soon as any attribute is rejected,
|
|
900
|
+
instead of collecting errors silently.
|
|
901
|
+
|
|
902
|
+
```ruby
|
|
903
|
+
class User
|
|
904
|
+
include Micro::Attributes.with(initialize: :strict, accept: :strict)
|
|
905
|
+
|
|
906
|
+
attribute :age, accept: Integer
|
|
907
|
+
attribute :name, accept: ->(v) { v.is_a?(String) && !v.empty? }, default: 'John doe'
|
|
908
|
+
end
|
|
909
|
+
|
|
910
|
+
User.new(age: 'x', name: nil)
|
|
911
|
+
# ArgumentError:
|
|
912
|
+
# One or more attributes were rejected. Errors:
|
|
913
|
+
# * :age expected to be a kind of Integer
|
|
914
|
+
# * :name is invalid
|
|
915
|
+
```
|
|
916
|
+
|
|
917
|
+
#### Interaction with other features
|
|
918
|
+
|
|
919
|
+
- Validation runs **after** the default value resolution, so defaults are validated like any
|
|
920
|
+
regular value.
|
|
921
|
+
- When combined with the [ActiveModel::Validation extension](#activemodelvalidation-extension),
|
|
922
|
+
the `:accept` checks run first; AM validations only run if every attribute is accepted.
|
|
923
|
+
- `accept:` plays nicely with [`freeze:`](#freezing-attribute-values-freeze) and
|
|
924
|
+
[`private:`/`protected:`](#attribute-visibility-private-protected). See the combined example
|
|
925
|
+
below.
|
|
926
|
+
|
|
927
|
+
```ruby
|
|
928
|
+
require 'digest'
|
|
929
|
+
|
|
930
|
+
class User::SignUpParams
|
|
931
|
+
include Micro::Attributes.with(:initialize, accept: :strict)
|
|
932
|
+
|
|
933
|
+
TrimString = ->(value) { String(value).strip }
|
|
934
|
+
|
|
935
|
+
attribute :email, default: TrimString,
|
|
936
|
+
accept: ->(s) { s =~ /\A.+@.+\..+\z/ }, freeze: :after_dup
|
|
937
|
+
attributes :password, :password_confirmation, default: TrimString,
|
|
938
|
+
reject: :empty?, private: true
|
|
939
|
+
|
|
940
|
+
def password_digest
|
|
941
|
+
Digest::SHA256.hexdigest(password) if password == password_confirmation
|
|
942
|
+
end
|
|
943
|
+
end
|
|
944
|
+
```
|
|
945
|
+
|
|
946
|
+
[⬆️ Back to Top](#table-of-contents-)
|
|
947
|
+
|
|
658
948
|
### `ActiveModel::Validation` extension
|
|
659
949
|
|
|
660
950
|
If your application uses ActiveModel as a dependency (like a regular Rails app). You will be enabled to use the `activemodel_validations` extension.
|
data/Rakefile
CHANGED
|
@@ -7,4 +7,33 @@ Rake::TestTask.new(:test) do |t|
|
|
|
7
7
|
t.test_files = FileList['test/**/*_test.rb']
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
task
|
|
10
|
+
require 'appraisal/task'
|
|
11
|
+
|
|
12
|
+
Appraisal::Task.new
|
|
13
|
+
|
|
14
|
+
desc 'Run the full test suite against every supported Rails version'
|
|
15
|
+
task :matrix do
|
|
16
|
+
appraisals =
|
|
17
|
+
if RUBY_VERSION < '3.1'
|
|
18
|
+
%w[rails-6-0 rails-6-1 rails-7-0 rails-7-1]
|
|
19
|
+
elsif RUBY_VERSION < '3.2'
|
|
20
|
+
%w[rails-7-0 rails-7-1 rails-7-2]
|
|
21
|
+
elsif RUBY_VERSION < '3.3'
|
|
22
|
+
%w[rails-7-0 rails-7-1 rails-7-2 rails-8-0]
|
|
23
|
+
elsif RUBY_VERSION < '3.4'
|
|
24
|
+
%w[rails-7-0 rails-7-1 rails-7-2 rails-8-0 rails-8-1 rails-edge]
|
|
25
|
+
elsif RUBY_VERSION < '4.0'
|
|
26
|
+
%w[rails-7-2 rails-8-0 rails-8-1 rails-edge]
|
|
27
|
+
else
|
|
28
|
+
%w[rails-8-1 rails-edge]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Run the no-activemodel baseline first
|
|
32
|
+
sh 'bundle exec rake test'
|
|
33
|
+
|
|
34
|
+
appraisals.each do |appraisal|
|
|
35
|
+
sh "bundle exec appraisal #{appraisal} rake test"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
task default: :test
|
data/bin/matrix
ADDED
data/bin/setup
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem "rake", "~> 13.0"
|
|
6
|
+
gem "u-case", "~> 4.5", ">= 4.5.1"
|
|
7
|
+
|
|
8
|
+
group :test do
|
|
9
|
+
gem "minitest", "~> 6.0"
|
|
10
|
+
gem "simplecov", "~> 0.22.0", require: false
|
|
11
|
+
gem "ostruct", "~> 0.6.3"
|
|
12
|
+
gem "activemodel", "~> 8.1.0"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
gemspec path: "../"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem "rake", "~> 13.0"
|
|
6
|
+
gem "u-case", "~> 4.5", ">= 4.5.1"
|
|
7
|
+
|
|
8
|
+
group :test do
|
|
9
|
+
gem "minitest", "~> 6.0"
|
|
10
|
+
gem "simplecov", "~> 0.22.0", require: false
|
|
11
|
+
gem "ostruct", "~> 0.6.3"
|
|
12
|
+
gem "activemodel", branch: "main", git: "https://github.com/rails/rails"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
gemspec path: "../"
|
data/u-attributes.gemspec
CHANGED
|
@@ -25,10 +25,11 @@ Gem::Specification.new do |spec|
|
|
|
25
25
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
26
26
|
spec.require_paths = ['lib']
|
|
27
27
|
|
|
28
|
-
spec.required_ruby_version = '>= 2.
|
|
28
|
+
spec.required_ruby_version = '>= 2.7.0'
|
|
29
29
|
|
|
30
30
|
spec.add_runtime_dependency 'kind', '>= 4.0', '< 6.0'
|
|
31
31
|
|
|
32
|
+
spec.add_development_dependency 'appraisal', '~> 2.5'
|
|
32
33
|
spec.add_development_dependency 'bundler'
|
|
33
34
|
spec.add_development_dependency 'rake', '~> 13.0'
|
|
34
35
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: u-attributes
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 3.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rodrigo Serradura
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: kind
|
|
@@ -30,6 +29,20 @@ dependencies:
|
|
|
30
29
|
- - "<"
|
|
31
30
|
- !ruby/object:Gem::Version
|
|
32
31
|
version: '6.0'
|
|
32
|
+
- !ruby/object:Gem::Dependency
|
|
33
|
+
name: appraisal
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
35
|
+
requirements:
|
|
36
|
+
- - "~>"
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: '2.5'
|
|
39
|
+
type: :development
|
|
40
|
+
prerelease: false
|
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
42
|
+
requirements:
|
|
43
|
+
- - "~>"
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '2.5'
|
|
33
46
|
- !ruby/object:Gem::Dependency
|
|
34
47
|
name: bundler
|
|
35
48
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -70,15 +83,17 @@ files:
|
|
|
70
83
|
- ".github/workflows/ci.yml"
|
|
71
84
|
- ".gitignore"
|
|
72
85
|
- ".vscode/settings.json"
|
|
86
|
+
- Appraisals
|
|
73
87
|
- CODE_OF_CONDUCT.md
|
|
74
88
|
- Gemfile
|
|
75
89
|
- LICENSE.txt
|
|
76
90
|
- README.md
|
|
77
91
|
- Rakefile
|
|
78
92
|
- bin/console
|
|
79
|
-
- bin/
|
|
93
|
+
- bin/matrix
|
|
80
94
|
- bin/setup
|
|
81
|
-
-
|
|
95
|
+
- gemfiles/rails_8_1.gemfile
|
|
96
|
+
- gemfiles/rails_edge.gemfile
|
|
82
97
|
- lib/micro/attributes.rb
|
|
83
98
|
- lib/micro/attributes/diff.rb
|
|
84
99
|
- lib/micro/attributes/features.rb
|
|
@@ -98,7 +113,6 @@ homepage: https://github.com/serradura/u-attributes
|
|
|
98
113
|
licenses:
|
|
99
114
|
- MIT
|
|
100
115
|
metadata: {}
|
|
101
|
-
post_install_message:
|
|
102
116
|
rdoc_options: []
|
|
103
117
|
require_paths:
|
|
104
118
|
- lib
|
|
@@ -106,15 +120,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
106
120
|
requirements:
|
|
107
121
|
- - ">="
|
|
108
122
|
- !ruby/object:Gem::Version
|
|
109
|
-
version: 2.
|
|
123
|
+
version: 2.7.0
|
|
110
124
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
125
|
requirements:
|
|
112
126
|
- - ">="
|
|
113
127
|
- !ruby/object:Gem::Version
|
|
114
128
|
version: '0'
|
|
115
129
|
requirements: []
|
|
116
|
-
rubygems_version:
|
|
117
|
-
signing_key:
|
|
130
|
+
rubygems_version: 4.0.7
|
|
118
131
|
specification_version: 4
|
|
119
132
|
summary: Create "immutable" objects with no setters, just getters.
|
|
120
133
|
test_files: []
|
data/bin/prepare_coverage
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
# Borrowed from https://gist.github.com/qortex/7e7c49f3731391a91ee898336183acef
|
|
4
|
-
|
|
5
|
-
# Temporary hack to get CodeClimate to work with SimpleCov 0.18 JSON format until issue is fixed
|
|
6
|
-
# upstream: https://github.com/codeclimate/test-reporter/issues/413
|
|
7
|
-
|
|
8
|
-
require "json"
|
|
9
|
-
|
|
10
|
-
filename = "coverage/.resultset.json"
|
|
11
|
-
contents = JSON.parse(File.read(filename))
|
|
12
|
-
|
|
13
|
-
def remove_lines_key(obj)
|
|
14
|
-
case obj
|
|
15
|
-
when Hash
|
|
16
|
-
obj.transform_values do |val|
|
|
17
|
-
val.is_a?(Hash) && val.key?("lines") ? val["lines"] : remove_lines_key(val)
|
|
18
|
-
end
|
|
19
|
-
else
|
|
20
|
-
obj
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# overwrite
|
|
25
|
-
File.write(filename, JSON.generate(remove_lines_key(contents)))
|
|
26
|
-
|
|
27
|
-
puts Dir['coverage/.*.json']
|
data/bin/test
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
set -e
|
|
4
|
-
|
|
5
|
-
RUBY_V=$(ruby -v)
|
|
6
|
-
|
|
7
|
-
function reset_gemfile_and_test {
|
|
8
|
-
rm Gemfile.lock
|
|
9
|
-
|
|
10
|
-
eval "$1 bundle update"
|
|
11
|
-
eval "$1 bundle exec rake test"
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function test_with_activemodel {
|
|
15
|
-
reset_gemfile_and_test "ACTIVEMODEL_VERSION=$1"
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
RUBY_2_2345="ruby 2.[2345]."
|
|
19
|
-
RUBY_2_234="ruby 2.[234]."
|
|
20
|
-
RUBY_2_567="ruby 2.[567]."
|
|
21
|
-
RUBY_2_2="ruby 2.2."
|
|
22
|
-
RUBY_3_X="ruby 3.0."
|
|
23
|
-
|
|
24
|
-
if [[ $RUBY_V =~ $RUBY_2_2345 ]]; then
|
|
25
|
-
if [[ $RUBY_V =~ $RUBY_2_234 ]]; then
|
|
26
|
-
reset_gemfile_and_test
|
|
27
|
-
fi
|
|
28
|
-
|
|
29
|
-
if [[ $RUBY_V =~ $RUBY_2_2 ]]; then
|
|
30
|
-
test_with_activemodel "3.2"
|
|
31
|
-
fi
|
|
32
|
-
|
|
33
|
-
test_with_activemodel "4.0"
|
|
34
|
-
test_with_activemodel "4.1"
|
|
35
|
-
test_with_activemodel "4.2"
|
|
36
|
-
test_with_activemodel "5.0"
|
|
37
|
-
test_with_activemodel "5.1"
|
|
38
|
-
test_with_activemodel "5.2"
|
|
39
|
-
fi
|
|
40
|
-
|
|
41
|
-
if [[ $RUBY_V =~ $RUBY_2_567 ]] || [[ $RUBY_V =~ $RUBY_3_X ]]; then
|
|
42
|
-
gem install bundler -v ">= 2" --no-doc
|
|
43
|
-
|
|
44
|
-
reset_gemfile_and_test
|
|
45
|
-
|
|
46
|
-
test_with_activemodel "6.0"
|
|
47
|
-
test_with_activemodel "6.1"
|
|
48
|
-
fi
|