Justools (formerly CoreUtilities)

Ruby-level extensions, utilities, convenience methods that I’ve found I’m constantly using in all my projects.

Usage:

gem 'justools', :git => "git://github.com/caleon/justools.git"

Selected Examples:

Object

Object#as

[:donkey, { :class => 'list-item' }].as { |arg, opts| link_to(arg, opts) }

Object#is_included_in? (deprecated by ActiveSupport’s newest Object#in?)

User.find(1).class.is_included_in?(User, Article, Authentication)

or alternatively:

@user.is_one_kind_of?(User, Article, Authentication)

which has the same effect as:

@user.is_one_kind_of?([User, Article, Authentication])

by virtue of:

Array

Array#flatten_splat!

#flatten_splat is for the common pattern of writing a method whose arguments are prepended by the splat operator, like the following:

def find(*types)
  types = types.first if types.size == 1 and types.first.is_a?(Array)
  # ...
end

… which can now be written as:

def find(*types)
  types.flatten_splat!
end

array/base, array/filters

These contain further convenience methods, none of them really novel or anything.

Array#extract_options(!)

Extending the behavior introduced by ActiveSupport, this one goes further to define Array#extract_options as the non-destructive analog, and also introduces Array#extract_options_with_merge. Previously you may have written:

def find(*args)
  opts = args.extract_options!
  opts[:user_id] = self.article.user_id
  opts[:found_at] = Time.now
end

but now you can write:

def find(*args)
  opts = args.extract_options_with_merge(:user_id => self.article.user_id, :found_at => Time.now)
end

Note: The inclusion of this gem makes the *_with_merge methods the default behavior for extract_options(!) via alias_method_chain.

Array#merge_options(!)

If you find yourself extracting options as above only to re-inject that hash back into the original array to pass the arguments to a helper method (after some merging of the options hash), you may consider utilizing #merge_options:

def find(*args)
  find_helper(*args.merge_options(:user_id => self.article.user_id, :found_at => Time.now))
end

Array #arguments_and_options (a.k.a. #args_and_opts)

The above Array methods lead to this handy method whose utility, in essence, is in its shortening a common Ruby pattern into a single line. Previously you may have written:

def find(*arguments)
  mandatory_opts = { :user_id => self.article.user_id, :found_at => Time.now }

  opts = arguments.extract_options!
  an_id = arguments.shift

  opts.merge!(mandatory_opts)
end

which, with the help of #args_and_opts (and the help of of #method_missing for extending its functionality) you can write:

def find(*arguments)
  an_id, opts = arguments.args_with_shift_and_opts_with_merge!(:user_id => self.article.user_id, :found_at => Time.now)
end

Note

The method_missing hook to allow the above functionality (explained in more detail below) is only available for Ruby 1.9+ because it depends, to an extent, on the availability of the method Method#parameters.

Basically the format of the method call is arg(ument)?s(_with_)?_and_opt(ion)?s(_with_)?!, where the ARGMETHOD is the name of the method which applies to the “args” part of the array, and OPTSMETHOD would be the name of the method which is called on the “opts” part of the array.

Additionally, arguments can be passed to #args_and_opts, but as of now, in the event that both ARGMETHOD and OPTSMETHOD are defined, the arguments will be passed to the OPTSMETHOD only. Some effort was made to utilize arity to determine where the arguments should be passed to, but to my recollection this is still an unfinished aspect.

Enumerable

Has #map_select and #map_detect.

Set

Has #not_subset?(set)

Hash

Has #append_value which is similar to merging hashes, but in cases where you don’t want to override the value of one of the hashes and would rather JOIN the values corresponding to the same key, (for example, wanting to add class names in a DOM element in Rails rather than overriding the original { :class => ‘className’ } hash):

{ :id => "user_1-comments", :class => "user-comments" }.append_value!(:class, 'comments')
# => { :id => "user_1-comments", :class => "user-comments comments" }

Additional information

Contributors

Please feel free to contact me about collaborating on this project.

github.com/caleon/justools/contributors

Maintainers

License

MIT License. Copyright 2012 caleon.