You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
defprint_onceyieldendprint_once{puts"Block is being run"}defmy_blockyield2yield3endmy_block{|parameter| puts"parameter is: #{parameter}"}defdo_something_with_blockreturn"No block given"unlessblock_given?yieldend
Proc
my_proc=Proc.new{ |x| puts"arg: #{x}"}my_proc.call"Abc"#=> arg: Abcdefexplicit_block(&block)return"No block given"unlessblockblock.call# same as yieldendexplicit_block{puts"Explicit block called"}factor=Proc.new{|n| printn*2}# or factor=proc{|n| printn*2}# using the proc value[3,2,1].each(&factor)=>642# & ruby knows that this is a proc and not a variable.defmy_each(&block)self.length.timesdo |i|
# and now we can call our new Proc like normalblock.call(self[i])endend[1,2,3].my_each{ |i| putsi*2}# &converts the block into a proc so we treat the block as a proc inside our method.
Lamda
lamb=lambda{|arg| puts"I am a lambda #{arg}"}lamb=->(arg){puts"I am a stuby lambda#{arg}"}# Procs don’t care about the correct number of arguments, while lambdas will raise an exception.# Return and break behaves differently in procs and lambdas
# map# The original array is not modified. Returns the modified array.[1,2,3,4,5,6,7,8,9,10].map{|e| e*3}# [3, 6, 9, 12, 15, 18, 21, 24, 27, 30]# collect is alias for map# select# Returns a new array containing all elements of ary for which the given block returns a true value.[1,2,3,4,5].select{ |num| num.even?}#=> [2, 4]# reject# Returns an array for all elements of enum for which the given block returns false.(1..10).reject{ |i| i % 3 == 0}#=> [1, 2, 4, 5, 7, 8, 10]# inject# Combines all elements of enum by applying a binary operation(5..10).inject(:+)#=>45(5..10).inject{ |product,n| product * n}#=> 151200# product=5, n=6# product=30, n=7# product=210, n=8# product=1680, n=9# product=15120, n=10# You can also specify an initial value as parameter before the block["bar","baz","quux"].inject("foo"){|acc,elem| acc + "!!" + elem}#=>"foo!!bar!!baz!!quux" # reduce is alias for inject# find# Passes each entry in enum to block. Returns the first for which block is not false.[1,2,3,4,5,6,7,8,9,10].find{ |el| el / 2 == 2}#=>4# detect is alias for find# find_all# Returns an array containing all elements of enum for which the given block returns a true value.[1,2,3,4,5].find_all{ |num| num.even?}#=> [2, 4]# find_all vs select# On a hash, find_all returns an array, but select returns a hash instead of an arrayhash={a: 1,b: 2,c: 3,d: 4}hash.find_all{ |key,value| value.odd?}#=> [[:a, 1], [:c, 3]]hash.select{ |key,value| value.odd?}#=> {a:1, c:3}#pluck# It is from activesupport[{id: 1,name: "David"},{id: 2,name: "Rafael"}].pluck(:id,:name)#=> [[1, "David"], [2, "Rafael"]]
group_by
group_by returns a hash where the keys are defined by our grouping rule, and the values are the corresponding objects from our original collection.
# if the receiver does not respond to it the call returns nil rather than raising an exception.@person.try(:name)# @person.name if @person && @person.name@person.try(:spouse).try(:name)# @person.spouse.name if @person && @person.spouse && @person.spouse.name# You can pass arguments and blocks to try():@manufacturer.products.first.try(:enough_in_stock?,32)# => "Yes"try!#Same as try, but raises a NoMethodError exception if the receiver is not nil and does not implement the tried method.123.try!(:upcase)# => NoMethodError: undefined method `upcase' for 123:Integer
&
#Same as try!account&.owner&.addressaccount=Account.new(owner: false)account.owner.address# => NoMethodError: undefined method `address' for false:FalseClass `account && account.owner && account.owner.address# => falseaccount.try(:owner).try(:address)# => nilaccount&.owner&.address# => undefined method `address' for false:FalseClass`
dig
address=params.dig(:account,:owner,:address)# address = params[:account].try(:[], :owner).try(:[], :address)h={foo: {bar: {baz: 1}}}h.dig(:foo,:bar,:baz)#=> 1h.dig(:foo,:zot,:xyz)#=> nilg={foo: [10,11,12]}g.dig(:foo,1)#=> 11g.dig(:foo,1,0)#=> TypeError: Integer does not have #dig methodg.dig(:foo,:bar)#=> TypeError: no implicit conversion of Symbol into Integer
Without arguments, rand gives you a floating point number between 0 & 1 (like 0.4836732493)
With an integer argument (rand(10)) you get a new integer between 0 & that number
With a range argument (rand(1..20)) you get an integer between the start of the range & the end of the range
# Generate an integer from 0 to 10(rand() * 10).to_irand(10)# Generate an integer from 1 to 20rand(1..20)
Percent Strings
stringA="World!"%w[Hello\n#{stringA}]=>["Hello\\n","\#{stringA}"]%W[Hello\n#{stringA}]=>["Hello\n","World!"]a="three"%i[onetwo#{a}]=>[:one,:two,:"\#{a}"]%I[onetwo#{a}]=>[:one,:two,:three]date=`date`"Tue Mar 3 13:50:57 NZDT 2020\n"echo=%x(echo `date`)#shell command=>"Tue Mar 3 13:51:13 NZDT 2020\n"# %() is shorthand for %Q%(<tr><td class="name">#{name}</td>)%Q()givesadouble-quotedstring
Heredoc
Nicely indented multi-line strings.
page=<<-HTML Heredocs are cool & usefulHTML# " Heredocs are cool & useful\n"#Note that this was introduced with Ruby 2.3. On older Rubies you may use String#strip_heredoc from ActiveSupport.page=<<~HTML Heredocs are cool & usefulHTML# "Heredocs are cool & useful\n"page=<<~HTML.strip Heredocs are cool & usefulHTML# "Heredocs are cool & useful"#<< vs <<- (or <<~)# terminating sequence must be at the very beginning of the linedeffooputs(<<TEXT) Hello!TEXTendend#interpolationtype="healthy"table="food"query=<<-SQL SELECT * FROM #{table} WHERE #{type} = trueSQL# You can disable the interpolation by surrounding the heredoc name with single quotes.doc=<<-'TIME'Current time is #{Time.now}TIMEstring=[<<ONE,<<TWO,<<THREE] the first thingONE the second thingTWO and the third thingTHREE=>["the first thing\n","the second thing\n","and the third thing\n"]