JunkDrawer is a gem providing a handful of random utility that are commonly
useful across projects.
Add this line to your application's Gemfile:
gem 'junk_drawer'And then execute:
$ bundle
Or install it yourself as:
$ gem install junk_drawer
If you want to include the Rails utilities, in your Gemfile you can instead use:
gem 'junk_drawer', require: 'junk_drawer/rails'JunkDrawer::Callable is a module that provides constraints and conveniences
for objects that implement a single method #call. It comes with the
philosophy that objects that do something, should do only one thing. When
including the JunkDrawer::Callable in one of your classes, you will get the
following:
- It raises an error if you try to implement a public method other than
#call.
class Foo
include JunkDrawer::Callable
def bar # Bad: can't define public method "#bar"
end
endproduces:
JunkDrawer::CallableError: invalid method name bar, only public method allowed is "call"
Private methods are fine:
class Foo
include JunkDrawer::Callable
private
def bar # private methods are okay!
end
end- It delegates
callon the class to a new instance:
class Foo
include JunkDrawer::Callable
def call(stuff)
puts "I am a Foo! I've got #{stuff}"
end
end> Foo.call('a brochure')
I am a Foo! I've got a brochure
> Foo.new.call('a brochure')
I am a Foo! I've got a brochure
- It implements
to_proc, both on the class and instance, allowing operations such as:
> ['puppies', 'a cold', 'cheeseburgers'].each(&Foo)
I am a Foo! I've got puppies
I am a Foo! I've got a cold
I am a Foo! I've got cheeseburgers
See here for a great explanation of to_proc and the & operator:
http://www.brianstorti.com/understanding-ruby-idiom-map-with-symbol/
JunkDrawer::Notifier is a class that provides simple notification strategies
for different environments. When you call it, it will send a notification via
your selected strategy. The strategies available are as follows:
:raiseraises an error when you call the notifier:
JunkDrawer::Notifier.strategy = :raise
JunkDrawer::Notifier.call('some message', some: 'context')produces:
JunkDrawer::NotifierError: some message, context: {:some=>"context"}
-
:honeybadgerwill send a notification to Honeybadger. You'll need to make sure you have Honeybadger required in your application and configured for this to work. -
:nullis a noop. If you want to disable notifications temporarily, you can configure the strategy to:null. -
To create your own custom notifier, configure
JunkDrawer::Notifierwith a callable object as the strategy.
class MyNotifier
include JunkDrawer::Callable
def call(*args)
SomeMonitoringService.notify(*args)
end
end
JunkDrawer::Notifier.strategy = MyNotifierJunkDrawer::Notifier.strategy = ->(*args) {
MonitoringServiceA.notify(*args)
MonitoringServiceB.notify(*args)
}If you're using Rails, you may want to configure Notifier based on the
environment, so in your config/environments/development.rb you might have:
config.after_initialize do
JunkDrawer::Notifier.strategy = :raise
endWhile in production.rb you might want:
config.after_initialize do
JunkDrawer::Notifier.strategy = :honeybadger
endFor Rails specific tools, instead of requiring 'junk_drawer', you can require
'junk_drawer/rails'. This will pull in both the plain Ruby and the Rails
specific utilities.
JunkDrawer::BulkUpdatable is a utility to enable bulk updating of
ActiveRecord models. To enable it, extend in your models:
class MyModel < ApplicationRecord
extend JunkDrawer::BulkUpdatable
endIf you want to enable it for all models, you can also add it to your
ApplicationModel class:
class ApplicationRecord
self.abstract_class = true
extend JunkDrawer::BulkUpdatable
endTo make use of it, you can pass an array of records into the .bulk_update
class method on your model:
my_model_1 = MyModel.find(1)
my_model_1.name = 'Jabba'
my_model_2 = MyModel.find(2)
my_model_2.name = 'JarJar'
MyModel.bulk_update([my_model_1, my_model_2])This will generate a single SQL query to update both of the records in the
database. If prepared_statements is set to true, BulkUpdatable will generate
queries that use bind parameters.
-
Right now this only supports PostgreSQL. PR's welcome!
-
It also only supports basic data types (including
hstoreandjsonb) for your columns, so if you've got something weird you may have a bad time. Also PR's welcome! -
General advice: if you're updating many thousands of records at the same time, you may still run into some performance bottlenecks. When you're dealing with massive amounts of data, we suggest pairing
JunkDrawer::BulkUpdatablewith Rails' built-infind_in_batches:MyModel.find_in_batches(batch_size: 250) do |batch| batch.each { |my_model| my_model.name = 'Jar' * rand(100) } MyModel.bulk_update(batch) end
After checking out the repo, run bin/setup to install dependencies. Then, run
rake spec to run the tests, or bin/test to run tests for all supported
ActiveRecord versions. 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 tags, and push the .gem file to rubygems.org.
In order to run tests against different Rails versions, you can use
BUNDLE_GEMFILE:
$ BUNDLE_GEMFILE=gemfiles/rails_7.0.gems rake specBug reports and pull requests are welcome on GitHub at https://github.com/thread-pond/junk_drawer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
The gem is available as open source under the terms of the MIT License.