formtastic_tristate_radio 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +151 -0
- data/Rakefile +12 -0
- data/app/inputs/tristate_radio_input.rb +170 -0
- data/app/models/active_record/base.rb +10 -0
- data/config/initializers/activemodel_type_boolean.rb +15 -0
- data/config/locales/active_admin.en.yml +5 -0
- data/config/locales/active_admin.ru.yml +7 -0
- data/config/locales/formtastic.en.yml +4 -0
- data/config/locales/formtastic.ru.yml +6 -0
- data/config/routes.rb +2 -0
- data/lib/formtastic_tristate_radio/engine.rb +4 -0
- data/lib/formtastic_tristate_radio/version.rb +3 -0
- data/lib/formtastic_tristate_radio.rb +8 -0
- data/lib/tasks/formtastic_tristate_radio_tasks.rake +4 -0
- metadata +166 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3c29b06aadeb4938a06be81d4b33c23c904d7033011aec8346d43b765f54d262
|
4
|
+
data.tar.gz: 471d66686e0aa7db2526642214602aa49ede7ab6183100877e9bda5954bab37d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7292702606d47a360a308d89c322bb3dda27adc62866c4bc0fa45e6939ebb841a30760684b8b299b7312838b83ebc800d1d5b83624a6d73b37d2f21f2ea33cc5
|
7
|
+
data.tar.gz: 97251242621b60cc2d1c9f381f29a58f408eddd44c202ba9f57ddf6c7075c54212733c70c9b7ef83c317e8fde8991b7aaaa9f79439e7d060f8f111fc6d0f6c11
|
data/README.md
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
# Formtastic tri-state radio
|
2
|
+
|
3
|
+
## What is “tri-state”?
|
4
|
+
|
5
|
+
— that which has 3 states.
|
6
|
+
|
7
|
+
By defenition Boolean values have 2 states: True | False.
|
8
|
+
|
9
|
+
However, if you store a Boolean value in a database column with no `NOT FULL` restriction, it aquires a 3d possible state: `null`.
|
10
|
+
|
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.
|
12
|
+
|
13
|
+
|
14
|
+
## What the gem does
|
15
|
+
|
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”.
|
19
|
+
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
For a Boolean column with 3 possible states:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
f.input :column_name, as: :tristate_radio
|
27
|
+
```
|
28
|
+
|
29
|
+
You get (HTML is simplified):
|
30
|
+
|
31
|
+
```html
|
32
|
+
<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
|
+
</fieldset>
|
37
|
+
```
|
38
|
+
|
39
|
+
In the future `:tristate_radio` will be registered for Boolean columns with `null` by default. Until then you have to assign it manually.
|
40
|
+
|
41
|
+
|
42
|
+
## Installation
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
gem "formtastic_tristate_radio"
|
46
|
+
```
|
47
|
+
|
48
|
+
Add translation for the new “unset” option:
|
49
|
+
|
50
|
+
```yaml
|
51
|
+
ru:
|
52
|
+
formtastic:
|
53
|
+
# :yes: Да # <- these two fall back to translations
|
54
|
+
# :no: Нет # in Formtastic gem but have only English
|
55
|
+
null: Неизвестно # <- this you must provide youself
|
56
|
+
```
|
57
|
+
|
58
|
+
ActiveAdmin will automatically translate `nil` as “No”, so if you use ActiveAdmin, add translation like so:
|
59
|
+
|
60
|
+
```yaml
|
61
|
+
ru:
|
62
|
+
active_admin:
|
63
|
+
status_tag:
|
64
|
+
:yes: Да
|
65
|
+
:no: Нет
|
66
|
+
null: Неизвестно
|
67
|
+
```
|
68
|
+
|
69
|
+
|
70
|
+
## Configuration
|
71
|
+
|
72
|
+
Nothing is configurable yet. I think of making configurable which values are regognized as `nil`.
|
73
|
+
|
74
|
+
|
75
|
+
## Dependencies
|
76
|
+
|
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.
|
78
|
+
|
79
|
+
|
80
|
+
## How it works
|
81
|
+
|
82
|
+
In Ruby any String is cast to `true`:
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
!!"" #=> true
|
86
|
+
!!"false" #=> true
|
87
|
+
!!"nil" #=> true
|
88
|
+
!!"no" #=> true
|
89
|
+
!!"null" #=> true
|
90
|
+
```
|
91
|
+
|
92
|
+
Web form params are passed as plain text and are interpreted as String by Rack.
|
93
|
+
|
94
|
+
So how Boolean values are transfered as strings if a `"no"` or `"0"` and even `""` is truthy in Ruby?
|
95
|
+
|
96
|
+
Frameworks just have a list of string values to be recognized and mapped to Boolean values:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
ActiveModel::Type::Boolean::FALSE_VALUES
|
100
|
+
#=> [
|
101
|
+
0, "0", :"0",
|
102
|
+
"f", :f, "F", :F,
|
103
|
+
false, "false", :false, "FALSE", :FALSE,
|
104
|
+
"off", :off, "OFF", :OFF,
|
105
|
+
]
|
106
|
+
```
|
107
|
+
|
108
|
+
so that
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
ActiveModel::Type::Boolean.new.cast("0") #=> false
|
112
|
+
ActiveModel::Type::Boolean.new.cast("f") #=> false
|
113
|
+
ActiveModel::Type::Boolean.new.cast(:FALSE) #=> false
|
114
|
+
ActiveModel::Type::Boolean.new.cast("off") #=> false
|
115
|
+
# etc
|
116
|
+
```
|
117
|
+
|
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`:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
module ActiveModel
|
122
|
+
module Type
|
123
|
+
class Boolean < Value
|
124
|
+
|
125
|
+
NULL_VALUES = [nil, "", "null", :null, "nil", :nil].to_set.freeze
|
126
|
+
|
127
|
+
private def cast_value(value)
|
128
|
+
NULL_VALUES.include?(value) ? nil : !FALSE_VALUES.include?(value)
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
```
|
135
|
+
|
136
|
+
And voila!
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
ActiveModel::Type::Boolean.new.cast("") #=> nil
|
140
|
+
ActiveModel::Type::Boolean.new.cast("null") #=> nil
|
141
|
+
ActiveModel::Type::Boolean.new.cast(:null) #=> nil
|
142
|
+
ActiveModel::Type::Boolean.new.cast("nil") #=> nil
|
143
|
+
ActiveModel::Type::Boolean.new.cast(:nil) #=> nil
|
144
|
+
```
|
145
|
+
|
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).
|
147
|
+
|
148
|
+
|
149
|
+
## License
|
150
|
+
|
151
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
|
5
|
+
# APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
6
|
+
load "rails/tasks/engine.rake"
|
7
|
+
load "rails/tasks/statistics.rake"
|
8
|
+
|
9
|
+
require "bundler/gem_tasks"
|
10
|
+
require "rspec/core/rake_task"
|
11
|
+
RSpec::Core::RakeTask.new(:spec)
|
12
|
+
task default: :spec
|
@@ -0,0 +1,170 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "formtastic"
|
4
|
+
|
5
|
+
# It may also be appropriate to put this file in `app/inputs`
|
6
|
+
class TristateRadioInput
|
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
|
15
|
+
#
|
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
|
+
|
23
|
+
|
24
|
+
For ActiveAdmin status tags in index & view tables:
|
25
|
+
ru:
|
26
|
+
active_admin:
|
27
|
+
status_tag:
|
28
|
+
:yes: Да
|
29
|
+
:no: Нет
|
30
|
+
:#{UNSET_KEY}: Неизвестно
|
31
|
+
|
32
|
+
For radiobutton labels in forms:
|
33
|
+
ru:
|
34
|
+
formtastic:
|
35
|
+
:yes: Да
|
36
|
+
:no: Нет
|
37
|
+
:#{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
|
41
|
+
|
42
|
+
|
43
|
+
# template => an instance of ActionView::Base
|
44
|
+
#
|
45
|
+
# @param choice [Array], ["Completed", "completed"]
|
46
|
+
#
|
47
|
+
def choice_html(choice)
|
48
|
+
template.content_tag(:label, tag_content(choice), tag_options(choice))
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
# collection => [["Completed", "completed"], ["In progress", "in_progress"], ["Unknown", "unset"]]
|
53
|
+
#
|
54
|
+
# @return [Array]
|
55
|
+
#
|
56
|
+
def collection_with_unset
|
57
|
+
collection + [[unset_label_translation, UNSET_KEY]]
|
58
|
+
end
|
59
|
+
|
60
|
+
|
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]
|
63
|
+
#
|
64
|
+
# @example
|
65
|
+
# { for: nil, class: ["label"] }
|
66
|
+
#
|
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`
|
76
|
+
#
|
77
|
+
# @param choice [Array], ["Completed", "completed"]
|
78
|
+
#
|
79
|
+
# For this to work, ActiveModel::Type::Boolean must be patched to resolve `UNSET_KEY` as nil
|
80
|
+
#
|
81
|
+
def selected?(choice)
|
82
|
+
ActiveModel::Type::Boolean.new.cast(choice_value(choice)) == object.public_send(method)
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
# @returns [String]
|
87
|
+
# "<input ...> Text..."
|
88
|
+
#
|
89
|
+
# @param choice [Array], ["Completed", "completed"]
|
90
|
+
#
|
91
|
+
# input_html_options => { id: "task_status", required: false, autofocus: false, readonly: false}
|
92
|
+
#
|
93
|
+
# input_html_options.merge(choice_html_options(choice)).merge({ required: false })
|
94
|
+
# => { id: "task_status_completed", required: false, autofocus: false, readonly: false }
|
95
|
+
#
|
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
|
101
|
+
#
|
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)
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
# choice_input_dom_id(choice) => "task_status_completed"
|
112
|
+
# label_html_options => { for: nil, class: ["label"] }
|
113
|
+
#
|
114
|
+
# @param choice [Array], ["Completed", "completed"]
|
115
|
+
#
|
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" }
|
122
|
+
#
|
123
|
+
# legend_html => "<legend class="label">
|
124
|
+
# <label>Status</label>
|
125
|
+
# </legend>"
|
126
|
+
#
|
127
|
+
# choice_html(choice) => "<label for="task_status_completed">
|
128
|
+
# <input type="radio" value="completed" name="task[status]" /> Completed
|
129
|
+
# </label>"
|
130
|
+
#
|
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)
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveModel
|
4
|
+
module Type
|
5
|
+
class Boolean < Value
|
6
|
+
|
7
|
+
NULL_VALUES = [nil, "", "null", :null, "nil", :nil].to_set.freeze
|
8
|
+
|
9
|
+
private def cast_value(value)
|
10
|
+
NULL_VALUES.include?(value) ? nil : !FALSE_VALUES.include?(value)
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/config/routes.rb
ADDED
metadata
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: formtastic_tristate_radio
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sergey Pedan
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-11-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: formtastic
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '5'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '5'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rails
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '4'
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '7'
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '4'
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '7'
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: coveralls
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0.2'
|
60
|
+
type: :development
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0.2'
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: pry
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0.14'
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0.14'
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: rake
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '13'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - "~>"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '13'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: yard
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0.9'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0.9'
|
109
|
+
description: 'Have 3-state radiobuttons instead of a 2-state checkbox for your Boolean
|
110
|
+
columns which can store NULL. Does not change controls, you need to turn it on via
|
111
|
+
`as: :tristate_radio` option.'
|
112
|
+
email:
|
113
|
+
- sergey.pedan@gmail.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files:
|
117
|
+
- README.md
|
118
|
+
files:
|
119
|
+
- README.md
|
120
|
+
- Rakefile
|
121
|
+
- app/inputs/tristate_radio_input.rb
|
122
|
+
- app/models/active_record/base.rb
|
123
|
+
- config/initializers/activemodel_type_boolean.rb
|
124
|
+
- config/locales/active_admin.en.yml
|
125
|
+
- config/locales/active_admin.ru.yml
|
126
|
+
- config/locales/formtastic.en.yml
|
127
|
+
- config/locales/formtastic.ru.yml
|
128
|
+
- config/routes.rb
|
129
|
+
- lib/formtastic_tristate_radio.rb
|
130
|
+
- lib/formtastic_tristate_radio/engine.rb
|
131
|
+
- lib/formtastic_tristate_radio/version.rb
|
132
|
+
- lib/tasks/formtastic_tristate_radio_tasks.rake
|
133
|
+
homepage: https://github.com/sergeypedan/formtastic-tristate-radio
|
134
|
+
licenses:
|
135
|
+
- MIT
|
136
|
+
metadata:
|
137
|
+
changelog_uri: https://github.com/sergeypedan/formtastic-tristate-radio/blob/master/Changelog.md
|
138
|
+
documentation_uri: https://github.com/sergeypedan/formtastic-tristate-radio#usage
|
139
|
+
homepage_uri: https://github.com/sergeypedan/formtastic-tristate-radio
|
140
|
+
source_code_uri: https://github.com/sergeypedan/formtastic-tristate-radio
|
141
|
+
post_install_message:
|
142
|
+
rdoc_options:
|
143
|
+
- "--charset=UTF-8"
|
144
|
+
require_paths:
|
145
|
+
- lib
|
146
|
+
- app/inputs
|
147
|
+
- app/models/active_record
|
148
|
+
- config/initializers
|
149
|
+
- config/locales
|
150
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - ">="
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: 2.4.0
|
155
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
requirements: []
|
161
|
+
rubygems_version: 3.2.15
|
162
|
+
signing_key:
|
163
|
+
specification_version: 4
|
164
|
+
summary: Have 3-state radiobuttons instead of a 2-state checkbox for your Boolean
|
165
|
+
columns which can store NULL
|
166
|
+
test_files: []
|