formtastic_tristate_radio 0.1.0 → 0.2.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: 3c29b06aadeb4938a06be81d4b33c23c904d7033011aec8346d43b765f54d262
4
- data.tar.gz: 471d66686e0aa7db2526642214602aa49ede7ab6183100877e9bda5954bab37d
3
+ metadata.gz: c61035dc61996da98086ef61f099baa1552221ccbae23e7f67a7d430494f400f
4
+ data.tar.gz: 870da0885677bfe7e1ccfbf02cf7b3c0c1b6803c01de4167dfd4f7cda3c5fa16
5
5
  SHA512:
6
- metadata.gz: 7292702606d47a360a308d89c322bb3dda27adc62866c4bc0fa45e6939ebb841a30760684b8b299b7312838b83ebc800d1d5b83624a6d73b37d2f21f2ea33cc5
7
- data.tar.gz: 97251242621b60cc2d1c9f381f29a58f408eddd44c202ba9f57ddf6c7075c54212733c70c9b7ef83c317e8fde8991b7aaaa9f79439e7d060f8f111fc6d0f6c11
6
+ metadata.gz: c36a9fe479ada5422ccfaf5feed00da1d9efaeeea737779bf9cfc87826ecd16864780f1c70f47d7ecb4854040bf5ef751e51aae24abd8381afaa82cfc1a1cf2a
7
+ data.tar.gz: b6952ce6cc1b434103f4f0abe58a6e7b8fe5d96d0691afd5275fa61c37635bcf420f18511e7bbdf6ecf7de3825d2b8416dc8e071557be5d67b51b4a9571e91f6
data/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # Changelog
2
+
3
+ ## [0.2.0] - 2021-11-04
4
+
5
+ - Custom translation override from form via options
6
+ - Custom error class
7
+ - YARD documentation for everything
8
+ - Inherits from `Formtastic::Inputs::RadioInput` and patches only necessary methods
9
+ - Error YAML example for ActiveAdmin included only if ActiveAdmin is detected
10
+
11
+ ## [0.1.0] - 2021-11-01
12
+
13
+ Initial release
data/README.md CHANGED
@@ -1,50 +1,63 @@
1
1
  # Formtastic tri-state radio
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/formtastic_tristate_radio.svg)](https://badge.fury.io/rb/formtastic_tristate_radio)
4
+
3
5
  ## What is “tri-state”?
4
6
 
5
- — that which has 3 states.
7
+ — that which has 3 states.
6
8
 
7
- By defenition Boolean values have 2 states: True | False.
9
+ By defenition Boolean values have 2 states: True & False.
8
10
 
9
- However, if you store a Boolean value in a database column with no `NOT FULL` restriction, it aquires a 3d possible state: `null`.
11
+ However, if you store a Boolean value in a database column with no `NOT NULL` restriction, it aquires a 3<sup>d</sup> possible state: `null`.
10
12
 
11
- Some may say this is a questionable practice — I don’t think so. In real life you always have a case when the answer to your question may be only “yes” or “no”, but you don’t know the answer yet. Using a string type column, storing there `"yes"`, `"no"` and `"unset"` + using a state machine + validations — feels overkill to me.
13
+ Some may consider this practice questionable — I don’t think so. In real life you always have a case when the answer to your question may be only “yes” or “no”, but you don’t know the answer yet. Using a string type column, storing there `"yes"`, `"no"` and `"unset"` + using a state machine + validations — feels overkill to me.
12
14
 
13
15
 
14
16
  ## What the gem does
15
17
 
16
- 1. Provides a custom Formtastic input type `:tristate_radio` which renders 3 radios (“Yes”, “No”, “Unset”) instead of a checkbox (only where you put it).
17
- 1. Teaches Rails recognize `"null"` and `"nil"` param values as `nil`. See “[How it works](#how-it-works)” ☟ section for technical details on this.
18
- 1. Encourages you to add translations for ActiveAdmin “status tag” so that `nil` be correctly translated as “Unset” instead of “False”.
18
+ 1. Provides a custom Formtastic input type `:tristate_radio` which renders 3 radios (“Yes”, “No”, “Unset”) instead of a checkbox (only where you put it).
19
+ 1. Teaches Rails recognize `"null"` and `"nil"` param values as `nil`. See “[How it works](#how-it-works)” ☟ section for technical details on this.
20
+ 1. Encourages you to add translations for ActiveAdmin “status tag” so that `nil` be correctly translated as “Unset” instead of “False”.
19
21
 
20
22
 
21
23
  ## Usage
22
24
 
23
- For a Boolean column with 3 possible states:
25
+ For a Boolean column with 3 possible states:
24
26
 
25
27
  ```ruby
26
- f.input :column_name, as: :tristate_radio
28
+ f.input :am_i_awake, as: :tristate_radio
29
+ f.input :is_this_a_dream, as: :tristate_radio, null: "Reality is a persistent hallucination"
27
30
  ```
28
31
 
29
- You get (HTML is simplified):
32
+ You get (HTML is simplified, actually there are more classes etc.):
30
33
 
31
34
  ```html
32
35
  <fieldset>
33
- <input name="column_name" type="radio" value="true"> <label>Yes</label>
34
- <input name="column_name" type="radio" value="false"> <label>No</label>
35
- <input name="column_name" type="radio" value="null"> <label>Unset</label>
36
+ <legend>Am i awake?</legend>
37
+ <input name="am_i_awake" type="radio" value="true"> <label>Yes</label>
38
+ <input name="am_i_awake" type="radio" value="false"> <label>No</label>
39
+ <input name="am_i_awake" type="radio" value="null"> <label>Unset</label>
36
40
  </fieldset>
37
- ```
38
41
 
39
- In the future `:tristate_radio` will be registered for Boolean columns with `null` by default. Until then you have to assign it manually.
42
+ <fieldset>
43
+ <legend>Is this a dream?</legend>
44
+ <input name="is_this_a_dream" type="radio" value="true"> <label>Yes</label>
45
+ <input name="is_this_a_dream" type="radio" value="false"> <label>No</label>
46
+ <input name="is_this_a_dream" type="radio" value="null"> <label>Reality is a persistent hallucination</label>
47
+ </fieldset>
48
+ ```
40
49
 
41
50
 
42
51
  ## Installation
43
52
 
53
+ ### Gem
54
+
44
55
  ```ruby
45
56
  gem "formtastic_tristate_radio"
46
57
  ```
47
58
 
59
+ ### Translations
60
+
48
61
  Add translation for the new “unset” option:
49
62
 
50
63
  ```yaml
@@ -55,7 +68,15 @@ ru:
55
68
  null: Неизвестно # <- this you must provide youself
56
69
  ```
57
70
 
58
- ActiveAdmin will automatically translate `nil` as “No”, so if you use ActiveAdmin, add translation like so:
71
+ As noted in [Usage](#usage), you can override individual translations like so:
72
+
73
+ ```ruby
74
+ f.input :attribute, as: :tristate_radio, null: "Your text"
75
+ ```
76
+
77
+ ### ActiveAdmin translations
78
+
79
+ ActiveAdmin will automatically translate `nil` as “No”, so if you use ActiveAdmin, add translation like so:
59
80
 
60
81
  ```yaml
61
82
  ru:
@@ -63,23 +84,25 @@ ru:
63
84
  status_tag:
64
85
  :yes: Да
65
86
  :no: Нет
66
- null: Неизвестно
87
+ unset: Неизвестно
67
88
  ```
68
89
 
90
+ Notice that the key ActiveAdmin uses is “unset”, not “null”.
91
+
69
92
 
70
93
  ## Configuration
71
94
 
72
- Nothing is configurable yet. I think of making configurable which values are regognized as `nil`.
95
+ Nothing is configurable yet. I think of making configurable which values are regognized as `nil`.
73
96
 
74
97
 
75
98
  ## Dependencies
76
99
 
77
- Now the gem depends on [Formtastic](https://github.com/formtastic/formtastic) (naturally) and Rails. Frankly I am not sure whether I will have time to make it work with other frameworks.
100
+ Now the gem depends on [Formtastic](https://github.com/formtastic/formtastic) (naturally) and Rails. Frankly I am not sure whether I will have time to make it work with other frameworks.
78
101
 
79
102
 
80
103
  ## How it works
81
104
 
82
- In Ruby any String is cast to `true`:
105
+ In Ruby any String is cast to `true`:
83
106
 
84
107
  ```ruby
85
108
  !!"" #=> true
@@ -89,11 +112,11 @@ In Ruby any String is cast to `true`:
89
112
  !!"null" #=> true
90
113
  ```
91
114
 
92
- Web form params are passed as plain text and are interpreted as String by Rack.
115
+ Web form params are passed as plain text and are interpreted as String by Rack.
93
116
 
94
- So how Boolean values are transfered as strings if a `"no"` or `"0"` and even `""` is truthy in Ruby?
117
+ So how Boolean values are transfered as strings if a `"no"` or `"0"` and even `""` is truthy in Ruby?
95
118
 
96
- Frameworks just have a list of string values to be recognized and mapped to Boolean values:
119
+ Frameworks just have a list of string values to be recognized and mapped to Boolean values:
97
120
 
98
121
  ```ruby
99
122
  ActiveModel::Type::Boolean::FALSE_VALUES
@@ -115,7 +138,7 @@ ActiveModel::Type::Boolean.new.cast("off") #=> false
115
138
  # etc
116
139
  ```
117
140
 
118
- So what [I do in this gem](https://github.com/sergeypedan/formtastic_tristate_radio/blob/master/config/initializers/activemodel_type_boolean.rb) is extend `ActiveModel::Type::Boolean` in a consistent way to teach it recognize null-ish values as `nil`:
141
+ So what [I do in this gem](https://github.com/sergeypedan/formtastic_tristate_radio/blob/master/config/initializers/activemodel_type_boolean.rb) is extend `ActiveModel::Type::Boolean` in a consistent way to teach it recognize null-ish values as `nil`:
119
142
 
120
143
  ```ruby
121
144
  module ActiveModel
@@ -143,9 +166,17 @@ ActiveModel::Type::Boolean.new.cast("nil") #=> nil
143
166
  ActiveModel::Type::Boolean.new.cast(:nil) #=> nil
144
167
  ```
145
168
 
146
- **Warning**: as you might have noticed, default Rails behavior is changed. If you rely on Rails’ automatic conversion of strings with value `"null"` into `true`, this gem might not be for you (and you are definitely doing something weird).
169
+ **Warning**: as you might have noticed, default Rails behavior is changed. If you rely on Rails’ automatic conversion of strings with value `"null"` into `true`, this gem might not be for you (and you are definitely doing something weird).
170
+
171
+
172
+ ## Roadmap
173
+
174
+ - [ ] Load translations from gem
175
+ - [ ] Add translations into most popular languages
176
+ - [ ] Rgister `:tristate_radio` for Boolean columns with `null`
177
+ - [ ] Decouple from Rails
147
178
 
148
179
 
149
180
  ## License
150
181
 
151
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
182
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -3,168 +3,109 @@
3
3
  require "formtastic"
4
4
 
5
5
  # It may also be appropriate to put this file in `app/inputs`
6
- class TristateRadioInput
6
+ class TristateRadioInput < Formtastic::Inputs::RadioInput
7
7
 
8
- include Formtastic::Inputs::Base
9
- include Formtastic::Inputs::Base::Collections
10
- include Formtastic::Inputs::Base::Choices
11
-
12
-
13
- # UNSET_KEY = :null
14
- UNSET_KEY = ActiveModel::Type::Boolean::NULL_VALUES.reject(&:blank?).first
8
+ # No equals `:null`.
15
9
  #
16
- # Mind ActiveAdmin status resolving logic:
17
- # https://github.com/activeadmin/activeadmin/blob/master/lib/active_admin/views/components/status_tag.rb#L51
18
- # In status tag builder the value is lowercased before casting into boolean, and the keyword for nil is "unset", so
19
- # if we have lowercase "unset", translations from `ru.formtastic.unset` will be overriden by `ru.active_admin.status_tag.unset`.
20
-
21
- MISSING_TRANSLATION_ERROR_MSG = <<~HEREDOC
22
-
10
+ # Mind ActiveAdmin [status resolving logic](https://github.com/activeadmin/activeadmin/blob/master/lib/active_admin/views/components/status_tag.rb#L51):
11
+ # in status tag builder the value is lowercased before casting into Boolean, and the keyword for nil is `"unset"`.
12
+ # So if we have lowercase `"unset"`, translations from `ru.formtastic.unset` will be overriden by `ru.active_admin.status_tag.unset`.
13
+ #
14
+ UNSET_KEY = ActiveModel::Type::Boolean::NULL_VALUES.reject(&:blank?).first
23
15
 
24
- For ActiveAdmin status tags in index & view tables:
16
+ I18N_EXAMPLE_ACTIVEADMIN = <<~YAML.chomp
25
17
  ru:
26
18
  active_admin:
27
19
  status_tag:
28
20
  :yes: Да
29
21
  :no: Нет
30
22
  :#{UNSET_KEY}: Неизвестно
23
+ YAML
31
24
 
32
- For radiobutton labels in forms:
25
+ I18N_EXAMPLE_FORMTASTIC = <<~YAML.chomp
33
26
  ru:
34
27
  formtastic:
35
28
  :yes: Да
36
29
  :no: Нет
37
30
  :#{UNSET_KEY}: Неизвестно
38
-
39
- Note: “yes”, “no”, “null” and some other words are reserved, converted into Boolean values in YAML, so you need to quote or symbolize them.
40
- HEREDOC
31
+ YAML
41
32
 
42
33
 
43
- # template => an instance of ActionView::Base
34
+ # @note In you have ActiveAdmin installed, it will give you YAML example for ActiveAdmin as well, otherwise only for Formtastic
44
35
  #
45
- # @param choice [Array], ["Completed", "completed"]
36
+ # @return [String] error message with YAML examples for the “unset” label translation lookup error
46
37
  #
47
- def choice_html(choice)
48
- template.content_tag(:label, tag_content(choice), tag_options(choice))
38
+ def self.missing_i18n_error_msg
39
+ msg = []
40
+ msg << "Add translations for the “unset” radio label"
41
+ msg << ["For radiobutton labels in forms:", I18N_EXAMPLE_FORMTASTIC].join("\n")
42
+ msg << "Note: “yes”, “no” and some other reserved words are converted into Boolean values in YAML, so you need to quote or symbolize them."
43
+ msg << ["For ActiveAdmin status tags in index & view tables:", I18N_EXAMPLE_ACTIVEADMIN].join("\n") if !!defined?(ActiveAdmin)
44
+ msg.join("\n\n")
49
45
  end
50
46
 
51
47
 
52
- # collection => [["Completed", "completed"], ["In progress", "in_progress"], ["Unknown", "unset"]]
48
+ # @see https://github.com/formtastic/formtastic/blob/35dc806964403cb2bb0a6074b951ceef906c8581/lib/formtastic/inputs/base/choices.rb#L59 Original Formtastic method
53
49
  #
54
- # @return [Array]
50
+ # @return [Hash] HTML options for the `<input type="radio" />` tag
55
51
  #
56
- def collection_with_unset
57
- collection + [[unset_label_translation, UNSET_KEY]]
52
+ # Adds `{ selected: true }` to the original options Hash if the choice value equals attribute value (to ultimately set for `checked="checked"`)
53
+ #
54
+ def choice_html_options(choice)
55
+ super.merge({ checked: selected?(choice) })
58
56
  end
59
57
 
60
58
 
61
- # Override to remove the for attribute since this isn't associated with any element, as it's nested inside the legend
62
- # @return [Hash]
59
+ # @example Original method
60
+ # def collection_for_boolean
61
+ # true_text = options[:true] || Formtastic::I18n.t(:yes)
62
+ # false_text = options[:false] || Formtastic::I18n.t(:no)
63
+ # [ [true_text, true], [false_text, false] ]
64
+ # end
63
65
  #
64
- # @example
65
- # { for: nil, class: ["label"] }
66
+ # collection_for_boolean #=> [["Да", true], ["Нет", false]]
66
67
  #
67
- def label_html_options
68
- super.merge({ for: nil })
69
- end
70
-
71
-
72
- # choice_value(choice) => true | false | UNSET_KEY <- in our version
73
- # choice_value(choice) => true | false | ? <- in regular radio-buttons version
74
- # method => :status
75
- # object => ActiveRecord::Base model subclass, `User`
68
+ # @example This patched method
69
+ # collection_for_boolean #=> [["Да", true], ["Нет", false], ["Неизвестно", :null]]
76
70
  #
77
- # @param choice [Array], ["Completed", "completed"]
71
+ # @return [Array<[String, (Boolean|String|Symbol)]>] an array of “choices”, each presented as an array with 2 items: HTML label text and HTML input value
78
72
  #
79
- # For this to work, ActiveModel::Type::Boolean must be patched to resolve `UNSET_KEY` as nil
73
+ # @see https://github.com/formtastic/formtastic/blob/e34baba470d2fda75bf9748cff8898ee0ed29075/lib/formtastic/inputs/base/collections.rb#L131 Original Formtastic method
80
74
  #
81
- def selected?(choice)
82
- ActiveModel::Type::Boolean.new.cast(choice_value(choice)) == object.public_send(method)
75
+ def collection_for_boolean
76
+ super + [[label_text_for_unset, UNSET_KEY]]
83
77
  end
84
78
 
85
79
 
86
- # @returns [String]
87
- # "<input ...> Text..."
80
+ # Checks translation passed as option, then checks in locale
88
81
  #
89
- # @param choice [Array], ["Completed", "completed"]
90
- #
91
- # input_html_options => { id: "task_status", required: false, autofocus: false, readonly: false}
82
+ # @example
83
+ # label_text_for_unset #=> "Неизвестно"
92
84
  #
93
- # input_html_options.merge(choice_html_options(choice)).merge({ required: false })
94
- # => { id: "task_status_completed", required: false, autofocus: false, readonly: false }
85
+ # @return [String] Label of the radio that stands for the unknown choice
95
86
  #
96
- # builder => an instance of ActiveAdmin::FormBuilder
97
- # choice_label(choice) => "Completed"
98
- # choice_html_options(choice) => { id: "task_status_completed" }
99
- # choice_value(choice) => "completed"
100
- # input_name => :status
87
+ # @raise [StandardError] if the translation could not be found
88
+ # @see missing_i18n_error_msg
101
89
  #
102
- def tag_content(choice)
103
- builder.radio_button(
104
- input_name,
105
- choice_value(choice),
106
- input_html_options.merge(choice_html_options(choice)).merge({ required: false, checked: selected?(choice) })
107
- ) << choice_label(choice)
90
+ def label_text_for_unset
91
+ options.fetch(:null, Formtastic::I18n.t(UNSET_KEY)).presence or \
92
+ fail FormtasticTristateRadio::MissingTranslationError.new(self.class.missing_i18n_error_msg)
108
93
  end
109
94
 
110
95
 
111
- # choice_input_dom_id(choice) => "task_status_completed"
112
- # label_html_options => { for: nil, class: ["label"] }
113
- #
114
- # @param choice [Array], ["Completed", "completed"]
96
+ # @example For each item of `collection` it runs:
97
+ # selected?(["Да", true]) #=> false
98
+ # selected?(["Нет", false]) #=> false
99
+ # selected?(["Неизвестно", :null]) #=> true
115
100
  #
116
- def tag_options(choice)
117
- label_html_options.merge({ for: choice_input_dom_id(choice), class: nil })
118
- end
119
-
120
-
121
- # choice_wrapping_html_options(choice) #=> { class: "choice" }
101
+ # @param choice [Array<[String, (Boolean|String|Symbol)]>]
122
102
  #
123
- # legend_html => "<legend class="label">
124
- # <label>Status</label>
125
- # </legend>"
103
+ # @return [Boolean] answer to the question “Is the passed option selected?”
126
104
  #
127
- # choice_html(choice) => "<label for="task_status_completed">
128
- # <input type="radio" value="completed" name="task[status]" /> Completed
129
- # </label>"
105
+ # @note For this to work, `ActiveModel::Type::Boolean` must be patched to resolve `UNSET_KEY` as `nil`.
130
106
  #
131
- # collection.map do |choice|
132
- # choice_wrapping({ class: "choice" }) do
133
- # choice_html(choice)
134
- # end
135
- # end
136
- # => ["<li class="choice">
137
- # <label for="task_status_completed">
138
- # <input type="radio" value="completed" name="task[status]" /> Completed
139
- # </label>
140
- # </li>",
141
- # "<li class="choice">
142
- # ...
143
- # ]
144
- #
145
- # This method relies on ActiveAdmin
146
- #
147
- def to_html
148
- choices = collection_with_unset #=> [["Completed", "completed"], ["In progress", "in_progress"], ["Unknown", "unset"]]
149
-
150
- input_wrapping do
151
- choices_wrapping do
152
- legend_html << choices_group_wrapping do
153
- choices.map { |choice|
154
- choice_wrapping(choice_wrapping_html_options(choice)) do
155
- choice_html(choice)
156
- end
157
- }.join("\n").html_safe
158
- end
159
- end
160
- end
161
- end
162
-
163
-
164
- # @return [String] Label of the radio that stands for the unknown choice
165
- #
166
- def unset_label_translation
167
- Formtastic::I18n.t(UNSET_KEY).presence or fail StandardError.new(MISSING_TRANSLATION_ERROR_MSG)
107
+ def selected?(choice)
108
+ ActiveModel::Type::Boolean.new.cast(choice_value(choice)) == object.public_send(method)
168
109
  end
169
110
 
170
111
  end
@@ -2,7 +2,11 @@
2
2
 
3
3
  class ActiveRecord::Base
4
4
 
5
- # @return [Array] of symbols — names of Boolean columns, which can be `NULL`
5
+ # @return [Array<Symbol>] names of Boolean columns which can store `NULL` values
6
+ # @example
7
+ # Company.tristate_column_names
8
+ # #=> [:is_profitable, :is_run_by_psychopaths, :evades_taxation, ...]
9
+ #
6
10
  def self.tristate_column_names
7
11
  columns.select { |col| col.type == :boolean && col.null }.map(&:name)
8
12
  end
@@ -4,7 +4,7 @@ module ActiveModel
4
4
  module Type
5
5
  class Boolean < Value
6
6
 
7
- NULL_VALUES = [nil, "", "null", :null, "nil", :nil].to_set.freeze
7
+ NULL_VALUES = [nil, "", :null, "null", :nil, "nil"].to_set.freeze
8
8
 
9
9
  private def cast_value(value)
10
10
  NULL_VALUES.include?(value) ? nil : !FALSE_VALUES.include?(value)
@@ -1,4 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FormtasticTristateRadio
4
+
5
+ # This is standard Rails way to autoload gem’s contents dynamically as an “engine”
6
+ # https://guides.rubyonrails.org/engines.html
7
+ #
2
8
  class Engine < ::Rails::Engine
3
9
  end
10
+
4
11
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FormtasticTristateRadio
2
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
3
5
  end
@@ -1,8 +1,9 @@
1
- require "formtastic_tristate_radio/version"
2
- require "formtastic_tristate_radio/engine"
3
-
1
+ require_relative "formtastic_tristate_radio/version"
2
+ require_relative "formtastic_tristate_radio/engine"
4
3
  require_relative "../app/models/active_record/base"
5
- # require_relative "../app/inputs/tristate_radio_input"
6
4
 
7
5
  module FormtasticTristateRadio
6
+
7
+ class MissingTranslationError < StandardError; end
8
+
8
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: formtastic_tristate_radio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergey Pedan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-03 00:00:00.000000000 Z
11
+ date: 2021-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: formtastic
@@ -115,7 +115,9 @@ executables: []
115
115
  extensions: []
116
116
  extra_rdoc_files:
117
117
  - README.md
118
+ - CHANGELOG.md
118
119
  files:
120
+ - CHANGELOG.md
119
121
  - README.md
120
122
  - Rakefile
121
123
  - app/inputs/tristate_radio_input.rb
@@ -135,7 +137,7 @@ licenses:
135
137
  - MIT
136
138
  metadata:
137
139
  changelog_uri: https://github.com/sergeypedan/formtastic-tristate-radio/blob/master/Changelog.md
138
- documentation_uri: https://github.com/sergeypedan/formtastic-tristate-radio#usage
140
+ documentation_uri: https://www.rubydoc.info/gems/
139
141
  homepage_uri: https://github.com/sergeypedan/formtastic-tristate-radio
140
142
  source_code_uri: https://github.com/sergeypedan/formtastic-tristate-radio
141
143
  post_install_message: