Skip to content

Instantly share code, notes, and snippets.

@yurko
Last active May 30, 2018 13:16
Show Gist options
  • Save yurko/737d21943bd30434bbdefd8d126228ae to your computer and use it in GitHub Desktop.
Save yurko/737d21943bd30434bbdefd8d126228ae to your computer and use it in GitHub Desktop.
Ruby tips&tricks from different sources
class Class
def new(*args, &block)
obj = allocate
obj.initialize(*args, &block)
# actually, this is obj.send(:initialize, …) because initialize is private
obj
end
end
class Foo
CONST_1 = 1
CONST_2 = 2
class_eval do
constants.each { |c| define_method(c.downcase) { self.class.const_get c } }
end
end
# Ruby < 2.5 (https://blog.bigbinary.com/2017/10/18/ruby-2.5-has-removed-top-level-constant-lookup.html)
module Kernel
A = B = C = D = E = F = "from kernel"
end
A = B = C = D = E = "from toplevel"
class Super
A = B = C = D = "from superclass"
end
module Included
A = B = C = "from included module"
end
module Enclosing
A = B = "from enclosing module"
class Local < Super
include Included
A = "defined locally"
puts A # "defined locally"
puts B # "from enclosing module"
puts C # "from included module"
puts D # "from superclass"
puts E # "from toplevel"
puts F # "from kernel"
end
end
rows = [['one','two','three'],[1,2,3],[4,5,6]]
sv_str = rows.inject([]) { |csv, row| csv << CSV.generate_line(row) }.join("")
File.open("orgs.csv", "w") {|f| f.write(rows.inject([]) { |csv, row| csv << CSV.generate_line(row) }.join(""))}
dates = ->(p) { Enumerator.new { |y, n = 0| loop { y << Time.now.utc.beginning_of_day + n.days; n += p } } }
class Callable
class << self
extend Forwardable
def_delegator :new, :call
end
def call
end
end
Callable.call == Callable.new.call
def repeatedly
Enumerator.new { |a| loop { a << yield } }
end
repeatedly {rand 100}.take 5
squares = ->() { Enumerator.new {|y, a=1| loop { y << a**2; a+=1 } }.lazy }
squares[].select { |e| e % 3 == 0 }.first 10
def fix_minutes
until (0...60).member? minutes
@hours -= 60 <=> minutes
@minutes += 60 * (60 <=> minutes)
end
@hours %= 24
self
end
class Point
attr_accessor :x, :y
def initialize(x, y)
@x = x
@y = y
freeze
end
def change
@x = 3
end
end
point = Point.new(1,2)
point.change # RuntimeError: can't modify frozen Point
h = { foo: 1, bar: 2, baz: 3 }
# instead of this:
[:foo, :bar].map { |key| h[key] } #=> [1, 2]
# we can use this syntax:
[:foo, :bar].map(&h) #=> [1, 2]
# Default string
class String
def |(what)
self.strip.blank? ? what : self
end
end
@user.address | "We don't know user's address"
# Custom Splat
class Netrc
Entry = Struct.new(:login, :password) do
alias_method :to_ary, :to_a
end
end
e = Netrc::Entry.new("user", "qwerty")
e.login # => "user"
e[:password] # => "qwerty"
e[1] # => "qwerty"
login, password = e
[ ] [ ]= Element reference, element set
** Exponentiation
! ~ + - Not, complement, unary plus and minus (method names for the last two are +@ and -@)
* / % Multiply, divide, and modulo
+ - Plus and minus
>> << Right and left shift
& Bitwise `and'
^ | Bitwise exclusive `or' and regular `or'
<= < > >= Comparison operators
<=> == === != =~ !~ Equality and pattern match operators (!= and !~ may not be defined as methods)
def pascal_triangle n
next_row = ->(row) { ([0] + row).zip(row + [0]).map {|l,r| l + r} }
row = ->(n) { n.times.inject([1]) {|x| next_row[x]} }
n.times { |t| p row[t] }
end
def pascal_tr n
row = Enumerator.new { |y, row=[1]| loop { y << row; row = ([0]+row).zip(row+[0]).map { |l,r| l+r } } }
n.times { p row.next }
end
(0...10).map{ ('a'..'z').to_a[rand(26)] }.join
# Delegate private methods
private *delegate(:foo, :bar, :to => :baz)
# Require all files from dir
Dir["/path/to/directory/*.rb"].each {|file| require file }
def define_methods
shared = 0
Kernel.send(:define_method, :counter) { shared }
Kernel.send(:define_method, :inc) { |x| shared += x }
end
class Dog
def self.closest_relative
"wolf"
end
end
class Dog
class << self
def closest_relative
"wolf"
end
end
end
def Dog.closest_relative
"wolf"
end
class << Dog
def closest_relative
"wolf"
end
end
def splitBase64(uri)
if uri.match(%r{^data:(.*?);(.*?),(.*)$})
return {
type: $1, # "image/png"
encoder: $2, # "base64"
data: $3, # data string
extension: $1.split('/')[1] # "png"
}
end
end
s = StringIO.open do |s|
s.puts 'adding newlines with puts is easy...'
s.puts 'and simple'
s.string
end
t = DateTime.now
t.to_date + (t.min < 30 ? t.hour.hours : t.hour.hours + 30.minutes)
def hello
yield name: 'Kasper'
end
hello { |options| p options[:name] }
# Outputs "Kasper"
Or named yielded arguments:
hello { |name:| p name }
# Outputs "Kasper"
Use an anonymous splat to avoid ArgumentErrors.
def hello
yield name: 'Kasper', play_style: :laces_out
end
hello { |name:, **| p name }
# Outputs "Kasper"
Source: https://dev.firmafon.dk/blog/drat-ruby-has-a-double-splat/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment