Zucker (pronunciation) is the German word for sugar. It adds syntactic sugar in the form of independent, small scripts that make Ruby even more sweet. It adds a lot of useful helper methods for an improved readability and usage of your every-day Ruby code. Almost every Zucker feature comes with specs. Everything is documented on this page. The source is available at github.
gem install zucker --no-rdoc --no-ri # might need sudo
require 'zucker/all'
The gem consists of many small snippets, called cubes, which are bundled in packs. Since there aren't any dependencies within the gem, you can easily require only the packs or cubes you want:
require 'zucker/cube_or_pack_name'
Object.to_proc extensions to use with &.Furthermore, there are two meta packs available: all simply requires all cubes and default requires all cubes except debug.
Info, RubyVersion, RubyEngine, OS, Infinity, NaN, alias_for, aliases_for, egonil, nn, iterate, instance_variables_from, ivars, activate_warnings!, deactivate_warnings!, executed_directly?, directly_executed?, standalone?, library?, ignore_sigint!, ignore_sigquit!, sandbox, tap_on, make_new, (blank?, present?, mcopy)
| Summary | Creates a block, where nil does not raise NoMethodErrors. |
|---|---|
| Methods/Usage | egonil, nnegonil do nil.some_methods.that[:do].not.exist end # => nil nn{ nil.some_methods.that[:do].not.exist } # => nil |
| Information | See this post for more information and discussion. |
| Specification | (show)
require 'zucker/egonil' describe 'egonil' do it 'should not raise nil exceptions in the block' do proc do egonil{ nil.some_methods.that[:do].not.exist } end.should_not raise_exception end it 'should restore default behaviour after the block' do proc do egonil{ nil.some_methods.that[:do].not.exist } end.should_not raise_exception proc do nil.a_method end.should raise_exception NoMethodError end it 'raise NoMethodError for non-nil objects' do proc do egonil{ 5.a_method } end.should raise_exception NoMethodError end it 'should raise other Exceptions' do proc do egonil{ 5 / 0 } end.should raise_exception ZeroDivisionError end end |
| Source | (show)
require 'zucker' module Zucker Egonil = true end # code by Yohan, slightly edited and comments by me def egonil(&block) # grip methods ori_method_missing = NilClass.instance_method(:method_missing) catch_method_missing = NilClass.instance_method(:catch_method_missing) # activate ego mode NilClass.send :define_method, :method_missing, catch_method_missing # run code yield ensure # no matter what happens: restore default nil behaviour NilClass.send :define_method, :method_missing, ori_method_missing end # this is the ego nil class NilClass def catch_method_missing(m, *args, &block) nil end end alias nn egonil # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Iterate over one or more collections. |
|---|---|
| Why? | It's like .each with two differences: It feels more like a control structure and you can easily iterate over multiple objects. |
| Methods/Usage | iterateiterate [1,2], [3,4,5] do |e,f| puts "#{e},#{f}" end # outputs # 1,3 # 2,4 # ,5 |
| Specification | (show)
require 'zucker/iterate' describe 'Object#iterate' do let :a do [1, 2, 3] end let :b do %w|a b c d| end let :res do Hash.new {[]} end it 'should behave like Enumerable#each for a single argument' do iterate a do |ele| res[:iter] << ele end a.each do |ele| res[:each] << ele end res[:iter].should == res[:each] end it 'should pass the right params to the block' do res = Hash.new {[]} # TODO: why? res[:iter_a_b] = [] # .... res[:iter_b_a] = [] # .... iterate a, b do |e,f| res[:iter_a_b] << [e, f] end res[:iter_a_b].should == [ [1, 'a'], [2, 'b'], [3, 'c'], [nil, 'd'], ] iterate b, a do |e,f| res[:iter_b_a] << [e, f] end res[:iter_b_a].should == [ ['a', 1], ['b', 2], ['c', 3], ['d', nil], ] end it 'should return enumerators if no block is applied' do res = Hash.new {[]} # TODO: why? res[:iter_a_b] = [] # .... res[:iter_b_a] = [] # .... enumerator = iterate a,b enumerator.should be_kind_of(RUBY_VERSION < '1.9' ? Enumerable::Enumerator : Enumerator) enumerator.to_a.should == [[1,'a'], [2,'b'], [3,'c'], [nil, 'd']] end end |
| Source | (show)
require 'zucker' module Zucker Iterate = true end def iterate(*params) # params.shift.zip(*params).each{ |*elements| yield *elements } raise ArgumentError, "wrong number of arguments (0)" if params.empty? first = params.shift if params.empty? # single param - like each if block_given? first.map{|e| yield e } else first.map.to_enum end else # multiple params max_size = [first, *params].max_by(&:count).size padded_first = first.to_a + [nil]*(max_size - first.count) # append nils obj = padded_first.zip(*params) if block_given? obj.map{|es| yield(*es) } else obj.map.to_enum end end end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Some useful general shortcut methods. |
|---|---|
| Why? | Readability. |
| Methods/Usage | activate_warnings!activate_warnings! # sets $VERBOSE to 1deactivate_warnings!deactivate_warnings! # sets $VERBOSE to 0executed_directly?, directly_executed?, standalone?executed_directly? # checks, if the current file is run directly -> truelibrary?library? # checks, if the current file is run directly -> falseirb?irb? # returns false if not called from IRB or RIPLignore_sigint!ignore_sigint! # blocks CTRL+Cignore_sigquit!ignore_sigquit! # blocks CTRL+\ |
| Specification | (show)
require 'zucker/kernel' describe 'activate_warnings!' do it 'should set $VERBOSE to true' do activate_warnings! $VERBOSE.should == true end end describe 'deactivate_warnings!' do it 'should set $VERBOSE to false' do deactivate_warnings! $VERBOSE.should == false end end describe 'library?' do it 'should return false if the file is invoked directly' do library?.should == ( __FILE__ != $PROGRAM_NAME ) end end describe 'executed_directly?' do it 'should return true if the file is invoked directly' do executed_directly?.should == ( __FILE__ == $PROGRAM_NAME ) end end describe 'irb?' do it 'should return true if called in IRB or RIPL' do; end end describe 'ignore_sigint!' do it 'should catch ctrl+c signals' do; end end describe 'ignore_sigquit!' do it 'should catch ctrl+\ signals' do; end end # J-_-L |
| Source | (show)
require 'zucker' module Zucker Kernel = true end module Kernel private def activate_warnings! $VERBOSE = true end def deactivate_warnings! $VERBOSE = false end def library? caller[0].rindex(/:\d+(:in `.*')?$/) $PROGRAM_NAME != $` # __FILE__ end def executed_directly? caller[0].rindex(/:\d+(:in `.*')?$/) $PROGRAM_NAME == $` # __FILE__ end alias standalone? executed_directly? alias directly_executed? executed_directly? def irb? (defined?(IRB) && $0 =~ /irb/) || (defined?(Ripl) && $0 =~ /ripl/) end def ignore_sigint! # ctrl+c Signal.trap(*%w|SIGINT IGNORE|) true end def ignore_sigquit! # ctrl+\ Signal.trap(*%w|SIGQUIT IGNORE|) true end end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Creates a sandbox area. |
|---|---|
| Why? | Ruby comes with sandboxes, but they are hidden (-> integrated) in the $SAFE concept. |
| Methods/Usage | sandboxsandbox do # dangerous commands throw SecurityErrors ($SAFE=4) end # everything's normal again |
| Specification | (show)
require 'zucker/sandbox' describe 'sandbox' do unless defined?(RUBY_ENGINE) && ( RUBY_ENGINE == 'jruby' || RUBY_ENGINE == 'rbx' ) it 'should throw a SecurityError if bad commands are issued' do proc do sandbox do `ls` end end.should raise_exception SecurityError end end end |
| Source | (show)
require 'zucker' module Zucker Sandbox = true end module Kernel private def sandbox warn "zucker: sandbox does not work in rbx and jruby" if defined?(RUBY_ENGINE) && ( RUBY_ENGINE == 'jruby' || RUBY_ENGINE == 'rbx' ) Thread.start do $SAFE = 4 yield end.value end end # J-_-L |
| Compatibility | 1.9, 1.8, Does not work on JRuby, since $SAFE is not supported there |
| Discussion | github wiki |
| Summary | This cube adds the two tap variants tap_on (known as returning in ActiveSupport) and make_new. |
|---|---|
| Methods/Usage | tap_ontap_on [1,2] do |obj| obj[4] = 5 end #=> [1, 2, nil, nil, 5] make_newmake_new Hash do |obj| obj[1] = 2 end #=> {1 => 2} |
| Information | Read more about using tap on the ruby best practices blog. |
| Specification | (show)
require 'zucker/tap' describe 'tap_on' do it 'should call tap on the argument and apply the block' do obj = "an_object" block = :reverse.to_proc tap_on( obj, &block ).should == obj.tap( &block ) end end describe 'make_new' do it 'should create a new instance of the class given as argument, apply the block on it and return result' do make_new Hash do |obj| obj[1] = 2 end.should.send(:'==', { 1 => 2}) end end |
| Source | (show)
require 'zucker' module Zucker Tap = true end def tap_on(obj, &block) obj.tap(&block) end def make_new(what, *args, &block) what.new(*args).tap(&block) end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Adds a RubyEngine class for easy compatibility checks. |
|---|---|
| Methods/Usage | RubyEngine# outputs the interpreter nameRubyEngine.mri?RubyEngine.mri? # true if using the official Ruby interpreter RubyEngine.jruby?RubyEngine.jruby? # true if using JRuby RubyEngine.rubinius?RubyEngine.rubinius? # true if using rubinius RubyEngine.ree?RubyEngine.ree? # true if using enterprise edition RubyEngine.ironruby?RubyEngine.ironruby? # true if using IronRuby RubyEngine.macruby?RubyEngine.macruby? # true if using MacRuby RubyEngine.cardinal?RubyEngine.cardinal? # true if using parrot |
| Specification | (show)
require 'zucker/engine' describe 'RubyEngine' do it 'should display the current ruby interpreter (to_s)' do RubyEngine end it 'should create many method aliases for asking for a specific interpreter' do # please see the source or description file end end |
| Source | (show)
require 'zucker' module Zucker Engine = true end module RubyEngine # try to guess the interpreter @interpreter = case when RUBY_PLATFORM == 'parrot' 'cardinal' when Object.const_defined?(:RUBY_ENGINE) if RUBY_ENGINE == 'ruby' if RUBY_DESCRIPTION =~ /Enterprise/ 'ree' else 'mri' end else RUBY_ENGINE.to_s # jruby, rbx, ironruby, macruby, etc. end else # probably 1.8 'mri' end class << self def is?(what) what === @interpreter end alias is is? def to_s @interpreter.to_s end # ask methods def mri? RubyEngine.is? 'mri' end alias official_ruby? mri? alias ruby? mri? def jruby? RubyEngine.is? 'jruby' end alias java? jruby? def rubinius? RubyEngine.is? 'rbx' end alias rbx? rubinius? def ree? RubyEngine.is? 'ree' end alias enterprise? ree? def ironruby? RubyEngine.is? 'ironruby' end alias iron_ruby? ironruby? def cardinal? RubyEngine.is? 'cardinal' end alias parrot? cardinal? alias perl? cardinal? end end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Access environment information with the Info module. |
|---|---|
| Why? | You don't need to remember in which global variable, constant or special method the information you are searching for is hidden. |
| Methods/Usage | Info# for example Info.working_directory # Dir.pwd Info.load_path # $: Info.platform # RUBY_PLATFORM Info.current_file # similar to __FILE__ # you could also add them to the global namespace with: include Info # see the source file for the list of accessors or Info.list |
| Information | Please note that it is not possible to put some of __THOSE_KEYWORDS__ in methods, so the result might slightly differ. This might affect current_file, current_file_directory, current_line and current_method.Thanks to Facets for the caller Regexp. |
| Specification | (show)
require 'zucker/info' describe 'Info' do it 'should define accessors for global variables, constants and some special methods/keywords' do # see sourcefile for the list end end |
| Source | (show)
require 'zucker' require 'rbconfig' require 'etc' module Zucker Info = true end module Info class << self # hash like access def [](what) send what end # list available info methods def list singleton_methods - [:[], :list, '[]', 'list'] end end module_function # input def last_input_file $FILENAME end def last_input_line_number $. end def last_input $_ end # program def program_name $0 end def program_arguments $: end def loaded_programs $" end def program_data ::DATA end def child_program_status $CHILD_STATUS end # system info def environment ::ENV end alias env environment def working_directory Dir.pwd end def platform ::RUBY_PLATFORM end def os RbConfig::CONFIG['host_os'] end def process_id $$ end def load_path $: end # user def user_login Etc.getlogin end def user_name Etc.getpwnam(user_login).gecos.split(',')[0] end # current def current_file # __FILE__ return $` if caller[0].rindex(/:\d+(:in `.*')?$/) end def current_file_directory if current_file[0,1] == '(' && current_file[-1,1] == ')' current_file else File.dirname(current_file) end end def current_line # __LINE__ return $1.to_i if caller[0].rindex( /:(\d+)(:in `.*')?$/ ) end def current_method # __method__ (except aliases) return $1.to_sym if caller(1)[0].rindex( /\`([^\']+)\'/ ) end def current_callstack caller end # dealing with strings def gets_separator $/ end def join_separator $, end def print_separator $, end def split_separator $; end # misc def security_level $SAFE end def warnings_activated? $VERBOSE end def debug_activated? $DEBUG end def last_exception $! end # defined objects def global_variables Object.send :global_variables end def global_constants Object.constants end # encoding (1.9) #def source_encoding # __ENCODING__ #end def external_encoding Encoding.default_external end def internal_encoding Encoding.default_internal end # ruby version info def ruby_version # also see the RubyVersion cube ::RUBY_VERSION end def ruby_patchlevel ::RUBY_PATCHLEVEL end def ruby_description ::RUBY_DESCRIPTION end def ruby_release_date ::RUBY_RELEASE_DATE end def ruby_engine # warning! not support by every implementation. It's saver to use the RubyEngine cube ::RUBY_ENGINE end end |
| Compatibility | 1.9, 1.8 (not all information) |
| Discussion | github wiki |
| Summary | Detect the operating system. |
|---|---|
| Why? | Checking for RUBY_PLATFORM does not report the OS when using JRuby and for better readability. |
| Methods/Usage | OS# displays the operating systemOS.linux?OS.linux? # true if you are on a linux machine OS.mac?OS.mac? # true for macs OS.bsd?OS.bsd? # true for bsds OS.windows?include OS; windows? # true for windows. Example of including OS to get the os methods into the global namespace OS.solaris?OS.solaris? # true for solaris/sunos OS.posix?OS.posix? # true if system is posix compatible OS.is?OS.is? /x/ # matches the regex against the os string |
| Information | This cube depends on system information and may not be 100% accurate. Syntax and semantic inspired by Roger Pack's os gem. |
| Specification | (show)
require 'zucker/os' describe 'OS' do it 'should display the used operation system (to_s)' do; end end describe 'linux?' do it 'should return true if OS is a linux' do; end end describe 'mac?' do it 'should return true if OS is a mac or darwin' do; end end describe 'bsd?' do it 'should return true if OS is a bsd' do; end end describe 'windows?' do it 'should return true if OS is a windows' do; end end describe 'solaris?' do it 'should return true if OS is a solaris or sunos' do; end end describe 'posix?' do it 'should return true if OS is posix compatible' do; end end describe 'OS.is?' do it "should test if RbConfig::CONFIG['host_os'] matches the regex (boolean value)" do OS.is?(/linux/).should == !!( RbConfig::CONFIG['host_os'] =~ /linux/ ) end end |
| Source | (show)
require 'zucker' require 'rbconfig' module Zucker Os = true end module OS class << self def is?(what) what === RbConfig::CONFIG['host_os'] end alias is is? def to_s RbConfig::CONFIG['host_os'] end end module_function def linux? OS.is?( /linux|cygwin/ ) end def mac? OS.is?( /mac|darwin/ ) end def bsd? OS.is?( /bsd/ ) end def windows? OS.is?( /mswin|mingw/ ) end def solaris? OS.is?( /solaris|sunos/ ) end def posix? linux? or mac? or bsd? or solaris? or begin fork do end true rescue NotImplementedError, NoMethodError false end end #def symbian? #TODO who knows what symbian returns? #end # ... end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Methods one could miss for Array. |
|---|---|
| Why? |
|
| Methods/Usage | Array#^[1,2,3,4] ^ [3,4,5,6] # => [1,2,5,6] Array#sum[1,2,3,4,5].sum # => 15 Array#chrs[72, 97, 108, 108, 111].chrs # => 'Hallo' |
| Specification | (show)
require 'zucker/array' describe 'Array#^' do it 'should do an exclusive or' do a = [1,2,3,4] b = [3,4,5,6] (a^b).should == [1,2,5,6] end end describe 'Array#sum' do it 'should sum the array' do [1,2,3,4,5].sum.should == 15 %w|More Ruby|.sum.should == 'MoreRuby' end end describe 'Array#chrs' do it 'should convert the array to a string, using each element as ord value for the char' do [72, 97, 108, 108, 111].chrs.should == 'Hallo' end end |
| Source | (show)
require 'zucker' module Zucker Array = true end class Array def ^(other) # TODO: more efficient (self - other) + (other - self) end # can take an argument & block to be Rails compatible def sum(identity = 0, &block) # inject(:+) if block_given? map(&block).sum( identity ) else inject(:+) || identity end end def chrs self.pack 'C*' end end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Provides String#to_camel and String#to_snake. |
|---|---|
| Why? | It kind of lies in the nature of Ruby. |
| Methods/Usage | String#to_camel'was_snake_string'.to_camel # => 'WasSnakeString' String#to_snake'WasCamelString' # => 'was_camel_string' |
| Specification | (show)
require 'zucker/case' describe 'String#to_camel' do it 'should turn a snake_cased string to CamelCase' do 'was_snake_case'.to_camel.should == 'WasSnakeCase' end end describe 'String#to_snake' do it 'should turn a CamelCased string to snake_case' do 'WasCamelCase'.to_snake.should == 'was_camel_case' end end |
| Source | (show)
require 'zucker' module Zucker Case = true end class String def to_snake gsub(/(?<!^)[A-Z]/) do "_#$&" end.downcase end def to_camel gsub(/(?:^|_)([a-z])/) do $1.upcase end end end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Enumerable extensions. |
|---|---|
| Methods/Usage | Enumerable#mash[1,2,3].mash{|e| [e, e.to_s] } # => {1=>'1',2=>'2',3=>'3'} |
| Information | Inspired by Ruby Facets' mash. |
| Specification | (show)
require 'zucker/enumerable' describe 'Enumerable#mash' do it 'should "map" a hash' do [1,2,3].mash{|e| [e, e.to_s] }.should == {1=>'1',2=>'2',3=>'3',} end end |
| Source | (show)
require 'zucker' module Zucker Enumerable = true end module Enumerable def mash ret = {} each{ |kv| ret.store( *(yield(kv)[0,2]) ) } ret end end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Extensions for File. |
|---|---|
| Methods/Usage | File.gsubFile.gsub 'some_filename', # will read the file and substitute the hash keys with their values /hi/ => 'cu', /\d/ => proc{ |m| (m.to_i+1).to_s } File.delete!File.delete! 'some_filename' # will delete the file, don't care if it exist. |
| Information | Idea for File.delete! from sugar-high. |
| Specification | (show)
require 'zucker/file' require 'fileutils' describe 'File.gsub' do let :random_filename do 'test_' + (0..20).map{|e| [*'a'..'z'].send RUBY_VERSION > '1.9' ? :sample : :choice }*'' end it 'should read filename in arg1, substitute every key in the arg2 with its value and save the file' do File.open(random_filename,'w'){ |file| file.print 'should read filename in arg1, substitute every key in the arg2 with its value and save the file' } File.gsub random_filename, /read/ => 'write', /\d+/ => proc{|m| (m.to_i+1).to_s } File.read(random_filename).should == 'should write filename in arg2, substitute every key in the arg3 with its value and save the file' FileUtils.rm random_filename end end describe 'File.delete!' do let :random_filename do 'test_' + (0..20).map{|e| [*'a'..'z'].send RUBY_VERSION > '1.9' ? :sample : :choice }*'' end it 'should delete the filename given as argument if it exists + return non-nil' do FileUtils.touch random_filename res = false proc do res = File.delete! random_filename end.should_not raise_exception res.should be_true end it 'should do nothing if the filename given as argument does not exist + return nil' do res = false proc do res = File.delete! random_filename end.should_not raise_exception res.should be_false end end |
| Source | (show)
require 'zucker' module Zucker File = true end class << File def gsub(filename, regex_hash) data = File.read filename File.open(filename,'w'){ |file| regex_hash.each{ |regex, new_string| regex = regex.to_s unless regex.is_a? Regexp if new_string.is_a? Proc data.gsub! regex, &new_string else data.gsub! regex, new_string end } file.print data } end def delete! filename return nil if !File.exist?(filename) File.delete filename end end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Some sugar for dealing with hashes. |
|---|---|
| Methods/Usage | Hash.zipHash.zip [1,2,3], [4,5,6] # => {1=>4, 2=>5, 3=>6} Hash#<<{1=>2} << [3, 4] # => { 1=>2, 3=>4 }
{1=>2} << { 5=>6 } # => { 1=>2, 5=>6 }
Hash#&{ 1=>4, 2=>5, 3=>6 } & { 1=>4, 2=>7 } # => { 1=>4 } |
| Information | Some of the operators are inspired by Ruby Facets. |
| Specification | (show)
require 'zucker/hash' describe 'Hash.zip' do it 'should zip together both given enumerables and take them as key=>values for a new hash' do Hash.zip( [1,2,3], [4,5,6] ).should == { 1=>4, 2=>5, 3=>6 } end end describe 'Hash#<<' do it 'should append new elements to the hash' do a = { 1=>4, 2=>5, 3=>6 } a << { 4=>7 } a << [5, 8] a.should == { 1=>4, 2=>5, 3=>6, 4=>7, 5=>8 } end end describe 'Hash#&' do it 'should select a sub hash containt only equal key-value pairs' do a = { 1=>4, 2=>5, 3=>6 } b= { 1=>4, 2=>7 } (a & b).should == { 1=>4 } end end |
| Source | (show)
require 'zucker' module Zucker Hash = true end class Hash def self.zip(keys,values) Hash[ *keys.zip( values ).flatten ] end def <<(other) case when other.is_a?(Hash) merge! other when other.is_a?(Enumerable) || other.respond_to?(:to_splat) merge! Hash[*other] else raise TypeError, 'can only append other Hashs and Enumerables (or Classes that implement to_splat)' end end def &(other) Hash[ *select{ |k,v| other[k] == v }.flatten ] end end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Generic String extensions. |
|---|---|
| Why? | Strings cannot be comfortable enough ;). |
| Methods/Usage | String#-'1234abc5678' - 'b' - /\d/ # => ac String#^'Yes vs No'^2 # => 's vs No' String#lchomp' Yes'.lchomp # => ' Yes' String#lchomp!# mutable lchomp versionString#ords'Hallo'.ords # => [72, 97, 108, 108, 111] String#constantize'Object'.constantize # => Object 'Spec::VERSION'.constantize # => Spec::VERSION if rspec is loaded # you can also pass a parameter or block to define what happens, when constant does not exist 'IdontExist'.constantize(Array) # => Array 'String5'.constantize do |string| string.chop.constantize end # => String |
| Information | constantize is an improved version of ActiveSupport's one. |
| Specification | (show)
require 'zucker/string' describe 'String#-' do it 'should remove the applied Regexp or String from self via gsub' do ('1234abc5678' - 'b' - /\d/).should == 'ac' end end describe 'String#^' do it 'should give C-like substring access to strings' do string = 'Theoretische Informatik ist voll geil!' (string^0).should == 'Theoretische Informatik ist voll geil!' (string^1).should == 'heoretische Informatik ist voll geil!' (string^13).should == 'Informatik ist voll geil!' (string^-1).should == 'Theoretische Informatik ist voll geil' (string^38).should == '' (string^99).should == nil end end describe 'String#lchomp' do it 'should chomp on the left side' do string = 'Theoretische Informatik ist voll geil!' string.lchomp('T').should == 'heoretische Informatik ist voll geil!' end end describe 'String#ords' do it 'should unpack characters' do string = 'Theoretische Informatik ist voll geil!' string.ords.should == [84, 104, 101, 111, 114, 101, 116, 105, 115, 99, 104, 101, 32, 73, 110, 102, 111, 114, 109, 97, 116, 105, 107, 32, 105, 115, 116, 32, 118, 111, 108, 108, 32, 103, 101, 105, 108, 33] end describe 'String#constantize' do it 'should return the constant with that name' do 'Object'.constantize.should == Object end it 'should also work for nested constants' do 'Zucker::VERSION'.constantize.should == Zucker::VERSION end it 'should throw name error if constant does not exist (and no parameter is given)' do proc do 'ObfsefsefsefafesafaefRubyZuckerafdfselijfesject'.constantize end.should raise_exception NameError end it 'should call the block (and not raise an error) if constant does not exist and block given' do proc do 'ObfsefsefsefafesafaefRubyZuckerafdfselijfesject'.constantize do |string| Default = [1,2,3] end.should == [1,2,3] end.should_not raise_exception NameError end it 'should return the second parameter (and not raise an error) if constant does not exist and parameter given' do proc do 'ObfsefsefsefafesafaefRubyZuckerafdfselijfesject'.constantize(Array).should == Array end.should_not raise_exception NameError end end end |
| Source | (show)
require 'zucker' module Zucker String = true end class String def -(rem) gsub( Regexp === rem ? rem : rem.to_s, '' ) end def ^(pos) pos = pos.to_i if pos >= 0 self[pos..-1] else self[0...pos] end end def lchomp(arg = $/) reverse.chomp(arg).reverse end def lchomp!(arg = $/) reverse.chomp!(arg).reverse end def ords unpack 'C*' # bytes.to_a end def constantize(default_value = nil) # always uses global scope as in AS... is this good? get_constant = lambda{ self.split(/::/).inject( Object ){ |base_constant, current_constant| base_constant.const_get current_constant } } if !default_value && !block_given? get_constant.call else begin get_constant.call rescue NameError if block_given? yield self else default_value end end end end end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Easy conversion between strings and symbols. |
|---|---|
| Why? | Sometimes, you do not care if you get a String or Symbol as input - but when analysing it, you often need to choose one format. A concise possibility for this conversion is using the unary operators String#-@ and Symbol#+@. |
| Methods/Usage | String#+@+'was_string' # => 'was_string' String#-@-'was_string' # => :was_string Symbol#+@+:was_symbol # => 'was_symbol' Symbol#-@-:was_symbol # => :was_symbol |
| Information | Inspired by (I've seen the unary + for Symbol somewhere on the net... but cannot remember where...) |
| Specification | (show)
require 'zucker/unary' describe Symbol, '#+@' do it 'should convert to_s' do +(:matz) == 'matz' # () 1.8 bug end end describe Symbol, '#-@' do it 'should do nothing' do -:matz == :matz end end describe String, '#+@' do it 'should do nothing' do +'matz' == 'matz' end end describe String, '#-@' do it 'should convert to_sym' do -'matz' == :matz end end |
| Source | (show)
require 'zucker' module Zucker Unary = true end class String def +@ self end def -@ to_sym end end class Symbol def +@ to_s end def -@ self end end # J-_-L |
| Compatibility | 1.9, 1.8 (+:literal not possible) |
| Discussion | github wiki |
| Summary | Easy creation of Regexp.unions. |
|---|---|
| Methods/Usage | Regexp#|, String#|/Ruby\d/ | /test/i | "cheat" # creates a Regexp similar to: # /(Ruby\d|[tT][eE][sS][tT]|cheat)/ |
| Specification | (show)
require 'zucker/union' shared_examples_for "Regexp.union operator" do it "should create an Regexp.union of both operands" do (/Ruby\d/ | /test/i | "cheat").should == Regexp.union( Regexp.union( /Ruby\d/, /test/i ), "cheat" ) end end describe 'Regexp#|' do it_should_behave_like 'Regexp.union operator' end describe 'String#|' do it_should_behave_like 'Regexp.union operator' end |
| Source | (show)
require 'zucker' module Zucker Union = true end class Regexp def |(arg) Regexp.union self, arg.is_a?(Regexp) ? arg : arg.to_s end end class String def |(arg) Regexp.union self, arg.is_a?(Regexp) ? arg : arg.to_s end end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Does pretty the same as in ActiveSupport (Every object can be asked if it is blank or present). |
|---|---|
| Why? | It's too familiar ;) |
| Methods/Usage | Object#blank?["'an object'.blank? # => false", "nil.present? # => false"] |
| Specification | (show)
require 'zucker/blank' describe 'Object#blank?' do it 'should be blank for blank values' do blank_values = [ nil, false, '', ' ', " \n\t \r ", [], {}, // ] blank_values.each{ |blank| blank.blank?.should == true } end it 'should not be blank for non blank values' do present_values = [ Object.new, true, 0, 1, 'a', [nil], { nil => nil } ] present_values.each{ |present| present.blank?.should == false } end end |
| Source | (show)
require 'zucker' module Zucker Blank = true end class Object def blank? if respond_to? :empty? then empty? else !self end end def present? !blank? end end { # what to do # for which classes lambda{ true } => [FalseClass, NilClass], lambda{ false } => [TrueClass, Numeric], lambda{ empty? } => [Array, Hash], lambda{ self !~ /\S/ } => [String], lambda{ self == // } => [Regexp], }.each{ |action, klass_array| klass_array.each{ |klass| klass.send :define_method, :blank?, &action } } # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Adds Object#mcopy to create a deep copy using Marshal. |
|---|---|
| Why? | Every Ruby book describes, you can do Marshal.load Marshal.dump object to create a deep copy... But who needs this verbose syntax in everyday coding? |
| Methods/Usage | Object#mcopya = %w[hello world]
b = a.mcopy
|
| Specification | (show)
require 'zucker/mcopy' describe 'Object#mcopy' do it 'create a (deep) copy via marshalling' do a = %w[hello world] b = a.mcopy b.should == a b[0][1,1] = '' b.should_not == a end end |
| Source | (show)
require 'zucker' module Zucker Mcopy = true end class Object def mcopy Marshal.load Marshal.dump self end end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | not returns an object on which all methods are redirected to it's receiver object, but returns the inverted boolean. |
|---|---|
| Why? | Better readability. |
| Methods/Usage | Object#not[1,2,3].not.empty? # true |
| Information | See this article by Jay Field for more information. |
| Specification | (show)
if defined? BasicObject # 1.9 only require 'zucker/not' describe 'Object#not' do it "should return an object on which all methods are redirected to it's receiver object, but return an inverted boolean" do [1,2,3].not.empty?.should == true nil.not.nil?.should == false end end end |
| Source | (show)
require 'zucker' module Zucker Not = true end class Object def not NotClass.new self end class NotClass < BasicObject def initialize(receiver) @receiver = receiver end def method_missing(m, *args, &block) not @receiver.public_send( m, *args, &block ) end end end # J-_-L |
| Compatibility | 1.9 |
| Discussion | github wiki |
| Summary | Calls the method named by the first paramenter and passes the other elements as paramaters. |
|---|---|
| Why? | When using Symbol#to_proc, you often wish to pass parameters. |
| Methods/Usage | Array#to_proc[1,2,3,4].map &[:*, 5] # => [5, 10, 15, 20] # you can also chain them, if the first parameter is an Array [1,2,3,4].map &[[:to_s, 2],[:+, 'b']] # => ["1b", "10b", "11b", "100b"] |
| Information | Inspired by this article. More about to_proc. Chaining inspired by eregon. |
| Specification | (show)
require 'zucker/array_to_proc' describe 'Array#to_proc' do it 'should call the method of the first symbol, using the remaining elements as paramaters' do [1,2,3,4].map( &[:to_s, 2] ).should == ["1", "10", "11", "100"] end it "should convert each element to a proc and chain it, if the first parameter is an array" do [1,2,3,4].map( &[[:*,2],[:+,4]] ).should == [1,2,3,4].map{|i| i*2 + 4 } end end |
| Source | (show)
require 'zucker' module Zucker ArrayToProc = true end class Array def to_proc Proc.new{ |obj| if self.first.is_a? Array self.inject(obj){ |result, nested_array| nested_array.to_proc.call result } else obj.send(*self) end } end end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Creates a new instance of the class. |
|---|---|
| Methods/Usage | Class#to_proc[ [1,2],[3,5,6,7,3] ].map(&Set) # => [ Set[1,2], Set[5,6,7,3] ] |
| Information | Inspired by Ruby Facets. More about to_proc. |
| Specification | (show)
require 'zucker/class_to_proc' require 'set' describe 'Class#to_proc' do it 'should create new instances of the class' do [ [1,2],[3,5,6,7,3] ].map(&Set).should == [ Set[1,2], Set[5,6,7,3] ] end end |
| Source | (show)
require 'zucker' module Zucker ClassToProc = true end class Class def to_proc Proc.new do |*args| self.new(*args) end end end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Use a hash to apply procs to specific objects. |
|---|---|
| Methods/Usage | Hash#to_proc[1,2,3,4].map(&{ 2 => lambda {|e| e + 1000}, 4 => :to_s, }) # => [1, 1002, 3, '4'] |
| Information | More about to_proc. |
| Specification | (show)
require 'zucker/hash_to_proc' describe 'Hash#to_proc' do it 'should run the proc given in the value for a key in the hash' do [1,2,3,4].map(&{ 4 => :to_s, # 3 => [:to_s, 2] # "11" => if array2proc is used 2 => lambda {|e| e + 1000} }).should == [1, 1002, 3, "4"] end end |
| Source | (show)
require 'zucker' module Zucker HashToProc = true end class Hash def to_proc Proc.new{ |obj| if self.member? obj self[obj].to_proc.call obj else obj end } end end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Use &/regex/ to match it against strings. |
|---|---|
| Methods/Usage | Regexp#to_proc%w|just another string array|.map &/[jy]/ # => ["j", nil, nil, "y"] %w|just another string array|.select &/[jy]/ # => ["just", "array"] |
| Information | More about to_proc. |
| Specification | (show)
require 'zucker/regexp_to_proc' describe 'Regexp#to_proc' do it 'should match the regex' do %w|just another string array|.map( &/[jy]/).should == ["j", nil, nil, "y"] %w|just another string array|.select( &/[jy]/).should == ["just", "array"] end end |
| Source | (show)
require 'zucker' module Zucker RegexpToProc = true end class Regexp def to_proc proc do |e| e.to_s[self] end end end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | A different way to create aliases: Reversed order and you can pass multiple alias names. |
|---|---|
| Why? | It's clearer in which order to put the arguments. |
| Methods/Usage | alias_for, aliases_foralias_for :methods, :ms # creates an alias for the method :methods with the name ms module Enumerable aliases_for :zip, :with, :% end # creates multiple aliases Module#method_alias_for, Module#method_aliases_for# same as alias_for, but using Module#alias_method instead of alias
|
| Information | Thanks to Kristian Mandrup for the idea and alias method specs. |
| Specification | (show)
require 'zucker/alias_for' describe 'alias_for' do it 'should create an alias for global methods' do # rspec bug? # def m1 # 1 # end # alias_for :m1, :a1 # # proc do # a1.should == 1 # end.should_not raise_exception end it 'should create an alias for instance methods' do class Array def m2 2 end alias_for :m2, :a2 end proc do [1,2,3].a2.should == 2 end.should_not raise_exception end it 'should create an alias for class (singleton) methods' do class Array class << Array def m3 3 end alias_for :m3, :a3 end end proc do Array.a3.should == 3 end.should_not raise_exception end it 'should create aliases for the first argument with all other arguments' do class Object def m4 4 end alias_for :m4, :ma, :mb, :mc end proc do 1.ma.should == 4 "1".mb.should == 4 [1].mc.should == 4 end.should_not raise_exception end end # alias_method module Blip def blip 'blip' end alias_methods_for :blip, :blap, :blup class << self def self_blip 'blip' end alias_methods_for :self_blip, :self_blap, :self_blup end end class Hello include Blip def hello 'hello' end alias_methods_for :hello, :hi, :howdy class << self def self_hello 'hello' end alias_methods_for :self_hello, :self_hi, :self_howdy end end describe 'alias_methods_for' do let(:h) { Hello.new } context "module context" do it "should alias instance methods" do h.blap.should == h.blip h.blup.should == h.blip end it "should alias class methods" do Blip.self_blap.should == Blip.self_blip Blip.self_blup.should == Blip.self_blip end end context "class context" do it "should alias instance methods" do h.hi.should == h.hello h.howdy.should == h.hello end it "should alias class methods" do Hello.self_hi.should == Hello.self_hello Hello.self_howdy.should == Hello.self_hello end end end |
| Source | (show)
require 'zucker' module Zucker AliasFor = true end def alias_for(m, *aliases) aliases.each{ |a| class_eval "alias #{a} #{m}" } end alias aliases_for alias_for class Module def alias_method_for(m, *alias_methods) alias_methods.each{ |a| class_eval do alias_method a.to_sym, m.to_sym end } end alias alias_methods_for alias_method_for end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Some convenient aliases (and constants) for existing methods. |
|---|---|
| Methods/Usage | Object#is_an?Object.is_a?Enumerable#withEnumerable#zip Enumerable#%Enumerable#zip Array#**Array#product Hash#+Hash#merge Binding#[]Binding#eval File.filenameFile.basenameDir.joinFile.joinDir.splitFile.splitInfinity1.0 / 0.0 NaN0.0 / 0.0 |
| Specification | (show)
require 'zucker/aliases' describe '(aliases)' do it 'should create these aliases' do # see aliases.rb for aliase list end it 'should define these constants' do Infinity.finite?.should == false NaN.nan?.should == true end end |
| Source | (show)
require 'zucker' module Zucker Aliases = true end class Object alias is_an? is_a? # thanks to utility_belt end module Enumerable alias with zip alias % zip end class Array alias ** product alias contains? include? end class String alias contains? include? end class Hash alias + merge end class Binding #alias [] eval def [](expr) self.eval "#{expr}" end end class << File alias filename basename # thanks rdp :) end class << Dir def join(*args) File.join(*args) end def split(*args) File.split(*args) end end # constants - who would use these in real-world code for other things? Infinity = 1.0 / 0.0 # or 2*Float::MAX or Float::INFINITY NaN = 0.0 / 0.0 # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | This method lets you easily assign lots of instance variables. |
|---|---|
| Why? | Often, you have to write boilerplate code for assigning instance variables, for example this one:def initialize(variable1, variable2) |
| Methods/Usage | instance_variables_from, ivarsdef a_method(a = 1, b = 2) instance_variables_from binding # assigns @a and @b params = {:c => 3, :d => 4} instance_variables_from params # # assigns @c and @d end |
| Specification | (show)
require 'zucker/ivars' describe 'instance_variables_from' do it 'should tansform the given parameter to instance variables' do def a_method(a = 1, b = 2) instance_variables_from binding # assigns @a and @b params = {:c => 3, :d => 4} ivars params # # assigns @c and @d end a_method @a.should == 1 @b.should == 2 @c.should == 3 @d.should == 4 end end |
| Source | (show)
require 'zucker' module Zucker Ivars = true end def instance_variables_from(obj, *only) iter = if obj.is_a? Binding obj.eval('local_variables').map{|e| [obj.eval("#{e}"), e] } elsif obj.is_a? Hash obj.map{|k,v| [v,k] } else # elsif obj.is_a? Enumerable obj.each.with_index end ret = [] iter.each{ |value, arg| arg = arg.to_s if only.include?(arg) || only.include?(arg.to_sym) || only.empty? arg = '_' + arg if (48..57).member? arg.unpack('C')[0] # 1.8+1.9 ret << ivar = :"@#{arg}" self.instance_variable_set ivar, value end } ret end alias ivars instance_variables_from # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | This helper methods defines [] and []= for accesing an instance variable. |
|---|---|
| Methods/Usage | square_brackets_forclass Klass def initialize @var = { :a_key => 1, :another_one => 2, } end square_brackets_for :var # creates [] and []= # square_brackets_for :var, false # would create only [] end a = Klass.new a[:a_key] # => 1 |
| Specification | (show)
require 'zucker/square_brackets_for' describe 'square_brackets_for' do before do class Klass def initialize @var = { :a_key => 1, :another_one => 2, } end @eigenvar = { :a_key => 99 } end end it 'should define a [] getter (not a setter) for an instance var, if the second parameter is false' do class Klass square_brackets_for :var, nil end a = Klass.new a[:a_key].should == 1 proc do a[:this_is] = 'not possible' end.should raise_exception NoMethodError end it 'should define [] and []= for accessing an instance variable' do class Klass square_brackets_for :var end a = Klass.new a[:a_key].should == 1 a[:this_is] = 'useful' a[:this_is].should == 'useful' end it 'should also work for class-instance variables' do class Klass class << Klass square_brackets_for :eigenvar end end Klass[:a_key].should == 99 end end |
| Source | (show)
require 'zucker' module Zucker SquareBracketsFor = true end class Module def square_brackets_for(ivar, assignment = true) # undef [] if respond_to? :[] # undef []= if respond_to? :[]= define_method :[] do |key| (instance_variable_get :"@#{ivar}")[key] end if assignment define_method :[]= do |key, value| (instance_variable_get :"@#{ivar}")[key] = value end end end end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
(not included by require 'zucker/default')
| Summary | Adds Binding#vars. It gives you information about the current environment variables. |
|---|---|
| Methods/Usage | Binding#variables, Binding#vars# shows your current environment's variables, irb example: >> a=3 => 3 >> binding.vars => #<Binding:0x94c4b50> local variables - a: 3 - _: #<Binding:0x94c4b50> (instance variables) - none self - main block_given? - false |
| Specification | (show)
require 'zucker/binding' describe 'Binding#variables' do it 'should output information about the current environment' do; end end |
| Source | (show)
require 'zucker' module Zucker Binding = true end unless defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' class Binding def variables put_vars = lambda { |array| if array.empty? ' - none' else array.map{|e| val = (self.eval "#{e}").inspect " - #{e}: #{ val }" }.join "\n" end } puts "#{self.to_s} local variables #{ put_vars[ self.eval 'local_variables' ] } (instance variables) #{ put_vars[ self.eval 'instance_variables' ] } self - #{self.eval 'self'} block_given? - #{self.eval 'block_given?'}" end alias vars variables end end # J-_-L |
| Compatibility | 1.9, 1.8 (no rbx support) |
| Discussion | github wiki |
| Summary | c outputs the current method callstack. |
|---|---|
| Methods/Usage | c, ccc # shows the method callstack c true # do not hide irb/ripl callstack |
| Specification | (show)
require 'zucker/cc' describe 'c' do it 'should output the method callstack' do; end end |
| Source | (show)
require 'zucker' module Zucker Cc = true end module Kernel private def c(show_irb = false) method_stack = caller.reverse.map{ |m| m.rindex( /:\d+(:in `(.*)')?$/ ) $2 }.compact if !show_irb if a = method_stack.index( 'irb_binding' ) method_stack = [ method_stack[0], '(irb)', *method_stack[a+1..-1] ] elsif a = method_stack[1..-1].index( '<main>' ) method_stack = [ method_stack[0], '(ripl)', *method_stack[a+2..-1] ] end end # puts method_stack.map.with_index{ |m, i| method_stack.each_with_index{ |m, i| puts " "*i + m } nil end alias cc c end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Easy debug printing with the p alternative .d. It outputs to stdout and returns self. Accepts a block. |
|---|---|
| Methods/Usage | Object#d, Object#ddsome.d.methods.d.noone.d.knows.d # ...outputs 4 lines with the inspected objects # => (result) 21+Math.sin(42).d # outputs -0.916521547915634 # => 20.0834784520844 name = 'Earth' 'Hello ' + name.d{|e| "The length is: #{e.size}"} # outputs "The length is: 5" # => 'Hello Earth' |
| Information | This is inspired by the .tap method.There is also tap cube with more tap methods. |
| Specification | (show)
require 'zucker/dd' describe 'Object#d' do let :a do [ 1, "1", 2..5, [], {:hallo => :du}, nil, true ] end it "should not change the object's value" do capture_stdout do a.each{ |e| (e.d).should == e } a.each{ |e| (e.d{|value| "This is a: #{value}"}).should == e } end end it "should puts .inspect if no block is given (and not change the object's value)" do capture_stdout do a[0].d a[1].d a[6].d end.should == %{1\n"1"\ntrue\n} end it "should puts the block if it is given (and not change the object's value)" do capture_stdout do a[0].d{|value| "This is a: #{value}"} a[1].d{|value| "This is a: #{value}"} a[6].d{|value| "This is a: #{value}"} end.should == %{This is a: 1\nThis is a: 1\nThis is a: true\n} end end |
| Source | (show)
require 'zucker' module Zucker Dd = true end module Kernel def d(*args, &block) if args.empty? tap{ if block_given? puts yield self else puts self.inspect end } else raise ArgumentError, ".d - The parser thought that the code after .d are method arguments... Please don't put a space after d or use .d() or .d{} in this case!" # eval ... end end alias dd d end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | m displays an ordered public method list. |
|---|---|
| Why? | See one object's methods without those rarely used inherited methods. |
| Methods/Usage | Object#m, Object#mm, Object#method_list>> 5.mm 2 # outputs the list (2 levels deep), for example: # = Fixnum # to_s -@ + - * / div % modulo divmod fdiv ** abs magnitude == === <=> > >= < <= ~ & | ^ [] << >> to_f size zero? odd? even? succ # = Integer # integer? odd? even? upto downto times succ next pred chr ord to_i to_int floor ceil truncate round gcd lcm gcdlcm numerator denominator to_r rationalize |
| Information | See this article for more information. |
| Specification | (show)
require 'zucker/mm' describe 'Object#mm' do it 'should display an ordered method list' do; end end |
| Source | (show)
require 'zucker' module Zucker Mm = true end module Kernel def m(levels = 1) # output helper mputs = proc{ |e| puts e.map(&:to_s)*' ' } # how to get results if self.is_a? Module klass, method_function = self, :public_methods else klass, method_function = self.class, :public_instance_methods end # eigenclass eigen = self.singleton_methods if !eigen.empty? puts '= Eigenclass' # sorry for not being up to date, I just love the word mputs[ self.singleton_methods ] end # display levels.times{ |level| if cur = klass.ancestors[level] puts "= #{cur}" # put class name mputs[ cur.send method_function, false ] # put methods of the class else break end } nil end alias mm m alias method_list m end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | The o method outputs the current method, line, file and label (if given). |
|---|---|
| Methods/Usage | o, ooo # e.g: Reached method `irb_binding', line 1 of file (irb) o:Label # e.g: Label: reached method `abc', line 7 of file (irb) |
| Specification | (show)
require 'zucker/oo' describe 'o' do it 'should output the current line, file, method and label (if given)' do; end end |
| Source | (show)
require 'zucker' module Zucker Oo = true end module Kernel private def o(desc = nil) caller[0].rindex( /:(\d+)(:in (`.*'))?$/ ) m = $3 ? "method #$3, " : "" d = desc ? "#{desc}: r" : 'R' puts "#{d}eached #{m}line #$1 of file #$`" # [$`, $1.to_i, $3.to_sym, desc] end alias oo o end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | The q method does the same like p, but outputs multiple arguments on the same line. |
|---|---|
| Methods/Usage | q, qqq "zucker", '', {6=>7}, 5, 2.3, :o # outputs "zucker" "" {6=>7} 5 2.3 :o |
| Information | Inspired by rdp. |
| Specification | (show)
require 'zucker/qq' describe 'q' do it 'should output the same as p for a single arg' do capture_stdout{p /some object/}.should == capture_stdout{q /some object/} end it "should output the same as p but for multiple args one one line, values separated by two spaces" do capture_stdout do q 1, "1", 2..5, [], {:hallo => :du}, nil, true end.chop.should == capture_stdout do p 1, "1", 2..5, [], {:hallo => :du}, nil, true end.chop.gsub( "\n", ' ' ) end end |
| Source | (show)
require 'zucker' module Zucker Qq = true end module Kernel private def q(*args) puts args.map( &:inspect )*' ' unless args.empty? end alias qq q end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
| Summary | Test your regex against a string, handy for the command line. |
|---|---|
| Methods/Usage | Regexp#visualize, Regexp#vis# regex = /\b([A-Z0-9._%+-]+)@([A-Z0-9.-]+\.[A-Z]{2,4})\b/i regex.vis 'I do not contain an email address.' # no match regex.vis 'I contain an email address: mail@example.com' # I contain an email address: >mail@example.com< regex.vis 'mail@example.com', 1 # 1: >mail< @example.com regex.vis 'mail@example.com', 2 # 2: mail@ >example.com< regex.vis 'mail@example.com', 3 # 3: no match regex.vis 'mail@example.com', [0,1,2] # 0: >mail@example.com< # 1: >mail< @example.com # 2: mail@ >example.com< |
| Specification | (show)
require 'zucker/regexp_visualize' describe 'Regexp#visualize' do let :regex do /\b([A-Z0-9._%+-]+)@([A-Z0-9.-]+\.[A-Z]{2,4})\b/i end # regex from regular-expressions.info/email.html it 'should display a string where >and< mark the found regex' do capture_stdout do regex.vis 'I do not contain an email address.' end.chomp.should == 'no match' end it 'should display "no match" if the regex could not be matched' do capture_stdout do regex.vis 'I contain an email address: mail@example.com' end.chomp.should == 'I contain an email address: >mail@example.com< ' end it 'should display a string where >and< mark the found regex group if group identifier is given as arg2' do capture_stdout do regex.vis 'mail@example.com', 1 end.chomp.should == '1: >mail< @example.com' end it 'should display "group identifier: no match" if the arg2 group could not be matched' do capture_stdout do regex.vis 'mail@example.com', 3 end.chomp.should == '3: no match' end it 'should also take an array of group identfiers as arg2' do capture_stdout do regex.vis 'mail@example.com', [0,1,2] end.chomp.should == "0: >mail@example.com< \n"\ "1: >mail< @example.com\n"\ "2: mail@ >example.com< " end end |
| Source | (show)
require 'zucker' module Zucker RegexpVisualize = true end class Regexp def visualize(string, groups = nil) if self =~ string if !groups puts $` + ' >' + $& + '< ' + $' else Array( groups ).each{ |group| begin gr_string = string.dup gr_string[ $~.end( group ), 0 ] = '< ' gr_string[ $~.begin( group ), 0 ] = ' >' puts group.to_s + ': ' + gr_string rescue IndexError, defined?(Rubinius) && Rubinius::ObjectBoundsExceededError puts group.to_s + ': no match' end } end else puts 'no match' end nil end alias vis visualize end # J-_-L |
| Compatibility | 1.9, 1.8 |
| Discussion | github wiki |
2012-01-16 | Zucker 12.1 * fix a requiring bug * rename zucker/version cube to zucker/ruby_version and Zucker::PACKAGES to Zucker::PACKS * remove more_aliases! (keep it simple...) * add case cube: String#to_camel and String#to_snake 2011-05-25 | Zucker 11 * add Zucker::constants to check if cube has been required (e.g. Zucker::AliasFor if 'zucker/alias_for' is loaded) * rbx tweaks * don't define Binding#vars on rbx (prevent endless recursion) * sandbox-not-working warning * add Kernel#ignore_sigquit! * fix warnings * doc tweaks 2011-04-29 | Zucker 10 * doc/spec tweaks * make test.rubygems.org-testable * fix zucker 9 permission issue 2011-01-22 | Zucker 9 * remove history versions (sorry, it caused too much gem/rdoc troubles) * add file cube: File.delete! and File.gsub * debug pack improvements * binding: typos + return nil * cc: support for ripl + return nil * mm: also show eigenclass for modules + nicer displaying + return nil * added Regexp#visualize * remove optional sandbox param * rename xxx2proc to xxx_to_proc * change rakefile/rspec/gemspec structure * more minor fixes and improvements 2010-10-06 | Zucker 8 * fix a little alias_for bug * disable rdoc creation when installing (in favour of the custom docs) * change Binding#inspect to Binding.variables (was too verbose and dangerous) 2010-10-03 | Zucker 7 * fix critical OS.windows? bug 2010-10-03 | Zucker 6 * no new cubes * bugfix for OS.posix? * small changes + bugfixes + doc improvements * add two user methods to Info * change egonil semantics ( using method_missing, see http://rbjl.net/26/catch_nil.rb ) * bugfix for vv 2010-09-04 | Zucker 5 * debug edition - add two debug helpers: oo (output line, method, file) and cc (output method callstack) * rename cube D to dd add add more debug aliases (for mm and binding) * fix __SPECIAL_VARS__ in info and kernel cube and some minor bugfixes * Zucker.activate_more_aliases! option * add Hash#& * add aliases: File.filename (for basename), Dir.join and Dir.split (for File.join, split) * add a flexible requiring mechansim in zucker.rb (no api changes) * restructure packages * add rake tasks for releasing * improve RubyVersion constant (cleaner and more flexible) 2010-09-01 | Zucker 4 * fix Binding#inspect * add RubyEngine constant * add RubyVersion constant * add OS constant * add q debug method (like p but on one line) * add String#- 2010-08-14 | Zucker 3 * add tap cube * add Object#not * add alias_for for an alternative alias syntax * add String#constantize (improved AS version) * improve Info module * make Array#sum Rails compatibile * improve docs * change directory layout (no changes for requiring) * more small changes 2010-08-08 | Zucker 2 * add info cube * add chaining for array2proc * fix Hash.zip * fix instance_variables_from binding for 1.9 * more specs 2010-08-06 | Zucker 1 * initial release 2010-08-05 | Zucker 0 * pre-release for rug-b talk