attribool 0.0.3 → 1.0.2

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: '0939b1cbdb170d795d5e99a9a2c353ccd2105b248f941b84638a7892e2ff8508'
4
- data.tar.gz: 9c446507b88ab93596f6d6f52a3717dfdf03a771885a9681b835e8e4e62cb050
3
+ metadata.gz: 40de41768cc69a7a822e65934217e6695907f8e2aa0896cac72073d4d7ee8620
4
+ data.tar.gz: 26bcc326d49235611dda2d00a230c592c192a502c4f2215698931ce76a0af80f
5
5
  SHA512:
6
- metadata.gz: feb26783987ea4569a324f461879f5e63908fc85a56438da1d0f252bd4e091f31daa45ec04a4089919e8bd0ab9d0fd2fa4f6e60d1b9d175b4fb9a7819e13e262
7
- data.tar.gz: 7ad52201e1f77310a09661ce11f29d1486ab935ecc02181bc69c6d349f6aa14482b6cf99e388c23c06ce9b50741ad2cc0b646b8ffbe72bbccfaa0b21614b9dd8
6
+ metadata.gz: f236b203d01b2f4a916c2f96c3ecc61f04d361b406700e93997fb17f5d965fd04f550858fc65ea33e5345247c3d36651bcd04a13faf454259f474743e0232c7b
7
+ data.tar.gz: 0bd9e8337766c2c4b9bae8a9e32cb70b898c6bdd6826b042c72a6938344840754c07af30a5737007f2c317ccbc1b8f326e1fe7af04e2982dad5fbdcd21e99ccc
@@ -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.3)
4
+ attribool (1.0.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
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 = 3
24
+ PATCH = 2
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.3
4
+ version: 1.0.2
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: