Ruby
Ruby (todo)
Links
Style Guide https://github.com/styleguide/ruby
Were to find tools/library: https://www.ruby-toolbox.com/
Debug
pry + http://cirw.in/blog/pry-to-the-rescue (debug your ruby code live)
letters: http://lettersrb.com/api
irb: _
is the last result.
Variable
global variable
instance variable, using "@", accessing it by using "self." You don't need to declare it somewhere, just use it.
Be careful, as you cannot simply declare and use it. It becomes not nil only after it's be assigned. (http://stackoverflow.com/questions/826734)
if using "attr_accessor", the variable becomes a C# property. Then we can use it by using "@"
class(static) variable: @@ (attribute all)
class(static) method
class
By default, variable inside class are protected
:count is a symbol. A Ruby symbol is a thing that has both a number (integer) representation and a string representation.
ruby constructor:
def initialize(a, b) self.a = a end
how to new:
person = Person.new("a","b")
C# params:
public string Concat(params String[] items) -> def concat(*items) result = "" items.each do |item| result += item end result end
Method can be called without writing parentheses:
results = method_name parameter1, parameter2 # calling method, not using parentheses
Another technique that Ruby allows is to give a Hash when invoking a function, and that gives you best of all worlds: named parameters, and variable argument length.
def accepts_hash( var ) print "got: ", var.inspect # will print out what it received end accepts_hash :arg1 => 'giving arg1', :argN => 'giving argN'
You see, the arguments for accepts_hash got rolled up into one hash variable. This technique is heavily used in the Ruby On Rails API. Use Hash to remove arguments order dependency. The above lines are equivalent to the more verbose ones:
accepts_hash( :arg1 => 'giving arg1', :argN => 'giving argN' ) # argument list enclosed in parens accepts_hash( { :arg1 => 'giving arg1', :argN => 'giving argN' } ) # hash is explicitly created
how to write block?
items.each { |item| result += item } items.each do |item|
block: the yield
statement actually calls the block
def do_twice yield yield end do_twice {puts 'hola'} # the block will be called twice because of two yields.
convert a block to a Proc: using lambda block is like a unborn Proc. source
say = lambda { |something| puts something }
how to patch class?
class << ThisIsAClassBeingPatched def new_method puts 'new method' end end
scope
!! NOT TURE a block can overrite the variable
f = 'a' ['a', 'b', 'c'].each do |f| puts f end puts f # f is now 'c'
if
doesn't introduce new scope!
if k.start_with? "0x" value = k.to_i(16) else value = k.to_i(2 end puts value
statement
"unless" is a negation of "if"
you can/should put "unless" and "if" at the end of the statement, like English:
puts "it's valid" if is_valid
puts "it's not valid" unless is_valid
you can put them together:
puts "do this if a is true and b is not true" if a unless b
ruby range:
<< is a concat method, it works with string too: a = “b" a << "c"
how to do swtich/case? it is called case..when in Ruby:
===, triple equal, longer rope but sags in the middel, which means it is more flexible than equal. It means included.
assert( (1900..1930) === 1918, true)
exception handling:
throw exception:
fail 'message'
yield is used to invoke block
Ultimately blocks are really just an implementation of the strategy pattern.
使用最新的lambda字面量语法。
lambda = ->(a, b) { a + b } lambda.(1, 2)
使用_来表示无用的代码块参数。
result = hash.map { |_, v| v + 1 }
string difference between single quote and double quote:
single quote: no interpolation: '#{my_name}' => #{my_name}
single quote: no interpolation so no escaping. '\n' => \n
"".empty? is true; ni.to_s.empty? is true
nil
nil.empty? throws exception. You'll have to use nil.nil?
**only nil and false evaluates false in if statement; everything other object (including 0) evaluates therubygame.
shortcut p :name
is the same as puts :name.inspect
parentheses in Ruby are optional:
stylesheet_link_tag("application", :media => "all") is the same as stylesheet_link_tag "application", :media => "all"
when hash are the last argument, the curly brases are optional
stylesheet_link_tag "application", { :media => "all" } is the same as stylesheet_link_tag "application", :media => "all"
collection
Array (like C# List)
Enumerable
condition
find(return the first), select/find_all(return all)
transform
map:
[1, 2, 3, 4].map { |i| i.to_s }
or[1, 2, 3, 4].map(&:to_s)
What is Enumerable.inject or reduce?? There is alow a each_with_object method:
use a memo to combine all elements.
if using block, pass 'memo' and 'object'
array.inject({}).{|memo, object| do_something_to_h_using_a; h}
array.each_with_object({}) {|a, h| do_something_to_h_using_a} # <= h not here
Hash (key value pair)
Set (unordered value with no duplicates, like HashSet in C#)
?? Class inheritance
example:
how does Ruby know employee has a vacation_days method? duck typing.
Metaprogramming
TODO
Ruby class:
String < Object < BasicObject
use
superclass
to get its super class
singleton methods: methods defined to a particular object.
animal = 'cat' def animal.speak puts 'miaow' end animal.speak
class << foo
opens foo's singleton class (eigenclass). class << self opens up self's singleton class, so that methods can be redefined for the current self object (which inside a class or module body is the class or module itself). Usually, this is used to define class/module ("static") methods:
class String class << self def value_of obj obj.to_s end end end String.value_of 42 # => "42"
module: module Mod def meth 'lala' end end usage: Mod.meth include a module makes module a super class of the target class: class Object < BaseClass after include module: class Object < Module < BaseClass
mixins: include the module then module methods become instance methods. class Song include Mod end s = Song.new s.meth
How to test a single method from a module?
Module Foo def get_file; end def self.get_file_can_call_directly; end end Class.new.extend(Foo).get_file Foo.get_file_can_call_directly
How to create a method that creates methods? The following creates instance methods
def define_methods_for_enviroment(names) names.each do |name| class_eval <<-EOS def #{name} data[env]['#{name}'] end EOS end end
extend
vs include
extend
will make the methods available to class level: add as class methodsNOTE
a.extend model_b
is different, it'll add instance methods to the object a.inlucde
will add as instance methods
string
String#split: if passing a empty delimiter, string is splitted as characters if no spaces
'abc'.split => ['a', 'b', 'c'] 'ab c'.split => ['ab', 'c']
path
Use require_relative
to load file
require_relative '../lib/cmd'
regex
Use match
or =~
(equals-tilde operator) to match regex;
match
returns MatchObject or nil, it returns the 1st match=~
returns matched position number in int or nilmatch
returns MatchData, where the 1st is the entire match string and others are matches.'B0'.match /([A-Z])([0-9])/ => #
Use scan
to return all match results.
str.match[2] reads much nicer than str.scan[0][1]. ruby-1.9.2-p290 :002 > 'a 1-night stay, a 2-night stay'.scan(/(a )?(\d)[- ]night/i).to_a => [["a ", "1"], ["a ", "2"]] ruby-1.9.2-p290 :004 > 'a 1-night stay, a 2-night stay'.match(/(a )?(\d)[- ]night/i).to_a => ["a 1-night", "a ", "1"]
How
check null and if not null check other property:
if user && user.authenticate(params[:session][:password])
assign to a value if it's nil but otherwise leave it alone.
a = @current_user ||= find_by_id(1)
different return value
first, *rest = ex.split(/, /)
array slice
users[2..40]
Use hash and lambda for rules: how rubygem "> 1.3" works (from rubygems::requirement.rb)
OPS = { #:nodoc: "=" => lambda { |v, r| v == r }, "!=" => lambda { |v, r| v != r }, ">" => lambda { |v, r| v > r }, "<" => lambda { |v, r| v < r }, ">=" => lambda { |v, r| v >= r }, "<=" => lambda { |v, r| v <= r }, "~>" => lambda { |v, r| v >= r && v.release < r.bump } }
def satisfied_by? version
end
Use hash to represent rules: how do you implement the rock/scissors/paper rules?
this two line provide both rule and the list of possible throws
How to colorize text
'colorize' gem NOTE on windows you need to manually require 'win32console' when using it, as 'colorize' only checks if RUBY_PLATFORM =~ /win32/ and in some cases RUBY_PLATFORM returns i386-mingw32.
Last updated