Ruby
Array和Hash
a = %w{ ant bee cat }
使用symbol在hash中定义key有两种方法:
hashtable1 = {
:symbol1 => 'Haha'
:symbol2 => 'Heihei'
}
hashtable2 = {
symbol1: 'Haha'
symbol2: 'Heihei'
}
第一种方法适用于任何情况,第二种只适合symbol。
redirect_to action: 'show', id: product.id
上面这个redirect_to命令传入了两个hash,一个是key为:action值为'show',另一个是key为:id值为product.id。
正则表达式:
Block
hello('Geurney') {puts 'Hi'}
block会在函数的yield的地方执行,可以给block传参数,例如:
animals.each {|animal| puts animail }
3.times {puts 'Hi'}
如果让block作为函数参数时,在定义函数时要使用&:
def hello &block
3.times(&block)
end
在调用函数时使用:
hello {puts 'Hi'}
异常处理
使用raise方法抛出异常,将会抛出异常的方法放在begin...end中,用rescue来捕获异常:begin
content = load_blog_data(file_name)
rescue BlogDataNotFound
STDERR.puts "File #{file_name} not found"
rescue BlogDataFormatError
STDERR.puts "Invalid blog data in #{file_name}"
rescue Exception => exc
STDERR.puts "General error loading #{file_name}: #{exc.message}"
end
也可以在方法中直接使用:
rescue StandardError => e
可以简写为:
rescue => e
类
class Order < ActiveRecord::Base
has_many :line_items
def self.find_all_unpaid
self.where( 'paid = 0' )
end
def total
sum = 0
line_items.each {|li| sum += li.total}
sum
end
end
在上面这个例子,定义了Order这个类,这个类继承自来自ActiveRecord module 的Base类。在一个module可以定义很多类。::这里来确定命名空间。
has_many是ActiveRecord module里的方法,传入了一个:line_items的参数。has_many方法在Order类定义时被调用,像这样在类定义时调用的class-level的方法称为declaration。
用self作前缀的方法是类方法,类方法只能通过类名调用。在类方法中,访问成员变量不报错但是没有值,self指代的是类。
非类方法默认是public,self指代的是instance。
使用@定义的成员变量只能在类内访问,如果要在类外访问,需要定义方法,或者使用attr定义:
class Greeter
def initialize(name)
@name = name
end
def name
@name
end
def name=(new_name)
@name = new_name
end
end
上面是用方法定义的getter和setter。
class Greeter
attr_accessor :name
attr_reader :greeting
attr_writer :age
这里使用attr_accessor定义了getter和setter,greeting只提供了getter,而age只提供了setter。
即可以使用.greeting来访问greeting的内容,使用.age=(17)来设置age的值。
注意这里的成员变量不是symbol,因为symbol是常量。没有用@标志的变量是局部变量。注意使用.to_s等类型转换。
@@标记的是类变量。
Access Control
public方法可以在类外访问private方法只能在类内使用,使用时只能implicitly,不能使用self.来explicitly调用,不能调用其他instance的private方法(区别于protected方法)。
def hello
hi #OK
self.hi #Not OK
end
private
def hi
end
protected方法只能在类内使用,使用时可以explicitly指明是在哪个instance上调用,如果是implicitly相当于是self的explicitly。
def compare(another_instance)
self.age.to_i > another_instance.age.to_i
end
protected
def age
@age
end
上面定义了age方法是protected的,在compare方法中传入了另一个instance,可以用调用self的age方法也可以,调用另一个instance的age方法。
将accessor设置为protected或private:
class Test
attr_accessor :age
protected :age
end
上述定义了成员变量age,然后将age的accessor定义为了protected。好像只能这样使用该语法。
module
module可以包含方法、常量、module和类定义。但module不能被实例化。module可以提供namespace和功能。
Rails可以自动将helper module和对应的view template链接起来。例如你写了一个helper的方法,你想在你的controller中控制view时调用这个方法,你就可以将你的helper方法加入到app/helpers目录下对应controller的ControllerHelper.rb文件中。
YAML是ruby library的一个module,用来写数据库、测试数据等的配置文件,文件后缀名为yml。例如:
development:
adapter: sqlite3
database: db/development.sqlite3
pool: 5
timeout: 5000
yml文件需要注意缩进,存储的是key/value pair。
最后一个例子
class CreateProducts < ActiveRecord::Migration
def change
create_table :products do |t|
t.string :title
t.text :description
t.string :image_url
t.decimal :price, precision: 8, scale: 2
t.timestamps
end
end
end
上面定义了CreateProducts类,这个类继承自ActiveRecord module的Migration类,定义了一个change方法。这个方法调用了Migration的create_table类方法,将一个products的table以symbol的形式作为参数,并提供了一个block。当这个block被调用时,将一个object传给了t,然后依次定义t的各个field,如:title、:description等。而t.decimal 还传入了两个hash作为参数,一个是precision=>8,一个是scale=>2。
或运算
a||b,如果a不为nil或者false,则返回a。否则返回b
a ||= b,如果a没有被赋值,则赋值为b,否则还是a。