attribool 0.0.2 → 1.0.1

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: 04a8612ea59018c8c1ace211692e9100676136ac77613627b8e8b0b295cf3bae
4
- data.tar.gz: fe39cccfee3277bd92028940a54313e10861445a1b486d4791942875a3cb918a
3
+ metadata.gz: e18815dc8107a42c84084e2c35614d8111f7ae827224b4b78cbb3e920ff9c970
4
+ data.tar.gz: 84642d3baca03e19bf84794ed88f2696d1f639801b79f55cd9fc2636309f8061
5
5
  SHA512:
6
- metadata.gz: 762bd93ec17802176022253614871443f0e388892558d455b697b90e69d26be00917f6cd5b803f105e6ace168985e85a4c14305059e92886500bbb3f035efcff
7
- data.tar.gz: 1b125fffc61d42dc9a8b63b77b625f57786ca03c44a2045a7bb1685bb5ea1d6c8e36ffa5fa6104b14fde943e79bedcfb8d5b92da88a59c1b0dd1f692b67098d2
6
+ metadata.gz: 3984a29d0285e92995b01d36ba9fbe0fe4919b9800116bff642ff5e7f0ee8e3fe1c4444a5bb1f3494f87e41228c31b4f0a7eec086ae3f3e5f07f255a5943ba41
7
+ data.tar.gz: 68246fd9004eb745078a8399ee4dc160ba2b06535a12fad81173958053c738c523fe5df152e266e2103e74f84715f9ca0bb309726eb30159e313f45efd9a8761
@@ -1,3 +1,10 @@
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
+
1
8
  name: Ruby
2
9
 
3
10
  on:
@@ -10,15 +17,19 @@ jobs:
10
17
  test:
11
18
 
12
19
  runs-on: ubuntu-latest
20
+ strategy:
21
+ matrix:
22
+ ruby-version: ['2.6', '2.7', '3.0']
13
23
 
14
24
  steps:
15
25
  - uses: actions/checkout@v2
16
- - name: Set up Ruby 2.6
17
- uses: actions/setup-ruby@v1
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
18
31
  with:
19
- ruby-version: 2.6.x
20
- - name: Build and test with Rake
21
- run: |
22
- gem install bundler
23
- bundle install
24
- bundle exec rake test
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/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- attribool (0.0.1)
4
+ attribool (1.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -28,4 +28,4 @@ DEPENDENCIES
28
28
  test-unit (~> 3.3, >= 3.3.5)
29
29
 
30
30
  BUNDLED WITH
31
- 2.1.4
31
+ 2.2.17
data/README.md CHANGED
@@ -3,22 +3,26 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/attribool.svg)](https://badge.fury.io/rb/attribool)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
- > Pre-release version. Everything works, but not everything is documented.
7
-
8
6
  Ruby macros for creating boolean methods for attributes that may or may not be
9
- booleans themselves. This is done via coercion based on truthiness. For example,
10
- if you have an attribute of `@name`, and you want to know if `@name` is not
11
- `nil`, you can declare `bool_reader :name`, which will define the method
12
- `name?`. This method will return true if `@name` is truthy.
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.
13
13
 
14
14
  The `bool_reader` also comes with some handy options. For example, you can
15
- [define a method name](#a-bool_reader-with-method-name-or-prefix) that makes
16
- more sense. Using the same example, as above, if your attribute is `@name`, but
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
17
17
  you'd like for your boolean method to be called `named?`, you can use
18
- `bool_reader :name, method: :named?`.
18
+ `bool_reader :name, method_name: :named?`.
19
19
  [Conditionals](#a-bool_reader-with-method-name-and-conditional) can also be set
20
20
  with lambdas via the `condition:` keyword argument.
21
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
+
22
26
  Macros also exist for `bool_writer` and `bool_accessor`. When a writer
23
27
  method is defined, the value will always be coerced into a boolean before
24
28
  setting the attribute.
@@ -49,10 +53,14 @@ bundle exec rake install
49
53
  require 'attribool'
50
54
 
51
55
  class Person
52
- include Attribool
56
+ extend Attribool
53
57
 
54
58
  attr_accessor :name
55
59
  bool_reader :name
60
+ # OR
61
+ # bool_reader :@name
62
+ # bool_reader 'name'
63
+ # bool_reader '@name'
56
64
  end
57
65
 
58
66
  person = Person.new
@@ -66,26 +74,23 @@ person.name?
66
74
  # true, because @name is truthy.
67
75
  ```
68
76
 
69
- #### A bool_reader with method name or prefix
77
+ #### A bool_reader with method name
70
78
  ```ruby
71
79
  require 'attribool'
72
80
 
73
81
  class Person
74
- include Attribool
82
+ extend Attribool
75
83
 
76
84
  attr_accessor :name
77
- bool_reader :name, method: :named?
78
- bool_reader :name, prefix: :has
85
+ bool_reader :name, method_name: :named?
79
86
  end
80
87
 
81
88
  person = Person.new
82
89
  person.named?
83
- person.has_name?
84
90
  # false, because @name is nil.
85
91
 
86
92
  person.name = 'John Smith'
87
93
  person.named?
88
- person.has_name?
89
94
  # true, because @name is truthy.
90
95
  ```
91
96
 
@@ -94,11 +99,11 @@ person.has_name?
94
99
  require 'attribool'
95
100
 
96
101
  class Person
97
- include Attribool
102
+ extend Attribool
98
103
 
99
104
  attr_accessor :age
100
105
  # In the condition lambdas, the argument refers to the attribute's value.
101
- bool_reader :age, method: :adult?, condition: ->(a) { a.to_i >= 18 }
106
+ bool_reader :age, method_name: :adult?, condition: ->(a) { a.to_i >= 18 }
102
107
  end
103
108
 
104
109
  person = Person.new
@@ -114,12 +119,40 @@ person.adult?
114
119
  # true, because @age is greater than 18.
115
120
  ```
116
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
+
117
150
  #### Standard bool_accessor
118
151
  ```ruby
119
152
  require 'attribool'
120
153
 
121
154
  class Person
122
- include Attribool
155
+ extend Attribool
123
156
 
124
157
  bool_accessor :living
125
158
  end
@@ -134,6 +167,29 @@ person.living?
134
167
  # Be aware -- if you pass anything truthy, it will be coerced to true!
135
168
  ```
136
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
+
137
193
  ## Reporting Bugs and Requesting Features
138
194
  If you have an idea or find a bug, please [create an
139
195
  issue](https://github.com/evanthegrayt/attribool/issues/new). Just make sure
@@ -144,4 +200,4 @@ Request.
144
200
  I do these projects for fun, and I enjoy knowing that they're helpful to people.
145
201
  Consider starring [the repository](https://github.com/evanthegrayt/attribool)
146
202
  if you like it! If you love it, follow me [on
147
- Github](https://github.com/evanthegrayt)!
203
+ GitHub](https://github.com/evanthegrayt)!
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::Version.to_s
5
+ spec.version = Attribool::VERSION
6
6
  spec.authors = ['Evan Gray']
7
7
  spec.email = 'evanthegrayt@vivaldi.net'
8
8
  spec.license = 'MIT'
@@ -0,0 +1,62 @@
1
+ ##
2
+ # Abstraction for an attribute to determine its name, reader, writer, and
3
+ # instance variable name.
4
+ class Attribool::Attribute
5
+ ##
6
+ # The name of the attribute, without the leading "@".
7
+ #
8
+ # @return [String]
9
+ attr_reader :name
10
+
11
+ ##
12
+ # The name of the instance variable for the attribute, with the leading "@".
13
+ #
14
+ # @return [String]
15
+ attr_reader :ivar
16
+
17
+ ##
18
+ # The name of the reader for the attribute.
19
+ #
20
+ # @return [String]
21
+ attr_reader :reader
22
+
23
+ ##
24
+ # The name of the writer for the attribute.
25
+ #
26
+ # @return [String]
27
+ attr_reader :writer
28
+
29
+ ##
30
+ # Ensures that if multiple attributes are being defined, and +method_name+ is
31
+ # provided, that +method_name+ is a +Proc+.
32
+ #
33
+ # @param [Integer] number_of_attributes
34
+ #
35
+ # @param [String, Symbol, Proc] method_name
36
+ def self.validate_method_name(number_of_attributes, method_name)
37
+ if number_of_attributes > 1 && method_name && !method_name.is_a?(Proc)
38
+ raise ArgumentError, "Must use a Proc when creating multiple methods"
39
+ end
40
+ end
41
+
42
+ ##
43
+ # Create an Attribute. The attribute can either be a String or a Symbol, and
44
+ # can also start with an "@", or not.
45
+ #
46
+ # @param [String, Symbol] attribute
47
+ #
48
+ # @param [String, Symbol, Proc, nil] reader_name
49
+ def initialize(attribute, reader_name = nil)
50
+ attribute.to_s.tap do |a|
51
+ @ivar = a.start_with?('@') ? a : "@#{a}"
52
+ @name = @ivar.delete_prefix('@')
53
+ @reader =
54
+ case reader_name
55
+ when Proc then reader_name.call(name)
56
+ when nil then "#{name}?"
57
+ else reader_name.to_s
58
+ end
59
+ @writer = "#{name}="
60
+ end
61
+ end
62
+ end
@@ -9,7 +9,7 @@ module Attribool
9
9
  # Major version.
10
10
  #
11
11
  # @return [Integer]
12
- MAJOR = 0
12
+ MAJOR = 1
13
13
 
14
14
  ##
15
15
  # Minor version.
@@ -21,14 +21,36 @@ module Attribool
21
21
  # Patch version.
22
22
  #
23
23
  # @return [Integer]
24
- PATCH = 2
24
+ PATCH = 1
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
- "#{MAJOR}.#{MINOR}.#{PATCH}"
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
+ ##
52
+ # The version, as a string.
53
+ #
54
+ # @return [String]
55
+ VERSION = Version.to_s.freeze
34
56
  end
data/lib/attribool.rb CHANGED
@@ -1,70 +1,66 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'attribool/version'
4
+ require_relative 'attribool/attribute'
5
+
3
6
  ##
4
- # Adds macros and methods for dealing with boolean attributes.
7
+ # Adds macros for dealing with boolean attributes.
5
8
  module Attribool
6
- def self.included(klass) # :nodoc:
7
- klass.extend(ClassMethods)
8
- end
9
-
10
9
  ##
11
- # Class methods to be added to the class when included.
12
- module ClassMethods
13
- ##
14
- # Creates a method that returns a boolean for attributes that may or may
15
- # not be booleans themselves.
16
- #
17
- # @param [Symbol, String] attribute
18
- #
19
- # @kwarg [Boolean] allow_nil:
20
- #
21
- # @kwarg [Lambda] condition:
22
- #
23
- # @kwarg [Symbol, String] method:
24
- #
25
- # @kwarg [Symbol, String] prefix:
26
- def bool_reader(
27
- attribute,
28
- allow_nil: true,
29
- condition: nil,
30
- prefix: nil,
31
- method: nil
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
10
+ # Creates methods that return a boolean for attributes that may or may not be
11
+ # booleans themselves. Multiple readers can be created at once
12
+ #
13
+ # @param [Symbol, String] *attributes
14
+ #
15
+ # @kwarg [Boolean] allow_nil
16
+ #
17
+ # @kwarg [Proc] condition
18
+ #
19
+ # @kwarg [Symbol, String, Proc] method_name
20
+ def bool_reader(
21
+ *attributes,
22
+ allow_nil: true,
23
+ condition: nil,
24
+ method_name: nil
25
+ )
26
+ Attribute.validate_method_name(attributes.size, method_name)
38
27
 
39
- condition ? condition.call(ivar) : !!(ivar)
28
+ attributes.map { |a| Attribute.new(a, method_name) }.each do |attribute|
29
+ define_method(attribute.reader) do
30
+ value = instance_variable_get(attribute.ivar)
31
+ raise TypeError, "#{attribute.ivar} is nil" if value.nil? && !allow_nil
32
+
33
+ condition ? condition.call(value) : !!(value)
40
34
  end
41
35
  end
36
+ end
42
37
 
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|
38
+ ##
39
+ # Creates a writer for boolean attributes. Always coerces to boolean based
40
+ # on truthiness.
41
+ #
42
+ # @param [Symbol, String] *attributes
43
+ #
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.writer) do |v|
52
48
  if strict && ![TrueClass, FalseClass].include?(v.class)
53
49
  raise ArgumentError, 'Argument must be a boolean'
54
50
  end
55
51
 
56
- instance_variable_set("@#{attribute}", !!v)
52
+ instance_variable_set(attribute.ivar, !!v)
57
53
  end
58
54
  end
55
+ end
59
56
 
60
- ##
61
- # Creates a simple reader and writer for booleans. This should only be used
62
- # when the attribute should only ever be +true+ or +false+.
63
- #
64
- # @param [Symbol, String] attribute
65
- def bool_accessor(attribute)
66
- bool_reader(attribute)
67
- bool_writer(attribute)
68
- end
57
+ ##
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)
69
65
  end
70
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.2
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Gray
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-22 00:00:00.000000000 Z
11
+ date: 2022-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -79,6 +79,7 @@ files:
79
79
  - Rakefile
80
80
  - attribool.gemspec
81
81
  - lib/attribool.rb
82
+ - lib/attribool/attribute.rb
82
83
  - lib/attribool/version.rb
83
84
  homepage: https://github.com/evanthegrayt/attribool
84
85
  licenses: