attribool 0.0.1 → 1.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/ruby.yml +35 -0
- data/.gitignore +1 -0
- data/Gemfile.lock +2 -2
- data/README.md +90 -14
- data/Rakefile +1 -1
- data/attribool.gemspec +3 -5
- data/lib/attribool/attribute.rb +10 -0
- data/lib/attribool/method_name.rb +18 -0
- data/lib/attribool/version.rb +21 -3
- data/lib/attribool.rb +47 -77
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc735929535da353af1b584656aafb3ba6ba46b7996af32ae37dedc30bcfb0a2
|
4
|
+
data.tar.gz: 116a6a7fd8f9803773d10a6fff0b294f73bb9f5eb872db573f11273f8fc1ddcb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73fc2ab7f625fdfbb7577cda39c60eb86f6f53511fa685b2c0b86a79c90d22876123fcd34db74a76deb25eabc223cf891964fac36f962732af87a0c0c9aabcb0
|
7
|
+
data.tar.gz: ec6dc2496637c4c21c3c252a4c02fa1d574b4e4e033b74bd9019d5a8c286febba0990cd6d5659cc15be20b6a6c6dc3428f23a8bcb11ded8ed6a884403f78f682
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
7
|
+
|
8
|
+
name: Ruby
|
9
|
+
|
10
|
+
on:
|
11
|
+
push:
|
12
|
+
branches: [ master ]
|
13
|
+
pull_request:
|
14
|
+
branches: [ master ]
|
15
|
+
|
16
|
+
jobs:
|
17
|
+
test:
|
18
|
+
|
19
|
+
runs-on: ubuntu-latest
|
20
|
+
strategy:
|
21
|
+
matrix:
|
22
|
+
ruby-version: ['2.6', '2.7', '3.0']
|
23
|
+
|
24
|
+
steps:
|
25
|
+
- uses: actions/checkout@v2
|
26
|
+
- name: Set up Ruby
|
27
|
+
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
28
|
+
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
29
|
+
# uses: ruby/setup-ruby@v1
|
30
|
+
uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
|
31
|
+
with:
|
32
|
+
ruby-version: ${{ matrix.ruby-version }}
|
33
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
34
|
+
- name: Run tests
|
35
|
+
run: bundle exec rake
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,22 +1,34 @@
|
|
1
1
|
# Attribool
|
2
|
+
[](https://actions-badge.atrox.dev/evanthegrayt/attribool/goto?ref=master)
|
3
|
+
[](https://badge.fury.io/rb/attribool)
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
5
|
+
|
2
6
|
Ruby macros for creating boolean methods for attributes that may or may not be
|
3
|
-
booleans themselves. This is done via coercion based on truthiness
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
+
booleans themselves. This is done via either coercion based on truthiness, or a
|
8
|
+
user-defined condition.
|
9
|
+
|
10
|
+
For example, if you have an attribute of `@name`, and you want to know if
|
11
|
+
`@name` is not `nil`, you can declare `bool_reader :name`, which will define the
|
12
|
+
method `name?`. This method will return true if `@name` is truthy.
|
7
13
|
|
8
14
|
The `bool_reader` also comes with some handy options. For example, you can
|
9
|
-
[define a method name](#a-bool_reader-with-method-name
|
10
|
-
more sense.
|
15
|
+
[define a method name](#a-bool_reader-with-method-name) that makes
|
16
|
+
more sense. Using the same example as above, if your attribute is `@name`, but
|
11
17
|
you'd like for your boolean method to be called `named?`, you can use
|
12
|
-
`bool_reader :name,
|
18
|
+
`bool_reader :name, method_name: :named?`.
|
13
19
|
[Conditionals](#a-bool_reader-with-method-name-and-conditional) can also be set
|
14
20
|
with lambdas via the `condition:` keyword argument.
|
15
21
|
|
22
|
+
The first argument is always the instance variable to check for truthiness.
|
23
|
+
Because of this, it is also valid syntax to use `bool_reader :@name`, if it
|
24
|
+
makes more sense to you.
|
25
|
+
|
16
26
|
Macros also exist for `bool_writer` and `bool_accessor`. When a writer
|
17
27
|
method is defined, the value will always be coerced into a boolean before
|
18
28
|
setting the attribute.
|
19
29
|
|
30
|
+
You can read the documentation [here](https://evanthegrayt.github.io/attribool/).
|
31
|
+
|
20
32
|
## Installation
|
21
33
|
#### Via Gemfile
|
22
34
|
```ruby
|
@@ -45,6 +57,10 @@ class Person
|
|
45
57
|
|
46
58
|
attr_accessor :name
|
47
59
|
bool_reader :name
|
60
|
+
# OR
|
61
|
+
# bool_reader :@name
|
62
|
+
# bool_reader 'name'
|
63
|
+
# bool_reader '@name'
|
48
64
|
end
|
49
65
|
|
50
66
|
person = Person.new
|
@@ -58,7 +74,7 @@ person.name?
|
|
58
74
|
# true, because @name is truthy.
|
59
75
|
```
|
60
76
|
|
61
|
-
#### A bool_reader with method name
|
77
|
+
#### A bool_reader with method name
|
62
78
|
```ruby
|
63
79
|
require 'attribool'
|
64
80
|
|
@@ -66,18 +82,15 @@ class Person
|
|
66
82
|
extend Attribool
|
67
83
|
|
68
84
|
attr_accessor :name
|
69
|
-
bool_reader :name,
|
70
|
-
bool_reader :name, prefix: :has?
|
85
|
+
bool_reader :name, method_name: :named?
|
71
86
|
end
|
72
87
|
|
73
88
|
person = Person.new
|
74
89
|
person.named?
|
75
|
-
person.has_name?
|
76
90
|
# false, because @name is nil.
|
77
91
|
|
78
92
|
person.name = 'John Smith'
|
79
93
|
person.named?
|
80
|
-
person.has_name?
|
81
94
|
# true, because @name is truthy.
|
82
95
|
```
|
83
96
|
|
@@ -90,7 +103,7 @@ class Person
|
|
90
103
|
|
91
104
|
attr_accessor :age
|
92
105
|
# In the condition lambdas, the argument refers to the attribute's value.
|
93
|
-
bool_reader :age,
|
106
|
+
bool_reader :age, method_name: :adult?, condition: ->(a) { a.to_i >= 18 }
|
94
107
|
end
|
95
108
|
|
96
109
|
person = Person.new
|
@@ -106,6 +119,34 @@ person.adult?
|
|
106
119
|
# true, because @age is greater than 18.
|
107
120
|
```
|
108
121
|
|
122
|
+
#### Assigning more than one bool_reader with a method name at once
|
123
|
+
```ruby
|
124
|
+
require 'attribool'
|
125
|
+
|
126
|
+
class Person
|
127
|
+
extend Attribool
|
128
|
+
|
129
|
+
attr_accessor :name, :age
|
130
|
+
# When creating multiple readers at once, if you want to specify a
|
131
|
+
# method_name, you must provide a Proc as the argument, where the attribute
|
132
|
+
# name is the argument.
|
133
|
+
bool_reader :age, :name, method_name: ->(m) { "has_#{m}?" }
|
134
|
+
end
|
135
|
+
|
136
|
+
person = Person.new
|
137
|
+
person.has_age?
|
138
|
+
person.has_name?
|
139
|
+
# Both false, because @age and @name are nil.
|
140
|
+
|
141
|
+
person.age = 10
|
142
|
+
person.has_age?
|
143
|
+
# true, because @age is not nil.
|
144
|
+
|
145
|
+
person.name = 'Bob'
|
146
|
+
person.has_name?
|
147
|
+
# true, because @name is not nil.
|
148
|
+
```
|
149
|
+
|
109
150
|
#### Standard bool_accessor
|
110
151
|
```ruby
|
111
152
|
require 'attribool'
|
@@ -123,5 +164,40 @@ person.living?
|
|
123
164
|
person.living = true
|
124
165
|
person.living?
|
125
166
|
# true, because @living is true.
|
126
|
-
# Be aware -- if you pass
|
167
|
+
# Be aware -- if you pass anything truthy, it will be coerced to true!
|
127
168
|
```
|
169
|
+
|
170
|
+
#### Standard bool_writer
|
171
|
+
In most cases where you'd use a `bool_writer`, you'd probably want to just use
|
172
|
+
`bool_accessor`. This example is to show that, even when using `bool_accessor`,
|
173
|
+
the value is coerced to a boolean when the value is set by `bool_writer`.
|
174
|
+
```ruby
|
175
|
+
require 'attribool'
|
176
|
+
|
177
|
+
class Person
|
178
|
+
extend Attribool
|
179
|
+
|
180
|
+
attr_reader :living
|
181
|
+
bool_writer :living
|
182
|
+
end
|
183
|
+
|
184
|
+
person = Person.new
|
185
|
+
person.living
|
186
|
+
# nil
|
187
|
+
|
188
|
+
person.living = 'blah'
|
189
|
+
person.living
|
190
|
+
# true, because 'blah' was coerced into a boolean because strings are truthy.
|
191
|
+
```
|
192
|
+
|
193
|
+
## Reporting Bugs and Requesting Features
|
194
|
+
If you have an idea or find a bug, please [create an
|
195
|
+
issue](https://github.com/evanthegrayt/attribool/issues/new). Just make sure
|
196
|
+
the topic doesn't already exist. Better yet, you can always submit a Pull
|
197
|
+
Request.
|
198
|
+
|
199
|
+
## Self-Promotion
|
200
|
+
I do these projects for fun, and I enjoy knowing that they're helpful to people.
|
201
|
+
Consider starring [the repository](https://github.com/evanthegrayt/attribool)
|
202
|
+
if you like it! If you love it, follow me [on
|
203
|
+
GitHub](https://github.com/evanthegrayt)!
|
data/Rakefile
CHANGED
data/attribool.gemspec
CHANGED
@@ -2,7 +2,7 @@ require_relative 'lib/attribool/version'
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
spec.name = 'attribool'
|
5
|
-
spec.version = Attribool::
|
5
|
+
spec.version = Attribool::VERSION
|
6
6
|
spec.authors = ['Evan Gray']
|
7
7
|
spec.email = 'evanthegrayt@vivaldi.net'
|
8
8
|
spec.license = 'MIT'
|
@@ -19,10 +19,8 @@ Gem::Specification.new do |spec|
|
|
19
19
|
|
20
20
|
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
21
21
|
spec.metadata['homepage_uri'] = spec.homepage
|
22
|
-
spec.metadata['source_code_uri'] =
|
23
|
-
|
24
|
-
spec.metadata['documentation_uri'] =
|
25
|
-
'https://evanthegrayt.github.io/attribool/doc/index.html'
|
22
|
+
spec.metadata['source_code_uri'] = 'https://github.com/evanthegrayt/attribool'
|
23
|
+
spec.metadata['documentation_uri'] = 'https://evanthegrayt.github.io/attribool/'
|
26
24
|
|
27
25
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
28
26
|
f.match(%r{^(test|spec|features)/})
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Attribool::MethodName
|
2
|
+
attr_reader :name
|
3
|
+
|
4
|
+
def self.validate(method_name, number_of_attributes)
|
5
|
+
if number_of_attributes > 1 && method_name && !method_name.is_a?(Proc)
|
6
|
+
raise ArgumentError, "Must use a Proc when creating multiple methods"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(attribute, method_name)
|
11
|
+
@name =
|
12
|
+
case method_name
|
13
|
+
when Proc then method_name.call(attribute)
|
14
|
+
when nil then "#{attribute}?"
|
15
|
+
else method_name
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/attribool/version.rb
CHANGED
@@ -9,7 +9,7 @@ module Attribool
|
|
9
9
|
# Major version.
|
10
10
|
#
|
11
11
|
# @return [Integer]
|
12
|
-
MAJOR =
|
12
|
+
MAJOR = 1
|
13
13
|
|
14
14
|
##
|
15
15
|
# Minor version.
|
@@ -21,14 +21,32 @@ module Attribool
|
|
21
21
|
# Patch version.
|
22
22
|
#
|
23
23
|
# @return [Integer]
|
24
|
-
PATCH =
|
24
|
+
PATCH = 0
|
25
|
+
|
26
|
+
##
|
27
|
+
# Version as +[MAJOR, MINOR, PATCH]+
|
28
|
+
#
|
29
|
+
# @return [Array]
|
30
|
+
def self.to_a
|
31
|
+
[MAJOR, MINOR, PATCH]
|
32
|
+
end
|
25
33
|
|
26
34
|
##
|
27
35
|
# Version as +MAJOR.MINOR.PATCH+
|
28
36
|
#
|
29
37
|
# @return [String]
|
30
38
|
def self.to_s
|
31
|
-
|
39
|
+
to_a.join('.')
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Version as +{major: MAJOR, minor: MINOR, patch: PATCH}+
|
44
|
+
#
|
45
|
+
# @return [Hash]
|
46
|
+
def self.to_h
|
47
|
+
%i[major minor patch].zip(to_a).to_h
|
32
48
|
end
|
33
49
|
end
|
50
|
+
|
51
|
+
VERSION = Version.to_s.freeze
|
34
52
|
end
|
data/lib/attribool.rb
CHANGED
@@ -1,96 +1,66 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'attribool/version'
|
4
|
+
require_relative 'attribool/method_name'
|
5
|
+
require_relative 'attribool/attribute'
|
6
|
+
|
3
7
|
##
|
4
|
-
# Adds macros
|
8
|
+
# Adds macros for dealing with boolean attributes.
|
5
9
|
module Attribool
|
6
|
-
def self.included(klass)
|
7
|
-
klass.extend(ClassMethods)
|
8
|
-
end
|
9
|
-
|
10
10
|
##
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
)
|
33
|
-
method ||= "#{attribute}?"
|
34
|
-
method = "#{prefix}_#{method}" if prefix
|
35
|
-
define_method(method) do
|
36
|
-
ivar = instance_variable_get("@#{attribute}")
|
37
|
-
raise TypeError, "#{attribute} is nil" if ivar.nil? && !allow_nil
|
38
|
-
|
39
|
-
condition ? condition.call(ivar) : to_boolean(ivar)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
##
|
44
|
-
# Creates a writer for boolean attributes. Always coerces to boolean based
|
45
|
-
# on truthiness.
|
46
|
-
#
|
47
|
-
# @param [Symbol, String] attribute
|
48
|
-
#
|
49
|
-
# @kwarg [Boolean] strict:
|
50
|
-
def bool_writer(attribute, strict: false)
|
51
|
-
define_method("#{attribute}=") do |v|
|
52
|
-
validate_boolean(v) if strict
|
11
|
+
# Creates methods that return a boolean for attributes that may or may not be
|
12
|
+
# booleans themselves. Multiple readers can be created at once
|
13
|
+
#
|
14
|
+
# @param [Symbol, String] *attributes
|
15
|
+
#
|
16
|
+
# @kwarg [Boolean] allow_nil
|
17
|
+
#
|
18
|
+
# @kwarg [Proc] condition
|
19
|
+
#
|
20
|
+
# @kwarg [Symbol, String, Proc] method_name
|
21
|
+
def bool_reader(
|
22
|
+
*attributes,
|
23
|
+
allow_nil: true,
|
24
|
+
condition: nil,
|
25
|
+
method_name: nil
|
26
|
+
)
|
27
|
+
MethodName.validate(method_name, attributes.size)
|
28
|
+
attributes.map { |a| Attribute.new(a) }.each do |attribute|
|
29
|
+
define_method(MethodName.new(attribute.name, method_name).name) do
|
30
|
+
value = instance_variable_get(attribute.ivar)
|
31
|
+
raise TypeError, "#{attribute.ivar} is nil" if value.nil? && !allow_nil
|
53
32
|
|
54
|
-
|
33
|
+
condition ? condition.call(value) : !!(value)
|
55
34
|
end
|
56
35
|
end
|
57
|
-
|
58
|
-
##
|
59
|
-
# Creates a simple reader and writer for booleans. This should only be used
|
60
|
-
# when the attribute should only ever be +true+ or +false+.
|
61
|
-
#
|
62
|
-
# @param [Symbol, String] attribute
|
63
|
-
def bool_accessor(attribute)
|
64
|
-
bool_reader(attribute)
|
65
|
-
bool_writer(attribute)
|
66
|
-
end
|
67
36
|
end
|
68
37
|
|
69
38
|
##
|
70
|
-
#
|
39
|
+
# Creates a writer for boolean attributes. Always coerces to boolean based
|
40
|
+
# on truthiness.
|
71
41
|
#
|
72
|
-
# @param [
|
42
|
+
# @param [Symbol, String] *attributes
|
73
43
|
#
|
74
|
-
# @
|
75
|
-
def
|
76
|
-
|
77
|
-
|
44
|
+
# @kwarg [Boolean] strict
|
45
|
+
def bool_writer(*attributes, strict: false)
|
46
|
+
attributes.map { |a| Attribute.new(a) }.each do |attribute|
|
47
|
+
define_method("#{attribute.name}=") do |v|
|
48
|
+
if strict && ![TrueClass, FalseClass].include?(v.class)
|
49
|
+
raise ArgumentError, 'Argument must be a boolean'
|
50
|
+
end
|
78
51
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
# @param [Object] attribute
|
83
|
-
#
|
84
|
-
# @return [Boolean]
|
85
|
-
def to_boolean(attribute)
|
86
|
-
!!attribute
|
52
|
+
instance_variable_set(attribute.ivar, !!v)
|
53
|
+
end
|
54
|
+
end
|
87
55
|
end
|
88
56
|
|
89
|
-
private
|
90
|
-
|
91
57
|
##
|
92
|
-
#
|
93
|
-
|
94
|
-
|
58
|
+
# Creates a simple reader and writer for booleans. This should only be used
|
59
|
+
# when the attribute should only ever be +true+ or +false+.
|
60
|
+
#
|
61
|
+
# @param [Symbol, String] *attributes
|
62
|
+
def bool_accessor(*attributes)
|
63
|
+
bool_reader(*attributes)
|
64
|
+
bool_writer(*attributes)
|
95
65
|
end
|
96
66
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attribool
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Gray
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -70,6 +70,7 @@ executables: []
|
|
70
70
|
extensions: []
|
71
71
|
extra_rdoc_files: []
|
72
72
|
files:
|
73
|
+
- ".github/workflows/ruby.yml"
|
73
74
|
- ".gitignore"
|
74
75
|
- Gemfile
|
75
76
|
- Gemfile.lock
|
@@ -78,6 +79,8 @@ files:
|
|
78
79
|
- Rakefile
|
79
80
|
- attribool.gemspec
|
80
81
|
- lib/attribool.rb
|
82
|
+
- lib/attribool/attribute.rb
|
83
|
+
- lib/attribool/method_name.rb
|
81
84
|
- lib/attribool/version.rb
|
82
85
|
homepage: https://github.com/evanthegrayt/attribool
|
83
86
|
licenses:
|
@@ -86,7 +89,7 @@ metadata:
|
|
86
89
|
allowed_push_host: https://rubygems.org
|
87
90
|
homepage_uri: https://github.com/evanthegrayt/attribool
|
88
91
|
source_code_uri: https://github.com/evanthegrayt/attribool
|
89
|
-
documentation_uri: https://evanthegrayt.github.io/attribool/
|
92
|
+
documentation_uri: https://evanthegrayt.github.io/attribool/
|
90
93
|
post_install_message:
|
91
94
|
rdoc_options: []
|
92
95
|
require_paths:
|