diff --git a/.travis.yml b/.travis.yml index a63cca8..2eaa384 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ rvm: - 2.5 - 2.6 - 2.7 - - ruby-head before_install: - yes | gem update --force --system - gem install bundler diff --git a/.yardopts b/.yardopts new file mode 100644 index 0000000..8a87dc3 --- /dev/null +++ b/.yardopts @@ -0,0 +1,3 @@ +--files 'CHANGELOG.md,LICENSE.txt' +--protected +--readme 'README.md' diff --git a/CHANGELOG.md b/CHANGELOG.md index 85ee30f..01d6dfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,60 @@ -# Changelog | attr_bool +# Changelog | AttrBool -Format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +All notable changes to this project will be documented in this file. -## [[Unreleased]](https://github.com/esotericpig/attr_bool/compare/v0.1.0...master) +Format is based on [Keep a Changelog v1.0.0](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning v2.0.0](https://semver.org/spec/v2.0.0.html). -## [v0.1.0] - 2020-04-20 +## [[Unreleased]](https://github.com/esotericpig/attr_bool/compare/v0.2.0...HEAD) + +- + +## [v0.2.0] - [2020-10-23](https://github.com/esotericpig/attr_bool/compare/v0.1.0...v0.2.0) + +A major departure from the previous version by not extending the core (monkey-patching) `Module` by default. + +```Ruby +require 'attr_bool' + +class BananaHammock + extend AttrBool::Ext +end +``` + +To imitate the previous version: + +```Ruby +require 'attr_bool/core_ext' +``` + +### Added +- AttrBool::Ext + - Was previously inside of *AttrBool* +- lib/attr_bool/core_ext.rb + - Was previously inside of *lib/attr_bool.rb* +- test/TestHelper +- test/CoreExtTest +- .yardopts + +### Changed +- attr_bool.gemspec + - Added *rdoc* & *redcarpet* dev deps for YARDoc + - Added *rdoc* files & opts + - Formatted for new Gemspec style +- README.md + - Updated to use new code + - Added more Similar Projects from [The Ruby Toolbox](https://www.ruby-toolbox.com/search?q=attr+bool) + - Formatted for new README style +- test/AttrBoolTest + - Updated to use new code + +## [v0.1.0] - [2020-04-20](https://github.com/esotericpig/attr_bool/tree/v0.1.0) Initial working version. + +### Added +### Changed +### Deprecated +### Removed +### Fixed +### Security diff --git a/README.md b/README.md index 867ac2b..f5fe657 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# attr_bool +# AttrBool [![Gem Version](https://badge.fury.io/rb/attr_bool.svg)](https://badge.fury.io/rb/attr_bool) [![Build Status](https://travis-ci.org/esotericpig/attr_bool.svg?branch=master)](https://travis-ci.org/esotericpig/attr_bool) @@ -7,112 +7,95 @@ [![Changelog](https://img.shields.io/badge/changelog-md-%23A0522D.svg)](CHANGELOG.md) [![License](https://img.shields.io/github/license/esotericpig/attr_bool.svg)](LICENSE.txt) -Easily create `attr` (attribute) methods that end with a question mark (`?`). +Easily create `attr` (attribute) methods that end with question marks (`?`). ```Ruby require 'attr_bool' module Wearable - # +attr_accessor?/reader?+ do not enforce boolean (true or false) values. - attr_accessor? :in_fashion,:in_season - attr_reader? :can_wash,:can_wear,default: 'yes!' + extend AttrBool::Ext + + attr_accessor? :in_fashion + attr_reader? :can_wash end class BananaHammock + extend AttrBool::Ext include Wearable - # +attr_bool*+ enforce boolean (true or false) values. - attr_bool :princess,:prince,default: 'Consuela' - attr_bool? :can_swim,:can_wink,true - attr_bool? (:crap_bag) { princess? && can_swim? } - attr_booler :friends - - def for_friends() - @friends - end + # Enforce boolean (true or false) values. + attr_bool :princess + attr_bool? :crap_bag end banham = BananaHammock.new() -puts banham.in_fashion? # => nil -puts banham.in_season? # => nil -puts banham.can_wash? # => 'yes!' -puts banham.can_wear? # => 'yes!' -puts '---' +banham.in_fashion = true +banham.princess = true -puts banham.princess? # => true (not 'Consuela') -puts banham.prince? # => true (not 'Consuela') -puts banham.can_swim? # => true -puts banham.can_wink? # => true -puts banham.crap_bag? # => true -puts '---' +p banham.in_fashion? #=> true +p banham.can_wash? #=> nil +p banham.princess? #=> true +p banham.crap_bag? #=> false +``` -banham.in_fashion = true -banham.in_season = 'always' -banham.princess = nil -banham.prince = 'Charming' -banham.friends = 'Valerie' +Require `attr_bool/core_ext` to extend the core (monkey-patch) `Module` & `Class` (not recommended for libraries): + +```Ruby +require 'attr_bool/core_ext' -puts banham.in_fashion? # => true -puts banham.in_season? # => 'always' -puts banham.princess? # => false (not nil) -puts banham.prince? # => true (not 'Charming') -puts banham.crap_bag? # => false (dynamic; because +princess?+ is now false) -puts banham.for_friends # => true (not 'Valerie') +class BananaHammock + attr_bool :princess + attr_bool? :crap_bag +end ``` ## Contents -- [Similar Projects](#similar-projects-) -- [Setup](#setup-) -- [Using](#using-) - - [Using with Default](#using-with-default-) - - [Using with Block/Proc/Lambda](#using-with-blockproclambda-) - - [Using with YARDoc](#using-with-yardoc-) -- [Hacking](#hacking-) - - [Benchmarks](#benchmarks-) -- [License](#license-) +- [Similar Projects](#-similar-projects) +- [Setup](#-setup) +- [Usage](#-usage) + - [Complete Example](#-complete-example) + - [Default Values](#-default-values) + - [Block/Proc/Lambda](#-blockproclambda) + - [YARDoc](#-yardoc) +- [Hacking](#-hacking) + - [Benchmarks](#-benchmarks) +- [License](#-license) -## Similar Projects [^](#contents) +## [//](#contents) Similar Projects Create an [issue](https://github.com/esotericpig/attr_bool/issues) to add your project. -| Name | Links | Example | +| Gem Name | Code | Example | | --- | --- | --- | -| attr_asker | [[GitHub]](https://github.com/kitlangton/attr_asker) [[RubyGems]](https://rubygems.org/gems/attr_asker) | `attr_asker :running` | -| attr_boolean | [[GitHub]](https://github.com/talentnest/attr_boolean) [[RubyGems]](https://rubygems.org/gems/attr_boolean) | `attr_boolean :running, default: true` | -| named_accessors | [[GitHub]](https://github.com/zlw/named_accessors) [[RubyGems]](https://rubygems.org/gems/named_accessors) | `named_reader :running, as: :running?` | -| attr_setting | [[GitHub]](https://github.com/merhard/attr_setting) [[RubyGems]](https://rubygems.org/gems/attr_setting) | `attr_setting :running, true` | -| property-accessor | [[GitHub]](https://github.com/estepnv/property-accessor) [[RubyGems]](https://rubygems.org/gems/property-accessor) | `property(:running) { get(:running?); default { true } }` | -| wannabe_bool | [[GitHub]](https://github.com/prodis/wannabe_bool) [[RubyGems]](https://rubygems.org/gems/wannabe_bool) | `attr_wannabe_bool :running` | -| wardrobe | [[GitHub]](https://github.com/agensdev/wardrobe) [[RubyGems]](https://rubygems.org/gems/wardrobe) | `attribute :running, Wardrobe::Boolean, default: true` | +| [attr_asker](https://rubygems.org/gems/attr_asker) | [[GitHub]](https://github.com/kitlangton/attr_asker) | `attr_asker :running` | +| [attr_boolean](https://rubygems.org/gems/attr_boolean) | [[GitHub]](https://github.com/talentnest/attr_boolean) | `attr_boolean :running, default: true` | +| [attr_setting](https://rubygems.org/gems/attr_setting) | [[GitHub]](https://github.com/merhard/attr_setting) | `attr_setting :running, true` | +| [attribute_boolean](https://rubygems.org/gems/attribute_boolean) | [[GitHub]](https://github.com/alexmchale/attribute_boolean) | `attr_boolean :running` | +| [boolean_accessor](https://rubygems.org/gems/boolean_accessor) | [[GitHub]](https://github.com/hiroki23/boolean_accessor) | `battr_accessor :running` | +| [named_accessors](https://rubygems.org/gems/named_accessors) | [[GitHub]](https://github.com/zlw/named_accessors) | `named_reader :running, as: :running?` | +| [property-accessor](https://rubygems.org/gems/property-accessor) | [[GitHub]](https://github.com/estepnv/property-accessor) | `property(:running) { get(:running?); default { true } }` | +| [question_mark_methods](https://rubygems.org/gems/question_mark_methods) | [[GitHub]](https://github.com/poiyzy/questionmarkmethods) | `add_question_mark_methods running?: :running` | +| [wannabe_bool](https://rubygems.org/gems/wannabe_bool) | [[GitHub]](https://github.com/prodis/wannabe_bool) | `attr_wannabe_bool :running` | +| [wardrobe](https://rubygems.org/gems/wardrobe) | [[GitHub]](https://github.com/agensdev/wardrobe) | `attribute :running, Wardrobe::Boolean, default: true` | -## Setup [^](#contents) +Searches: -Pick your poison... +- [The Ruby Toolbox](https://www.ruby-toolbox.com/search?q=attr+bool) +- [RubyGems.org](https://rubygems.org/search?query=attr+OR+attribute) -In your *Gemspec* (*<project>.gemspec*): +## [//](#contents) Setup -```Ruby -# Pick one... -spec.add_runtime_dependency 'attr_bool', '~> X.X' -spec.add_development_dependency 'attr_bool', '~> X.X' -``` +Add `attr_bool` to your *Gemspec* or *Gemfile*. -In your *Gemfile*: +Or, use the *RubyGems* package manager: -```Ruby -# Pick one... -gem 'attr_bool', '~> X.X' -gem 'attr_bool', '~> X.X', :group => :development -gem 'attr_bool', :git => 'https://github.com/esotericpig/attr_bool.git', :tag => 'vX.X.X' +``` +$ gem install attr_bool ``` -With the RubyGems package manager: - -`$ gem install attr_bool` - -Manually: +Or, manually: ``` $ git clone 'https://github.com/esotericpig/attr_bool.git' @@ -121,9 +104,35 @@ $ bundle install $ bundle exec rake install:local ``` -## Using [^](#contents) +## [//](#contents) Usage + +Either require `attr_bool` or `attr_bool/core_ext`. + +The first one requires extending `AttrBool::Ext` manually. + +```Ruby +require 'attr_bool' + +class Game + extend AttrBool::Ext + + attr_accessor? :running + attr_reader? :winning +end +``` + +The second one automatically extends `Module` & `Class`, which is not recommended for sharing libraries. -Simply use `attr_accessor?` and/or `attr_reader?` with 1 or more Symbols and/or Strings. +```Ruby +require 'attr_bool/core_ext' + +class Game + attr_accessor? :running + attr_reader? :winning +end +``` + +Now, simply use `attr_accessor?` and/or `attr_reader?` with one or more Symbols and/or Strings. These do **not** force the values to be booleans (true or false). @@ -133,6 +142,8 @@ For most purposes, this is adequate. require 'attr_bool' class Game + extend AttrBool::Ext + attr_accessor? :running,'looper' attr_reader? :fps,'music' @@ -146,25 +157,27 @@ end game = Game.new() -puts game.running? # => false -puts game.looper? # => nil -puts game.fps? # => 60 -puts game.music? # => 'Beatles' +puts game.running? #=> false +puts game.looper? #=> nil +puts game.fps? #=> 60 +puts game.music? #=> 'Beatles' game.running = true game.looper = :main -puts game.running? # => true -puts game.looper? # => :main +puts game.running? #=> true +puts game.looper? #=> :main ``` -There is also `attr_writer?`, but it simply calls the standard `attr_writer` unless you pass in a [block](#using-with-blockproclambda-). +There is also `attr_writer?`, but it simply calls the standard `attr_writer` unless you pass in a [block](#-blockproclambda). To enforce boolean (true or false) values, use... -- `attr_bool` or `attr_boolor` (accessor) -- `attr_bool?` (reader) -- `attr_booler` (writer) +| Name | Access | +| --- | --- | +| `attr_bool` or `attr_boolor` | accessor | +| `attr_bool?` | reader | +| `attr_booler` | writer | These are slightly slower due to always checking the values. @@ -172,6 +185,8 @@ These are slightly slower due to always checking the values. require 'attr_bool' class Game + extend AttrBool::Ext + attr_bool :running,'looper' attr_bool? :fps,'music' attr_booler :sound @@ -189,22 +204,22 @@ end game = Game.new() -puts game.running? # => false -puts game.looper? # => false -puts game.fps? # => true -puts game.music? # => true -puts game.loud? # => false +puts game.running? #=> false +puts game.looper? #=> false +puts game.fps? #=> true +puts game.music? #=> true +puts game.loud? #=> false game.running = true game.looper = :main game.sound = 'loud!' -puts game.running? # => true -puts game.looper? # => true -puts game.loud? # => true +puts game.running? #=> true +puts game.looper? #=> true +puts game.loud? #=> true ``` -### Using with Default [^](#contents) +### [///](#contents) Default Values A default value can be passed in, but I don't recommend using it because it's slightly slower due to always checking the value and not setting the instance variable directly. @@ -218,6 +233,8 @@ If the last argument is not a `Symbol` or a `String`, then it will be used as th require 'attr_bool' class Game + extend AttrBool::Ext + attr_accessor? :running,:looper,false attr_reader? :min_fps,:max_fps,60 @@ -227,14 +244,14 @@ end game = Game.new() -puts game.running? # => false -puts game.looper? # => false -puts game.min_fps? # => 60 -puts game.max_fps? # => 60 -puts game.gravity? # => true -puts game.wind? # => true -puts game.min_force? # => true (not 110) -puts game.max_force? # => true (not 110) +puts game.running? #=> false +puts game.looper? #=> false +puts game.min_fps? #=> 60 +puts game.max_fps? #=> 60 +puts game.gravity? #=> true +puts game.wind? #=> true +puts game.min_force? #=> true (not 110) +puts game.max_force? #=> true (not 110) ``` Instead of the last argument, you can use the `default:` keyword argument. In addition to being more clear, this allows you to pass in a `String` or a `Symbol`. @@ -243,19 +260,21 @@ Instead of the last argument, you can use the `default:` keyword argument. In ad require 'attr_bool' class Game + extend AttrBool::Ext + attr_accessor? :running,:looper,default: :main attr_reader? :music,:sound,default: 'quiet!' end game = Game.new() -puts game.running? # => :main -puts game.looper? # => :main -puts game.music? # => 'quiet!' -puts game.sound? # => 'quiet!' +puts game.running? #=> :main +puts game.looper? #=> :main +puts game.music? #=> 'quiet!' +puts game.sound? #=> 'quiet!' ``` -### Using with Block/Proc/Lambda [^](#contents) +### [///](#contents) Block/Proc/Lambda A block can be passed in for dynamic values, but I don't recommend using it. However, many Gems do this, so I also added this functionality anyway. @@ -267,6 +286,8 @@ With blocks, you can quickly write a dynamic attribute that depends on other var require 'attr_bool' class Game + extend AttrBool::Ext + attr_reader?(:lag) { print @ping,','; @ping > 300 } attr_writer?(:ping) {|value| @ping = value.to_i() } @@ -303,32 +324,80 @@ game.fps = 29.99 game.music = 'Beatles' game.frames = 1 -puts game.lag? # => 310,true -puts game.sound? # => 99,true -puts game.slow? # => 29,true -puts game.music? # => :Beatles,true -puts game.frames? # => true +puts game.lag? #=> 310,true +puts game.sound? #=> 99,true +puts game.slow? #=> 29,true +puts game.music? #=> :Beatles,true +puts game.frames? #=> true ``` -### Using with YARDoc [^](#contents) - -`attr_bool` defines some macros to help with documenting your code: +### [///](#contents) Complete Example ```Ruby -attr_accessor? :doc_acc # @!macro attach attr_accessor? -attr_reader? :doc_read # @!macro attach attr_reader? -attr_writer? :doc_write # @!macro attach attr_writer? -attr_bool :doc_bool # @!macro attach attr_bool -attr_bool? :doc_boolq # @!macro attach attr_bool? -attr_booler :doc_booler # @!macro attach attr_booler -attr_boolor :doc_boolor # @!macro attach attr_boolor +require 'attr_bool/core_ext' + +module Wearable + # +attr_accessor?/reader?+ do not enforce boolean (true or false) values. + attr_accessor? :in_fashion,:in_season + attr_reader? :can_wash,:can_wear,default: 'yes!' +end + +class BananaHammock + include Wearable + + # +attr_bool*+ enforce boolean (true or false) values. + attr_bool :princess,:prince,default: 'Consuela' + attr_bool? :can_swim,:can_wink,true + attr_bool? (:crap_bag) { princess? && can_swim? } + attr_booler :friends + + def for_friends() + @friends + end +end + +banham = BananaHammock.new() + +puts banham.in_fashion? #=> nil +puts banham.in_season? #=> nil +puts banham.can_wash? #=> 'yes!' +puts banham.can_wear? #=> 'yes!' +puts '---' + +puts banham.princess? #=> true (not 'Consuela') +puts banham.prince? #=> true (not 'Consuela') +puts banham.can_swim? #=> true +puts banham.can_wink? #=> true +puts banham.crap_bag? #=> true +puts '---' + +banham.in_fashion = true +banham.in_season = 'always' +banham.princess = nil +banham.prince = 'Charming' +banham.friends = 'Valerie' + +puts banham.in_fashion? #=> true +puts banham.in_season? #=> 'always' +puts banham.princess? #=> false (not nil) +puts banham.prince? #=> true (not 'Charming') +puts banham.crap_bag? #=> false (dynamic; because +princess?+ is now false) +puts banham.for_friends #=> true (not 'Valerie') ``` -**Note:** These do **not** currently work with multiple attributes. Instead, you should use `@!attribute` as in the example below. +### [///](#contents) YARDoc + +A custom `AttributeHandler` plugin is planned for the next version: -If you don't like the way these look, need more control, or they don't work, please use YARDoc's built-in ways: +- [Writing Handlers](https://yardoc.org/guides/extending-yard/writing-handlers.html) +- [YARD::Handlers::Ruby::AttributeHandler](https://github.com/lsegal/yard/blob/main/lib/yard/handlers/ruby/attribute_handler.rb) + +For now, please use one of YARDoc's built-in ways: ```Ruby +attr_accessor? :winning # @!attribute [rw] winning=(value),winning? +attr_reader? :running # @!attribute [r] running? + # @!attribute [r] can_swim? # @return [true,false] can you swim in it? # @!attribute [r] can_wink? @@ -369,7 +438,7 @@ Further reading: - [Tags#Macro](https://www.rubydoc.info/gems/yard/file/docs/Tags.md#macro) - [Tags#Attribute](https://www.rubydoc.info/gems/yard/file/docs/Tags.md#attribute) -## Hacking [^](#contents) +## [//](#contents) Hacking ``` $ git clone 'https://github.com/esotericpig/attr_bool.git' @@ -378,40 +447,45 @@ $ bundle install $ bundle exec rake -T ``` -### Testing - -`$ bundle exec rake test` +### Test -To test YARDoc macros, run this: - -`$ bundle exec rake doc_test` - -Then open up [doc/TestBag.html](doc/TestBag.html) & check the `doc_` methods. +``` +$ bundle exec rake test +``` -### Generating Doc +### Generate Doc -`$ bundle exec rake doc` +``` +$ bundle exec rake doc +``` -### Installing Locally +### Install Locally -`$ bundle exec rake install:local` +``` +$ bundle exec rake install:local +``` -### Releasing/Publishing +### Release -`$ bundle exec rake release` +``` +$ bundle exec rake release +``` -### Benchmarks [^](#contents) +### [///](#contents) Benchmarks There are some benchmarks that test `define_method` vs `module_eval` and `? true : false` vs `!!`. To run these on your system: -`$ bundle exec rake benchmark` +``` +$ bundle exec rake benchmark +``` -## License [^](#contents) +## [//](#contents) License [MIT](LICENSE.txt) +> AttrBool (https://github.com/esotericpig/attr_bool) > Copyright (c) 2020 Jonathan Bradley Whited (@esotericpig) > > Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/Rakefile b/Rakefile index 6611075..c322632 100644 --- a/Rakefile +++ b/Rakefile @@ -2,13 +2,13 @@ # frozen_string_literal: true #-- -# This file is part of attr_bool. +# This file is part of AttrBool. # Copyright (c) 2020 Jonathan Bradley Whited (@esotericpig) # -# attr_bool is free software: you can redistribute it and/or modify it under +# AttrBool is free software: you can redistribute it and/or modify it under # the terms of the MIT License. # -# You should have received a copy of the MIT License along with attr_bool. +# You should have received a copy of the MIT License along with AttrBool. # If not, see . #++ @@ -22,18 +22,16 @@ require 'yard' require 'attr_bool/version' - -CLEAN.exclude('.git/','stock/') +CLEAN.exclude('{.git,stock}/**/*') CLOBBER.include('doc/') - task default: [:test] -desc 'Generate doc (YARDoc)' +desc 'Generate doc' task :doc => [:yard] do |task| end -desc 'Generate doc for tests too (for checking macros)' +desc 'Generate doc for tests too' task :doc_test do |task| ENV['doctest'] = 'y' @@ -44,6 +42,7 @@ task :doc_test do |task| end Rake::TestTask.new() do |task| + task.deps << :doc_test task.libs = ['lib','test'] task.pattern = File.join('test','**','*_test.rb') task.description += ": '#{task.pattern}'" @@ -54,20 +53,15 @@ end YARD::Rake::YardocTask.new() do |task| task.files = [File.join('lib','**','*.{rb}')] - task.options += ['--files','CHANGELOG.md,LICENSE.txt'] - task.options += ['--readme','README.md'] - - task.options << '--protected' # Show protected methods #task.options += ['--template-path',File.join('yard','templates')] - task.options += ['--title',"attr_bool v#{AttrBool::VERSION} doc"] + task.options += ['--title',"AttrBool v#{AttrBool::VERSION} doc"] task.before = Proc.new() do task.files << File.join('test','**','*.{rb}') if ENV['doctest'].to_s().casecmp?('y') end end - -desc 'Benchmark define_method vs module_eval & ?: vs bangbang' +desc 'Benchmark define_method vs module_eval and ?: vs bangbang' task :benchmark do |task| N0 = 100_000 N1 = 20_000_000 diff --git a/attr_bool.gemspec b/attr_bool.gemspec index c38c26a..c8d104e 100644 --- a/attr_bool.gemspec +++ b/attr_bool.gemspec @@ -2,22 +2,18 @@ # frozen_string_literal: true #-- -# This file is part of attr_bool. +# This file is part of AttrBool. # Copyright (c) 2020 Jonathan Bradley Whited (@esotericpig) # -# attr_bool is free software: you can redistribute it and/or modify it under +# AttrBool is free software: you can redistribute it and/or modify it under # the terms of the MIT License. # -# You should have received a copy of the MIT License along with attr_bool. +# You should have received a copy of the MIT License along with AttrBool. # If not, see . #++ -lib = File.expand_path(File.join('..','lib'),__FILE__) -$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) - -require 'attr_bool/version' - +require_relative 'lib/attr_bool/version' Gem::Specification.new() do |spec| spec.name = 'attr_bool' @@ -32,22 +28,32 @@ Gem::Specification.new() do |spec| ' Default values can also be passed in.' spec.metadata = { - 'bug_tracker_uri' => 'https://github.com/esotericpig/attr_bool/issues', - 'changelog_uri' => 'https://github.com/esotericpig/attr_bool/blob/master/CHANGELOG.md', 'homepage_uri' => 'https://github.com/esotericpig/attr_bool', 'source_code_uri' => 'https://github.com/esotericpig/attr_bool', + 'bug_tracker_uri' => 'https://github.com/esotericpig/attr_bool/issues', + 'changelog_uri' => 'https://github.com/esotericpig/attr_bool/blob/master/CHANGELOG.md', } - spec.require_paths = ['lib'] + spec.required_ruby_version = '>= 2.4' + spec.require_paths = ['lib'] + + spec.files = [ + Dir.glob(File.join("{#{spec.require_paths.join(',')}}",'**','*.{erb,rb}')), + %W[ Gemfile #{spec.name}.gemspec Rakefile ], + %w[ LICENSE.txt ], + ].flatten() - spec.files = Dir.glob(File.join("{#{spec.require_paths.join(',')}}",'**','*.{rb}')) + - %W( Gemfile #{spec.name}.gemspec Rakefile ) + - %w( LICENSE.txt ) + spec.add_development_dependency 'bundler' ,'~> 2.1' + spec.add_development_dependency 'minitest' ,'~> 5.14' + spec.add_development_dependency 'rake' ,'~> 13.0' + spec.add_development_dependency 'rdoc' ,'~> 6.2' # YARDoc RDoc (*.rb) + spec.add_development_dependency 'redcarpet' ,'~> 3.5' # YARDoc Markdown (*.md) + spec.add_development_dependency 'yard' ,'~> 0.9' # Doc - spec.required_ruby_version = '>= 2.4' + spec.extra_rdoc_files = %w[ LICENSE.txt ] - spec.add_development_dependency 'bundler' ,'~> 2.1' - spec.add_development_dependency 'minitest','~> 5.14' - spec.add_development_dependency 'rake' ,'~> 13.0' - spec.add_development_dependency 'yard' ,'~> 0.9' # For doc + spec.rdoc_options = [ + '--hyperlink-all','--show-hash', + '--title',"AttrBool v#{AttrBool::VERSION} Doc", + ] end diff --git a/lib/attr_bool.rb b/lib/attr_bool.rb index d1ec666..bb00bcf 100644 --- a/lib/attr_bool.rb +++ b/lib/attr_bool.rb @@ -3,40 +3,37 @@ # frozen_string_literal: true #-- -# This file is part of attr_bool. +# This file is part of AttrBool. # Copyright (c) 2020 Jonathan Bradley Whited (@esotericpig) # -# attr_bool is free software: you can redistribute it and/or modify it under +# AttrBool is free software: you can redistribute it and/or modify it under # the terms of the MIT License. # -# You should have received a copy of the MIT License along with attr_bool. +# You should have received a copy of the MIT License along with AttrBool. # If not, see . #++ require 'attr_bool/version' - ### -# Benchmarks are kind of meaningless, but after playing around with some, -# I found the following to be the case on my system: -# - +define_method+ is faster than +module_eval+ & +class_eval+ -# - +? true : false+ (ternary operator) is faster than +!!+ (surprisingly) -# -# To run benchmark code: -# $ bundle exec rake benchmark -# # @author Jonathan Bradley Whited (@esotericpig) # @since 0.1.0 ### module AttrBool ### - # This works for both +class+ & +module+ because +class+ extends +module+. + # Benchmarks are kind of meaningless, but after playing around with some, + # I found the following to be the case on my system: + # - +define_method+ is faster than +module_eval+ & +class_eval+ + # - +? true : false+ (ternary operator) is faster than +!!+ (surprisingly) + # + # To run benchmark code: + # $ bundle exec rake benchmark # # @author Jonathan Bradley Whited (@esotericpig) - # @since 0.1.0 + # @since 0.2.0 ### - module ModuleExt + module Ext def attr_accessor?(*var_ids,default: nil,reader: nil,writer: nil,&block) if block reader = block if reader.nil?() @@ -188,40 +185,5 @@ def attr_booler(*var_ids,&block) end end end - - # @!macro attach attr_reader? - # @!method $1? - # @return [Boolean] whether +$1+ or not - - # @!macro attach attr_writer? - # @!method $1=(value) - # Sets +$1+ to +true+ or +false+. - # @param value [Boolean] the new value of +$1+ - - # @!macro attach attr_accessor? - # @!method $1? - # @!macro attach attr_reader? - # @!method $1=(value) - # @!macro attach attr_writer? - - # @!macro attach attr_bool? - # @!method $1? - # @return [true,false] whether +$1+ or not - - # @!macro attach attr_booler - # @!method $1=(value) - # Sets +$1+ to +true+ or +false+. - # @param value [true,false] the new value of +$1+ - - # @!macro attach attr_bool - # @!method $1? - # @!macro attach attr_bool? - # @!method $1=(value) - # @!macro attach attr_booler - - # @!macro attach attr_boolor - # @!macro attach attr_bool end end - -Module.prepend AttrBool::ModuleExt diff --git a/lib/attr_bool/core_ext.rb b/lib/attr_bool/core_ext.rb new file mode 100644 index 0000000..246be08 --- /dev/null +++ b/lib/attr_bool/core_ext.rb @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# encoding: UTF-8 +# frozen_string_literal: true + +#-- +# This file is part of AttrBool. +# Copyright (c) 2020 Jonathan Bradley Whited (@esotericpig) +# +# AttrBool is free software: you can redistribute it and/or modify it under +# the terms of the MIT License. +# +# You should have received a copy of the MIT License along with AttrBool. +# If not, see . +#++ + + +require 'attr_bool' + +module AttrBool + ### + # @author Jonathan Bradley Whited (@esotericpig) + # @since 0.2.0 + ### + module CoreExt + end +end + +# This works for both +class+ & +module+ because +class+ extends +module+. +Module.prepend AttrBool::Ext diff --git a/lib/attr_bool/version.rb b/lib/attr_bool/version.rb index 31ea795..25c1445 100644 --- a/lib/attr_bool/version.rb +++ b/lib/attr_bool/version.rb @@ -3,17 +3,17 @@ # frozen_string_literal: true #-- -# This file is part of attr_bool. +# This file is part of AttrBool. # Copyright (c) 2020 Jonathan Bradley Whited (@esotericpig) # -# attr_bool is free software: you can redistribute it and/or modify it under +# AttrBool is free software: you can redistribute it and/or modify it under # the terms of the MIT License. # -# You should have received a copy of the MIT License along with attr_bool. +# You should have received a copy of the MIT License along with AttrBool. # If not, see . #++ module AttrBool - VERSION = '0.1.0' + VERSION = '0.2.0' end diff --git a/test/attr_bool_test.rb b/test/attr_bool_test.rb index 28bfef6..760b7fa 100644 --- a/test/attr_bool_test.rb +++ b/test/attr_bool_test.rb @@ -3,122 +3,26 @@ # frozen_string_literal: true #-- -# This file is part of attr_bool. +# This file is part of AttrBool. # Copyright (c) 2020 Jonathan Bradley Whited (@esotericpig) # -# attr_bool is free software: you can redistribute it and/or modify it under +# AttrBool is free software: you can redistribute it and/or modify it under # the terms of the MIT License. # -# You should have received a copy of the MIT License along with attr_bool. +# You should have received a copy of the MIT License along with AttrBool. # If not, see . #++ -require 'minitest/autorun' +require 'test_helper' require 'attr_bool' - -### -# Test +doc_*+ vars with: -# $ bundle exec rake doc_test -# $ xdg-open doc/TestBag.html -# -# @author Jonathan Bradley Whited (@esotericpig) -# @since 0.1.0 -### -class TestBag - attr_accessor :hidden - - def initialize() - @hidden = 0 - - @acc = nil - @acc5 = nil - @acc6 = nil - @acc15 = nil - @acc16 = nil - @acc17 = nil - end - - attr_accessor? :doc_acc # @!macro attach attr_accessor? - attr_reader? :doc_read # @!macro attach attr_reader? - attr_writer? :doc_write # @!macro attach attr_writer? - attr_bool :doc_bool # @!macro attach attr_bool - attr_bool? :doc_boolq # @!macro attach attr_bool? - attr_booler :doc_booler # @!macro attach attr_booler - attr_boolor :doc_boolor # @!macro attach attr_boolor - - attr_accessor? :acc - attr_accessor? :acc1,1 - attr_accessor? :acc2,default: 2 - attr_accessor?(:acc3, - reader: lambda { @acc3.odd?() }, - writer: lambda {|value| @acc3 = value + 1} - ) - attr_accessor?(:acc4) do |value=nil| - @acc4 = value + 1 unless value.nil?() - @acc4.odd?() - end - - attr_accessor? :acc5 ,:acc6 - attr_accessor? :acc7 ,:acc8,78 - attr_accessor? :acc9 ,:acc10,default: 910 - attr_accessor?(:acc11,:acc12, - reader: lambda { @hidden.odd?() }, - writer: lambda {|value| @hidden = value + 1} - ) - attr_accessor?(:acc13,:acc14) do |value=nil| - @hidden = value + 1 unless value.nil?() - @hidden.odd?() - end - - attr_accessor? 'acc15' - attr_accessor? 'acc16','acc17' - attr_accessor? 'acc18',default: 'str' - attr_accessor? 'acc19','acc20',default: 'str' - attr_accessor? 'acc21',default: :sym - attr_accessor? 'acc22','acc23',default: :sym - - attr_bool :boo - attr_bool :boo1,1 - attr_bool :boo2,default: 2 - attr_bool(:boo3, - reader: lambda { @boo3.odd?() }, - writer: lambda {|value| @boo3 = value + 1} - ) - attr_bool(:boo4) do |value=nil| - @boo4 = value + 1 unless value.nil?() - @boo4.odd?() - end - - attr_bool :boo5 ,:boo6 - attr_bool :boo7 ,:boo8,78 - attr_bool :boo9 ,:boo10,default: 910 - attr_bool(:boo11,:boo12, - reader: lambda { @hidden.odd?() }, - writer: lambda {|value| @hidden = value + 1} - ) - attr_bool(:boo13,:boo14) do |value=nil| - @hidden = value + 1 unless value.nil?() - @hidden.odd?() - end - - attr_bool 'boo15' - attr_bool 'boo16','boo17' - attr_bool 'boo18',default: 'str' - attr_bool 'boo19','boo20',default: 'str' - attr_bool 'boo21',default: :sym - attr_bool 'boo22','boo23',default: :sym - - attr_boolor :bor -end - ### # @author Jonathan Bradley Whited (@esotericpig) # @since 0.1.0 ### -class AttrBoolTest < Minitest::Test +class AttrBoolTest < TestHelper def setup() @bag = TestBag.new() end @@ -243,4 +147,89 @@ def test_attr_boolor() @bag.bor = true assert_equal true,@bag.bor?() end + + ### + # @author Jonathan Bradley Whited (@esotericpig) + # @since 0.2.0 + ### + class TestBag + extend AttrBool::Ext + + attr_accessor :hidden + + def initialize() + @hidden = 0 + + @acc = nil + @acc5 = nil + @acc6 = nil + @acc15 = nil + @acc16 = nil + @acc17 = nil + end + + attr_accessor? :acc + attr_accessor? :acc1,1 + attr_accessor? :acc2,default: 2 + attr_accessor?(:acc3, + reader: lambda { @acc3.odd?() }, + writer: lambda {|value| @acc3 = value + 1} + ) + attr_accessor?(:acc4) do |value=nil| + @acc4 = value + 1 unless value.nil?() + @acc4.odd?() + end + + attr_accessor? :acc5 ,:acc6 + attr_accessor? :acc7 ,:acc8,78 + attr_accessor? :acc9 ,:acc10,default: 910 + attr_accessor?(:acc11,:acc12, + reader: lambda { @hidden.odd?() }, + writer: lambda {|value| @hidden = value + 1} + ) + attr_accessor?(:acc13,:acc14) do |value=nil| + @hidden = value + 1 unless value.nil?() + @hidden.odd?() + end + + attr_accessor? 'acc15' + attr_accessor? 'acc16','acc17' + attr_accessor? 'acc18',default: 'str' + attr_accessor? 'acc19','acc20',default: 'str' + attr_accessor? 'acc21',default: :sym + attr_accessor? 'acc22','acc23',default: :sym + + attr_bool :boo + attr_bool :boo1,1 + attr_bool :boo2,default: 2 + attr_bool(:boo3, + reader: lambda { @boo3.odd?() }, + writer: lambda {|value| @boo3 = value + 1} + ) + attr_bool(:boo4) do |value=nil| + @boo4 = value + 1 unless value.nil?() + @boo4.odd?() + end + + attr_bool :boo5 ,:boo6 + attr_bool :boo7 ,:boo8,78 + attr_bool :boo9 ,:boo10,default: 910 + attr_bool(:boo11,:boo12, + reader: lambda { @hidden.odd?() }, + writer: lambda {|value| @hidden = value + 1} + ) + attr_bool(:boo13,:boo14) do |value=nil| + @hidden = value + 1 unless value.nil?() + @hidden.odd?() + end + + attr_bool 'boo15' + attr_bool 'boo16','boo17' + attr_bool 'boo18',default: 'str' + attr_bool 'boo19','boo20',default: 'str' + attr_bool 'boo21',default: :sym + attr_bool 'boo22','boo23',default: :sym + + attr_boolor :bor + end end diff --git a/test/core_ext_test.rb b/test/core_ext_test.rb new file mode 100644 index 0000000..7a4d6d2 --- /dev/null +++ b/test/core_ext_test.rb @@ -0,0 +1,57 @@ +#!/usr/bin/env ruby +# encoding: UTF-8 +# frozen_string_literal: true + +#-- +# This file is part of AttrBool. +# Copyright (c) 2020 Jonathan Bradley Whited (@esotericpig) +# +# AttrBool is free software: you can redistribute it and/or modify it under +# the terms of the MIT License. +# +# You should have received a copy of the MIT License along with AttrBool. +# If not, see . +#++ + + +require 'test_helper' + +require 'attr_bool/core_ext' + +### +# @author Jonathan Bradley Whited (@esotericpig) +# @since 0.2.0 +### +class CoreExtTest < TestHelper + def setup() + @bag = TestBag.new() + end + + def test_core_ext() + @bag.acc = true + @bag.write = true + @bag.bool = true + @bag.booler = true + @bag.boolor = true + + assert_equal true ,@bag.acc?() + assert_nil @bag.read?() + assert_equal true ,@bag.bool?() + assert_equal false,@bag.boolq?() + assert_equal true ,@bag.boolor?() + end + + ### + # @author Jonathan Bradley Whited (@esotericpig) + # @since 0.2.0 + ### + class TestBag + attr_accessor? :acc + attr_reader? :read + attr_writer? :write + attr_bool :bool + attr_bool? :boolq + attr_booler :booler + attr_boolor :boolor + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000..3955614 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,24 @@ +#!/usr/bin/env ruby +# encoding: UTF-8 +# frozen_string_literal: true + +#-- +# This file is part of AttrBool. +# Copyright (c) 2020 Jonathan Bradley Whited (@esotericpig) +# +# AttrBool is free software: you can redistribute it and/or modify it under +# the terms of the MIT License. +# +# You should have received a copy of the MIT License along with AttrBool. +# If not, see . +#++ + + +require 'minitest/autorun' + +### +# @author Jonathan Bradley Whited (@esotericpig) +# @since 0.2.0 +### +class TestHelper < Minitest::Test +end