attribool 0.0.1 → 1.0.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: 469b94667c5be65a2901c9049f8290711c823fc7d08226140471c4c8820e66df
4
- data.tar.gz: 526c90658fc7f1ac712383083a5c38ced3088f3ed91fc32af3a6801e7c0352cc
3
+ metadata.gz: dc735929535da353af1b584656aafb3ba6ba46b7996af32ae37dedc30bcfb0a2
4
+ data.tar.gz: 116a6a7fd8f9803773d10a6fff0b294f73bb9f5eb872db573f11273f8fc1ddcb
5
5
  SHA512:
6
- metadata.gz: 90be0ebf1c939bf765d0dd3848cf273b00606d4e00335418b1fc44de239ffb5f2042032525a22f9b205b9b10b6ff71126ba0a3c01449d2957fe328f4be354359
7
- data.tar.gz: 48dbb1b70a57413523a962d29432343e5c7117f06ceae8063a7de1a5306595bab5f469db638a25bed1074efee037982e4a776c75334168e9d6e0064359e9e240
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
@@ -1,2 +1,3 @@
1
1
  attribool-*.gem
2
2
  coverage/*
3
+ docs/*
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
@@ -1,22 +1,34 @@
1
1
  # Attribool
2
+ [![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fevanthegrayt%2Fattribool%2Fbadge%3Fref%3Dmaster&style=flat)](https://actions-badge.atrox.dev/evanthegrayt/attribool/goto?ref=master)
3
+ [![Gem Version](https://badge.fury.io/rb/attribool.svg)](https://badge.fury.io/rb/attribool)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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. For example,
4
- if you have an attribute of `@name`, and you want to know if `@name` is not
5
- `nil`, you can declare `bool_reader :name`, which will define the method
6
- `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.
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-or-prefix) that makes
10
- 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
11
17
  you'd like for your boolean method to be called `named?`, you can use
12
- `bool_reader :name, method: :named?`.
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 or prefix
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, method: :named?
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, method: :adult?, condition: ->(a) { a.to_i >= 18 }
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 a string, it will be coerced to true!
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
@@ -14,7 +14,7 @@ end
14
14
 
15
15
  RDoc::Task.new do |rdoc|
16
16
  rdoc.main = 'README.md'
17
- rdoc.rdoc_dir = 'doc'
17
+ rdoc.rdoc_dir = 'docs'
18
18
  rdoc.rdoc_files.include('README.md', 'lib/**/*.rb')
19
19
  end
20
20
 
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'
@@ -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
- 'https://github.com/evanthegrayt/attribool'
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,10 @@
1
+ class Attribool::Attribute
2
+ attr_reader :name
3
+ attr_reader :ivar
4
+
5
+ def initialize(attribute)
6
+ attribute = attribute.to_s
7
+ @ivar = attribute.start_with?('@') ? attribute : "@#{attribute}"
8
+ @name = @ivar.delete_prefix('@')
9
+ end
10
+ end
@@ -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
@@ -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,32 @@ module Attribool
21
21
  # Patch version.
22
22
  #
23
23
  # @return [Integer]
24
- PATCH = 1
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
- "#{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
+ 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 and methods for dealing with boolean attributes.
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
- # 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
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
- instance_variable_set("@#{attribute}", to_boolean(v))
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
- # Is the argument a boolean?
39
+ # Creates a writer for boolean attributes. Always coerces to boolean based
40
+ # on truthiness.
71
41
  #
72
- # @param [Object] attribute
42
+ # @param [Symbol, String] *attributes
73
43
  #
74
- # @return [Boolean]
75
- def boolean?(attribute)
76
- [TrueClass, FalseClass].include?(attribute.class)
77
- end
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
- # Converts an Object to a boolean.
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
- # Raises if argument is not a boolean.
93
- def validate_boolean(attribute) # :nodoc:
94
- raise ArgumentError, 'Argument must be a boolean' unless boolean?(attribute)
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.1
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: 2021-04-22 00:00:00.000000000 Z
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/doc/index.html
92
+ documentation_uri: https://evanthegrayt.github.io/attribool/
90
93
  post_install_message:
91
94
  rdoc_options: []
92
95
  require_paths: