alba 1.5.0 → 1.6.0

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: 34c441cbc87f959f73c3e7a0175309f780b23ce840add4d53cf5083488390f1f
4
- data.tar.gz: f78fb2eea40f502c6f7b3c905317616054bd397d30aa9ce979285003205c81af
3
+ metadata.gz: c7ab62feaab9747cd1441aea57b8d8f7f1d149261d86e4e64e9f859ae8f1091c
4
+ data.tar.gz: 4442a77416ee235ad6537580ec0600c4b1c9b0bea7b154b3a96010514316531d
5
5
  SHA512:
6
- metadata.gz: 326ac8e731f2b4e0fe4afbb8f690059ecd578ffcb9270b9779bdcb6bb50d57d063ec0a98fc488398915c39ca2978b41e79d53bb1f5a809f9272ad885c383a549
7
- data.tar.gz: 2b36eb5d07749505b4ab377b56cc7e564bcd6e86d872e7cb2c45f62ae2cf91a41b2c6e0b70cdcbb8d2a5d802528e4d9bfb113b723a2be7b1bdbc207c0277df45
6
+ metadata.gz: 373f00c4b2bf57f18d65d86a9c8209f9d0c94038f44a98df8e7c7768158d23e03f427729006eb113f0e88fde17a829364cf561026858c83bbb861a7d7eefba13
7
+ data.tar.gz: ad75036a0f554d13637d32413906f17166347459f2e3bcd3e1fe55f4ddc5d805da59ece5c1e46babadea434d667927aab4e3b7f6b0d37887ee6f58cae10396c9
@@ -0,0 +1,70 @@
1
+ # For most projects, this workflow file will not need changing; you simply need
2
+ # to commit it to your repository.
3
+ #
4
+ # You may wish to alter this file to override the set of languages analyzed,
5
+ # or to provide custom queries or build logic.
6
+ #
7
+ # ******** NOTE ********
8
+ # We have attempted to detect the languages in your repository. Please check
9
+ # the `language` matrix defined below to confirm you have the correct set of
10
+ # supported CodeQL languages.
11
+ #
12
+ name: "CodeQL"
13
+
14
+ on:
15
+ push:
16
+ branches: [ main ]
17
+ pull_request:
18
+ # The branches below must be a subset of the branches above
19
+ branches: [ main ]
20
+ schedule:
21
+ - cron: '21 4 * * 5'
22
+
23
+ jobs:
24
+ analyze:
25
+ name: Analyze
26
+ runs-on: ubuntu-latest
27
+ permissions:
28
+ actions: read
29
+ contents: read
30
+ security-events: write
31
+
32
+ strategy:
33
+ fail-fast: false
34
+ matrix:
35
+ language: [ 'ruby' ]
36
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37
+ # Learn more about CodeQL language support at https://git.io/codeql-language-support
38
+
39
+ steps:
40
+ - name: Checkout repository
41
+ uses: actions/checkout@v2
42
+
43
+ # Initializes the CodeQL tools for scanning.
44
+ - name: Initialize CodeQL
45
+ uses: github/codeql-action/init@v1
46
+ with:
47
+ languages: ${{ matrix.language }}
48
+ # If you wish to specify custom queries, you can do so here or in a config file.
49
+ # By default, queries listed here will override any specified in a config file.
50
+ # Prefix the list here with "+" to use these queries and those in the config file.
51
+ # queries: ./path/to/local/query, your-org/your-repo/queries@main
52
+
53
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
54
+ # If this step fails, then you should remove it and run the build manually (see below)
55
+ - name: Autobuild
56
+ uses: github/codeql-action/autobuild@v1
57
+
58
+ # ℹ️ Command-line programs to run using the OS shell.
59
+ # 📚 https://git.io/JvXDl
60
+
61
+ # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
62
+ # and modify them (or add more) to build your code if your project
63
+ # uses a compiled language
64
+
65
+ #- run: |
66
+ # make bootstrap
67
+ # make release
68
+
69
+ - name: Perform CodeQL Analysis
70
+ uses: github/codeql-action/analyze@v1
@@ -8,9 +8,11 @@ jobs:
8
8
  fail-fast: false
9
9
  matrix:
10
10
  os: [ubuntu-latest, windows-latest, macos-latest]
11
- ruby: [2.5, 2.6, 2.7, 3.0, head, jruby, truffleruby]
11
+ ruby: [2.5, 2.6, 2.7, 3.0, 3.1, head, jruby, truffleruby]
12
12
  gemfile: [all, without_active_support, without_oj]
13
13
  exclude:
14
+ - os: windows-latest
15
+ ruby: 3.1
14
16
  - os: windows-latest
15
17
  ruby: jruby
16
18
  - os: windows-latest
data/.rubocop.yml CHANGED
@@ -46,9 +46,11 @@ Metrics:
46
46
  - 'test/**/*.rb'
47
47
 
48
48
  # `Resource` module is a core module and its length tends to be long...
49
+ # `Alba` main module is also long because it has all parts of configuration
49
50
  Metrics/ModuleLength:
50
51
  Exclude:
51
52
  - 'lib/alba/resource.rb'
53
+ - 'lib/alba.rb'
52
54
 
53
55
  # Resource class includes DSLs, which tend to accept long list of parameters
54
56
  Metrics/ParameterLists:
data/CHANGELOG.md CHANGED
@@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.6.0] 2022-03-16
10
+
11
+ - [Feat] Support instance method as an attribute
12
+ - [Fix] Explicitly raise error when inference is disabled
13
+ - [Improve] `enable_inference!` now takes inflector as argument
14
+ - [Improve] `transform_keys` now accepts `:snake` and `:none`
15
+ - [Deprecate] `to_hash` is special method and should not be used
16
+ - [Deprecate] `ignoring` in favor of `attributes` overriding
17
+ - [Deprecate] `Alba.on_nil`, `Alba.on_error` and `Alba.enable_root_key_transformation!`
18
+
9
19
  ## [1.5.0] 2021-11-28
10
20
 
11
21
  - [Feat] Add nil handler
data/Gemfile CHANGED
@@ -9,8 +9,8 @@ gem 'inch', require: false # For inline documents
9
9
  gem 'minitest', '~> 5.14' # For test
10
10
  gem 'rake', '~> 13.0' # For test and automation
11
11
  gem 'rubocop', '>= 0.79.0', require: false # For lint
12
- gem 'rubocop-minitest', '~> 0.17.0', require: false # For lint
13
- gem 'rubocop-performance', '~> 1.12.0', require: false # For lint
12
+ gem 'rubocop-minitest', '~> 0.18.0', require: false # For lint
13
+ gem 'rubocop-performance', '~> 1.13.0', require: false # For lint
14
14
  gem 'rubocop-rake', '>= 0.5.1', require: false # For lint
15
15
  gem 'rubocop-sensible', '~> 0.3.0', require: false # For lint
16
16
  gem 'simplecov', '~> 0.21.0', require: false # For test coverage
data/README.md CHANGED
@@ -2,7 +2,6 @@
2
2
  [![CI](https://github.com/okuramasafumi/alba/actions/workflows/main.yml/badge.svg)](https://github.com/okuramasafumi/alba/actions/workflows/main.yml)
3
3
  [![codecov](https://codecov.io/gh/okuramasafumi/alba/branch/master/graph/badge.svg?token=3D3HEZ5OXT)](https://codecov.io/gh/okuramasafumi/alba)
4
4
  [![Maintainability](https://api.codeclimate.com/v1/badges/fdab4cc0de0b9addcfe8/maintainability)](https://codeclimate.com/github/okuramasafumi/alba/maintainability)
5
- [![Inline docs](http://inch-ci.org/github/okuramasafumi/alba.svg?branch=main)](http://inch-ci.org/github/okuramasafumi/alba)
6
5
  ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/okuramasafumi/alba)
7
6
  ![GitHub](https://img.shields.io/github/license/okuramasafumi/alba)
8
7
 
@@ -20,19 +19,19 @@ If you have feature requests or interesting ideas, join us with [Ideas](https://
20
19
 
21
20
  ## Why Alba?
22
21
 
23
- Because it's fast, flexible and well-maintained!
22
+ Because it's fast, easy-to-use and extensible!
24
23
 
25
24
  ### Fast
26
25
 
27
26
  Alba is faster than most of the alternatives. We have a [benchmark](https://github.com/okuramasafumi/alba/tree/master/benchmark).
28
27
 
29
- ### Flexible
28
+ ### Easy to use
30
29
 
31
- Alba provides a small set of DSL to define your serialization logic. It also provides methods you can override to alter and filter serialized hash so that you have full control over the result.
30
+ Alba provides four DSLs, `attributes` to fetch attribute with its name, `attribute` to execute block for the attribute, `one` to seriaize single attribute with another resource, and `many` to serialize collection attribute with another resource. When you want to do something complex, there are many examples in this README so you can mimic them to get started.
32
31
 
33
- ### Maintained
32
+ ### Extensible
34
33
 
35
- Alba is well-maintained and adds features quickly. [Coverage Status](https://coveralls.io/github/okuramasafumi/alba?branch=master) and [CodeClimate Maintainability](https://codeclimate.com/github/okuramasafumi/alba/maintainability) show the code base is quite healthy.
34
+ Alba embraces extensibility through common techniques such as class inheritance and module inclusion. Alba provides its capacity with one module so you can still have your own class hierarchy.
36
35
 
37
36
  ## Installation
38
37
 
@@ -72,15 +71,6 @@ You can find the documentation on [RubyDoc](https://rubydoc.info/github/okuramas
72
71
  * Layout
73
72
  * No runtime dependencies
74
73
 
75
- ## Anti features
76
-
77
- * Sorting keys
78
- * Class level support of parameters
79
- * Supporting all existing JSON encoder/decoder
80
- * Cache
81
- * [JSON:API](https://jsonapi.org) support
82
- * And many others
83
-
84
74
  ## Usage
85
75
 
86
76
  ### Configuration
@@ -116,23 +106,21 @@ You can consider setting a backend with Symbol as a shortcut to set encoder.
116
106
  You can enable inference feature using `enable_inference!` method.
117
107
 
118
108
  ```ruby
119
- Alba.enable_inference!
109
+ Alba.enable_inference!(with: :active_support)
120
110
  ```
121
111
 
122
- You must install `ActiveSupport` to enable inference.
123
-
124
- #### Error handling configuration
112
+ You can choose which inflector Alba uses for inference. Possible value for `with` option are:
125
113
 
126
- You can configure error handling with `on_error` method.
127
-
128
- ```ruby
129
- Alba.on_error :ignore
130
- ```
114
+ - `:active_support` for `ActiveSupport::Inflector`
115
+ - `:dry` for `Dry::Inflector`
116
+ - any object which responds to some methods (see [below](#custom-inflector))
131
117
 
132
118
  For the details, see [Error handling section](#error-handling)
133
119
 
134
120
  ### Simple serialization with root key
135
121
 
122
+ You can define attributes with (yes) `attributes` macro with attribute names. If your attribute need some calculations, you can use `attribute` with block.
123
+
136
124
  ```ruby
137
125
  class User
138
126
  attr_accessor :id, :name, :email, :created_at, :updated_at
@@ -159,7 +147,34 @@ end
159
147
 
160
148
  user = User.new(1, 'Masafumi OKURA', 'masafumi@example.com')
161
149
  UserResource.new(user).serialize
162
- # => "{\"id\":1,\"name\":\"Masafumi OKURA\",\"name_with_email\":\"Masafumi OKURA: masafumi@example.com\"}"
150
+ # => "{\"user\":{\"id\":1,\"name\":\"Masafumi OKURA\",\"name_with_email\":\"Masafumi OKURA: masafumi@example.com\"}}"
151
+ ```
152
+
153
+ You can define instance methods on resources so that you can use it as attribute name in `attributes`.
154
+
155
+ ```ruby
156
+ # The serialization result is the same as above
157
+ class UserResource
158
+ include Alba::Resource
159
+
160
+ root_key :user, :users # Later is for plural
161
+
162
+ attributes :id, :name, :name_with_email
163
+
164
+ # Attribute methods must accept one argument for each serialized object
165
+ def name_with_email(user)
166
+ "#{user.name}: #{user.email}"
167
+ end
168
+ end
169
+ ```
170
+
171
+ This even works with users collection.
172
+
173
+ ```ruby
174
+ user1 = User.new(1, 'Masafumi OKURA', 'masafumi@example.com')
175
+ user2 = User.new(2, 'Test User', 'test@example.com')
176
+ UserResource.new([user1, user2]).serialize
177
+ # => "{\"users\":[{\"id\":1,\"name\":\"Masafumi OKURA\",\"name_with_email\":\"Masafumi OKURA: masafumi@example.com\"},{\"id\":2,\"name\":\"Test User\",\"name_with_email\":\"Test User: test@example.com\"}]}"
163
178
  ```
164
179
 
165
180
  ### Serialization with associations
@@ -240,6 +255,63 @@ class AnotherUserResource
240
255
  end
241
256
  ```
242
257
 
258
+ You can "filter" association using second proc argument. This proc takes association object and `params`.
259
+
260
+ This feature is useful when you want to modify association, such as adding `includes` or `order` to ActiveRecord relations.
261
+
262
+ ```ruby
263
+ class User
264
+ attr_reader :id
265
+ attr_accessor :articles
266
+
267
+ def initialize(id)
268
+ @id = id
269
+ @articles = []
270
+ end
271
+ end
272
+
273
+ class Article
274
+ attr_accessor :id, :title, :body
275
+
276
+ def initialize(id, title, body)
277
+ @id = id
278
+ @title = title
279
+ @body = body
280
+ end
281
+ end
282
+
283
+ class ArticleResource
284
+ include Alba::Resource
285
+
286
+ attributes :title
287
+ end
288
+
289
+ class UserResource
290
+ include Alba::Resource
291
+
292
+ attributes :id
293
+
294
+ # Second proc works as a filter
295
+ many :articles,
296
+ proc { |articles, params|
297
+ filter = params[:filter] || :odd?
298
+ articles.select {|a| a.id.send(filter) }
299
+ },
300
+ resource: ArticleResource
301
+ end
302
+
303
+ user = User.new(1)
304
+ article1 = Article.new(1, 'Hello World!', 'Hello World!!!')
305
+ user.articles << article1
306
+ article2 = Article.new(2, 'Super nice', 'Really nice!')
307
+ user.articles << article2
308
+
309
+ UserResource.new(user).serialize
310
+ # => '{"id":1,"articles":[{"title":"Hello World!"}]}'
311
+ UserResource.new(user, params: {filter: :even?}).serialize
312
+ # => '{"id":1,"articles":[{"title":"Super nice"}]}'
313
+ ```
314
+
243
315
  ### Inline definition with `Alba.serialize`
244
316
 
245
317
  `Alba.serialize` method is a shortcut to define everything inline.
@@ -263,9 +335,11 @@ Alba.serialize(something)
263
335
 
264
336
  Although this might be useful sometimes, it's generally recommended to define a class for Resource.
265
337
 
266
- ### Inheritance and Ignorance
338
+ ### Inheritance and attributes filter
267
339
 
268
- You can `exclude` or `ignore` certain attributes using `ignoring`.
340
+ You can filter out certain attributes by overriding `attributes` instance method. This is useful when you want to customize existing resource with inheritance.
341
+
342
+ You can access raw attributes via `super` call. It returns a Hash whose keys are the name of the attribute and whose values are the body. Usually you need only keys to filter out, like below.
269
343
 
270
344
  ```ruby
271
345
  class Foo
@@ -285,7 +359,9 @@ class GenericFooResource
285
359
  end
286
360
 
287
361
  class RestrictedFooResource < GenericFooResource
288
- ignoring :id, :body
362
+ def attributes
363
+ super.select { |key, _| key.to_sym == :name }
364
+ end
289
365
  end
290
366
 
291
367
  RestrictedFooResource.new(foo).serialize
@@ -324,14 +400,22 @@ UserResourceCamel.new(user).serialize
324
400
  # => '{"id":1,"firstName":"Masafumi","lastName":"Okura"}'
325
401
  ```
326
402
 
403
+ Possible values for `transform_keys` argument are:
404
+
405
+ * `:camel` for CamelCase
406
+ * `:lower_camel` for lowerCamelCase
407
+ * `:dash` for dash-case
408
+ * `:snake` for snake_case
409
+ * `:none` for not transforming keys
410
+
327
411
  You can also transform root key when:
328
412
 
329
413
  * `Alba.enable_inference!` is called
330
414
  * `root_key!` is called in Resource class
331
- * `root` option of `transform_keys` is set to true or `Alba.enable_root_key_transformation!` is called.
415
+ * `root` option of `transform_keys` is set to true
332
416
 
333
417
  ```ruby
334
- Alba.enable_inference!
418
+ Alba.enable_inference!(with: :active_support) # with :dry also works
335
419
 
336
420
  class BankAccount
337
421
  attr_reader :account_number
@@ -361,30 +445,29 @@ Supported transformation types are :camel, :lower_camel and :dash.
361
445
 
362
446
  #### Custom inflector
363
447
 
364
- A custom inflector can be plugged in as follows...
365
- ```ruby
366
- Alba.inflector = MyCustomInflector
367
- ```
368
- ...and has to implement following interface (the parameter `key` is of type `String`):
448
+ A custom inflector can be plugged in as follows.
449
+
369
450
  ```ruby
370
- module InflectorInterface
371
- def camelize(key)
372
- raise "Not implemented"
451
+ module CustomInflector
452
+ module_function
453
+
454
+ def camelize(string)
455
+ end
456
+
457
+ def camelize_lower(string)
373
458
  end
374
459
 
375
- def camelize_lower(key)
376
- raise "Not implemented"
460
+ def dasherize(string)
377
461
  end
378
462
 
379
- def dasherize(key)
380
- raise "Not implemented"
463
+ def underscore(string)
464
+ end
465
+
466
+ def classify(string)
381
467
  end
382
468
  end
383
469
 
384
- ```
385
- For example you could use `Dry::Inflector`, which implements exactly the above interface. If you are developing a `Hanami`-Application `Dry::Inflector` is around. In this case the following would be sufficient:
386
- ```ruby
387
- Alba.inflector = Dry::Inflector.new
470
+ Alba.enable_inference!(with: CustomInflector)
388
471
  ```
389
472
 
390
473
  ### Filtering attributes
@@ -469,7 +552,7 @@ We believe this is clearer than using some (not implemented yet) DSL such as `de
469
552
  After `Alba.enable_inference!` called, Alba tries to infer root key and association resource name.
470
553
 
471
554
  ```ruby
472
- Alba.enable_inference!
555
+ Alba.enable_inference!(with: :active_support) # with :dry also works
473
556
 
474
557
  class User
475
558
  attr_reader :id
@@ -517,8 +600,6 @@ This resource automatically sets its root key to either "users" or "user", depen
517
600
 
518
601
  Also, you don't have to specify which resource class to use with `many`. Alba infers it from association name.
519
602
 
520
- Note that to enable this feature you must install `ActiveSupport` gem.
521
-
522
603
  ### Error handling
523
604
 
524
605
  You can set error handler globally or per resource using `on_error`.
@@ -562,12 +643,14 @@ There are four possible arguments `on_error` method accepts.
562
643
  The block receives five arguments, `error`, `object`, `key`, `attribute` and `resource class` and must return a two-element array. Below is an example.
563
644
 
564
645
  ```ruby
565
- # Global error handling
566
- Alba.on_error do |error, object, key, attribute, resource_class|
567
- if resource_class == MyResource
568
- ['error_fallback', object.error_fallback]
569
- else
570
- [key, error.message]
646
+ class ExampleResource
647
+ include Alba::Resource
648
+ on_error do |error, object, key, attribute, resource_class|
649
+ if resource_class == MyResource
650
+ ['error_fallback', object.error_fallback]
651
+ else
652
+ [key, error.message]
653
+ end
571
654
  end
572
655
  end
573
656
  ```
@@ -624,43 +707,6 @@ UserResource.new(User.new(1)).serialize
624
707
  # => '{"user":{"id":1,"name":"User1","age":20}}'
625
708
  ```
626
709
 
627
- You can also set global nil handler.
628
-
629
- ```ruby
630
- Alba.on_nil { 'default name' }
631
-
632
- class Foo
633
- attr_reader :name
634
- def initialize(name)
635
- @name = name
636
- end
637
- end
638
-
639
- class FooResource
640
- include Alba::Resource
641
-
642
- key :foo
643
-
644
- attributes :name
645
- end
646
-
647
- FooResource.new(Foo.new).serialize
648
- # => '{"foo":{"name":"default name"}}'
649
-
650
- class FooResource2
651
- include Alba::Resource
652
-
653
- key :foo
654
-
655
- on_nil { '' } # This is applied instead of global handler
656
-
657
- attributes :name
658
- end
659
-
660
- FooResource2.new(Foo.new).serialize
661
- # => '{"foo":{"name":""}}'
662
- ```
663
-
664
710
  ### Metadata
665
711
 
666
712
  You can set a metadata with `meta` DSL or `meta` option.
@@ -824,6 +870,108 @@ Also note that we use percentage notation here to use double quotes. Using singl
824
870
 
825
871
  Currently, Alba doesn't support caching, primarily due to the behavior of `ActiveRecord::Relation`'s cache. See [the issue](https://github.com/rails/rails/issues/41784).
826
872
 
873
+ ### Extend Alba
874
+
875
+ Sometimes we have shared behaviors across resources. In such cases we can have a module for common logic.
876
+
877
+ In `attribute` block we can call instance method so we can improve the code below:
878
+
879
+ ```ruby
880
+ class FooResource
881
+ include Alba::Resource
882
+ # other attributes
883
+ attribute :created_at do |foo|
884
+ foo.created_at.strftime('%m/%d/%Y')
885
+ end
886
+
887
+ attribute :updated_at do |foo|
888
+ foo.updated_at.strftime('%m/%d/%Y')
889
+ end
890
+ end
891
+
892
+ class BarResource
893
+ include Alba::Resource
894
+ # other attributes
895
+ attribute :created_at do |bar|
896
+ bar.created_at.strftime('%m/%d/%Y')
897
+ end
898
+
899
+ attribute :updated_at do |bar|
900
+ bar.updated_at.strftime('%m/%d/%Y')
901
+ end
902
+ end
903
+ ```
904
+
905
+ to:
906
+
907
+ ```ruby
908
+ module SharedLogic
909
+ def format_time(time)
910
+ time.strftime('%m/%d/%Y')
911
+ end
912
+ end
913
+
914
+ class FooResource
915
+ include Alba::Resource
916
+ include SharedLogic
917
+ # other attributes
918
+ attribute :created_at do |foo|
919
+ format_time(foo.created_at)
920
+ end
921
+
922
+ attribute :updated_at do |foo|
923
+ format_time(foo.updated_at)
924
+ end
925
+ end
926
+
927
+ class BarResource
928
+ include Alba::Resource
929
+ include SharedLogic
930
+ # other attributes
931
+ attribute :created_at do |bar|
932
+ format_time(bar.created_at)
933
+ end
934
+
935
+ attribute :updated_at do |bar|
936
+ format_time(bar.updated_at)
937
+ end
938
+ end
939
+ ```
940
+
941
+ We can even add our own DSL to serialize attributes for readability and removing code duplications.
942
+
943
+ To do so, we need to `extend` our module. Let's see how we can achieve the same goal with this approach.
944
+
945
+ ```ruby
946
+ module AlbaExtension
947
+ # Here attrs are an Array of Symbol
948
+ def formatted_time_attributes(*attrs)
949
+ attrs.each do |attr|
950
+ attribute attr do |object|
951
+ time = object.send(attr)
952
+ time.strftime('%m/%d/%Y')
953
+ end
954
+ end
955
+ end
956
+ end
957
+
958
+ class FooResource
959
+ include Alba::Resource
960
+ extend AlbaExtension
961
+ # other attributes
962
+ formatted_time_attributes :created_at, :updated_at
963
+ end
964
+
965
+ class BarResource
966
+ include Alba::Resource
967
+ extend AlbaExtension
968
+ # other attributes
969
+ formatted_time_attributes :created_at, :updated_at
970
+ end
971
+ ```
972
+
973
+ In this way we have shorter and cleaner code. Note that we need to use `send` or `public_send` in `attribute` block to get attribute data.
974
+
827
975
  ## Rails
828
976
 
829
977
  When you use Alba in Rails, you can create an initializer file with the line below for compatibility with Rails JSON encoder.
data/alba.gemspec CHANGED
@@ -12,9 +12,13 @@ Gem::Specification.new do |spec|
12
12
  spec.license = 'MIT'
13
13
  spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
14
14
 
15
- spec.metadata['homepage_uri'] = spec.homepage
16
- spec.metadata['source_code_uri'] = 'https://github.com/okuramasafumi/alba'
17
- spec.metadata['changelog_uri'] = 'https://github.com/okuramasafumi/alba/blob/main/CHANGELOG.md'
15
+ spec.metadata = {
16
+ 'bug_tracker_uri' => 'https://github.com/okuramasafumi/issues',
17
+ 'changelog_uri' => 'https://github.com/okuramasafumi/alba/blob/main/CHANGELOG.md',
18
+ 'documentation_uri' => 'https://rubydoc.info/github/okuramasafumi/alba',
19
+ 'source_code_uri' => 'https://github.com/okuramasafumi/alba',
20
+ 'rubygems_mfa_required' => 'true'
21
+ }
18
22
 
19
23
  # Specify which files should be added to the gem when it is released.
20
24
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.