✨ Magic Support
Magic Support is a collection of utility classes and standard library extensions that were found useful for my pet projects.
It’s inspired by Active Support.
Installation
TODO: Replace UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
Install the gem and add to the application's Gemfile by executing:
bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
If bundler is not being used to manage dependencies, install the gem by executing:
gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
Core extensions
Loading
Magic Support is broken into small pieces so that only the desired extensions can be loaded. It also has some convenience entry points to load related extensions in one shot, even all of them.
Cherry-picking
For every single method defined as a core extension a note says where such a method is defined.
That means that you can require
it like this:
require 'magic/core_ext/<module>/<extension>'
Magic Support has been carefully revised so that cherry-picking a file loads only strictly needed dependencies, if any.
Loading grouped core extensions
As a rule of thumb, extensions to SomeClass
are available in
one shot by loading magic/core_ext/some_class
.
Thus, to load all extensions to Kernel
:
require 'magic/core_ext/kernel'
Loading all core extensions
You may prefer just to load all core extensions, there is a file for that:
require 'magic/core_ext'
Extensions to all objects
#optional
Yields self to the block and returns the result of the block if it’s truthy, and self otherwise.
rand(6) # returns 0–5
.optional { it + 1 if one_based? } # returns 1–6 if 1-based, or
# the original 0–5 otherwise
It can be considered as a conditional #then
.
Good usage for #optional
is value piping in method chains with conditional processing:
@people = Person
.optional { it.where created_at: (1.hour.ago...) if new? }
.optional { anonymize it if gdpr? }
.optional { try :decorate }
Defined in core_ext/kernel/optional
.
Gems
Author
It holds authors info to be used primarily in gem specs.
Loading
Pre-install Magic Support if you plan to use Gem::Author
in your gemspec.
gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
Usage
Inherit
Gem::Author
inside your gem and add the authors’ info.require 'rubygems/author' module MyLib class Author < Gem::Author new( name: 'Your Name', email: '[email protected]', github: 'Your-GitHub-Username', ) end end
You can call some helper methods now.
Gem::Specification.new do |spec| spec.name = 'my_lib' spec.version = MyLib::VERSION spec. = MyLib::Author.names spec.email = MyLib::Author.emails spec.homepage = "#{MyLib::Author.github_url}/#{spec.name}" end
RSpec
Method specs
Enables one to write specs for single methods.
[!WARNING] Planed for extraction into a separate gem.
Loading
Require it in spec_helper.rb
:
require 'rspec/method'
Usage
Include a method reference into the description. The reference should start with either
.
for class methods or#
for instance ones.
RSpec.describe MyClass do
describe '.class_method' do
its([arg1, arg2]) { is_expected.to be return_value }
end
describe '#instance_method' do
its([arg1, arg2]) { is_expected.to be return_value }
end
end
[!NOTE] Though
rspec/its
is not needed, it could come useful (see the article on method testing).
Within examples, subject
is set to the corresponding Method
instance.
In cases when the method couldn’t be found (e.g., due to delegation via method_missing
), it’s set to a Proc
instance
instead.
Anyway, one may treat it as something callable.
A method name is exposed as a Symbol
via method_name
.
[!NOTE]
subject.name
may be undefined, usemethod_name
instead.
Delegated methods
One can use it_behaves_like :delegated
for delegated methods.
This will ensure that calling the method calls the one of the same name on a delegate under the hood passing it the arguments.
RSpec.describe MyClass do
describe '#method_with_arguments' do
it_behaves_like :delegated, to: delegate, with: [arg1, arg2]
end
describe '#method_without_arguments' do
it_behaves_like :delegated, to: delegate
end
end
Module specs
It’s recommended to use class method notation, when writing specs for module functions.
RSpec.describe MyModule do
describe '.module_function' do
# put the examples here
end
end
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and the created tag, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/Alexander-Senko/magic-support. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
License
The gem is available as open source under the terms of the MIT License.
Code of Conduct
Everyone interacting in the Magic::Support project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.