formtastic_tristate_radio 0.1.0 → 0.2.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: 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: