Day15 心得体会&读书笔记

一、心得体会
1、今天完成了什么?

  • 看了Ruby核心、Duck typing、类与对象、RUby安全
  • 看10个controller

2、今天收获了什么?

  • 类对象的类型不是类
  • 什么是module
  • 什么是代理类
  • 10个controller:工单日志(Ticketschanges)、工单(tickets)、加急原因、登记、仓库(warehouses)、话术(words)、师傅(workers)、小组规则、案例标签(case_tags)、案例(cases)
    3、今天犯了哪些错误?
    4、今天的状态如何?
  • 今天状态爆表,看完了镐头书,还把rails-guide快速浏览了一遍,觉得比镐头书要容易些,两天内看完。
    5、明天还需要做什么?
  • 明天好好计划怎么在两天之内把rails书看完
  • 计划看一半

二、读书笔记
22.6 方法参数
22.7 调用方法(Invoking a Method)
开头的形参将被赋值给方法的实际参数,这些形参后面可以有一个key=>value配对的列表,这些key=>value对被将收集到一个新的Hash对象中,并作为一个形参传入方法。

这些形参后面可以是一个前面带星号的参数,如果这个形参是一个数组,那么Ruby将用相应的数组元素,将它替换为零或多个形参。

def regular(a, b, *c)
end

block可以关联一个方法调用,该调用可以使用字面量形式的block(它必须和调用的最后一行在同一行上),也可以关联一个参数,该参数包含带有&符号的Proc或Method对象的引用,不管block参数存在与否,Ruby使用全局函数Kernel.block_given?的值来判断是否存在与本调用相关联的block。

a_proc = lambda{ 99 }
an_array = [ 98, 97, 96]
def block
  yield
end
block { }
block do
end
block(&a_proc)

def all(a, b, c, *d, &e)
  puts "a = #{a.inspect}"
  puts "b = #{b.inspect}"
  puts "c = #{c.inspect}"
  puts "d = #{d.inspect}"
  puts "block = #{yield(e).inspect}"
end

all('test', 1 => 'cat', 2 => 'dog', *an_array)
Foo.bar() #方法调用
Foo.bar #方法调用
Foo::bar() #方法调用
Foo::bar #访问常量

方法的返回值是执行的最后一个表达式的值。

return []

return表达式会立即退出方法,如果不带参数调用return,则return的返回值为nil,如果带一个参数,则返回该参数的值,如果参数多于一个,则返回一个包含所有参数值的数组。

22.7.1 super
在方法体内,调用super就像调用原方法一样,不过是在含有原方法的对象的超类中搜索方法体,如果没有参数(且未加括号)传递给super,则原方法的参数将作为super的参数,否则,super的参数将被传递。

22.7.2 操作符方法(Operator Methods)

如果操作符表达式中的操作符是一个可重新定义的方法,Ruby像调用如下表达式那样执行操作符表达式。

22.7.3 属性赋值(Attribute Assignment)

当receiver.attrname作为左值出现时,Ruby将调用接收者中名为attrname=方法,并以右值作为其唯一参数,这种赋值语句的返回值是rvalue的值——attrname=的返回值将被抛弃。

如果你想访问返回值(多半情况下不是rvalue的值),那么向方法发送一个显式的消息

class Demo
  attr_reader :attr
  def attr=(val)
    @attr = val
    "return value"
  end
end

d = Demo.new

22.7.4 元素引用操作符(Element Reference Operator)

receiver[expr[,expr]...]
receiver[expr[,expr]...] = rvalue

当用作右值时,元素引用调用接收者的[]方法,并以方括号中的表达式作为参数传递。## ????不懂

22.8 别名(aliasing)
alias new_name old_name

将创建一个引用已有的方法、操作符、全局变量或正则表达式向后引用的新名字

当为方法起别名字,新的名字将指向原方法体的一个拷贝,即使后来方法被重新定义了,别名仍旧会调用原来的方法实现代码。

def meth
  "original method"
end
alias origi meth

def meth
  "new and improved"
end

meth

origi

22.9 类定义(Class Definition)
Ruby的类定义通过执行类代码体创建或者扩展类Class的对象。第一种形式中,一个命名类将被创建或扩展。生成的对象将被赋给名为classname的常量。

这个名字应该以一个大写字母开头,在第二种形式中,一个匿名类会和指定的对象相关联。

如果superexpr存在,那么它应当是一个以Class对象为结果的表达式,而且它也将是被定义的类的超类,如果省略了superexpr,则默认为类Object。

在方法体内,随着各种定义代码的读入,大多数Ruby表达式将被执行。然而:

  • 方法定义将在类的对象的一个表中注册该方法。
  • 嵌套的类和模块定义将被存储在类的常量中,而不是全局常量中。
module NameSpace
  class Example
    CONST = 123
  end
end

obj = NameSpace::Example.new
a = NameSpace::Example::CONST
  • 方法Module#include将把命名的模块添作被定义的类的匿名超类。

  • 使用域作用符(::)可以为类定义中的classname前置一个已存在的类或模块名。这种语法会将新的定义插入到前面已定义的模块或类的名字空间,但不是在这些外部类的作用域中解释此定义。

  • 在下面的例子中,类C被插入到模块A的作用域,但并不是A的上下文中进行解释。结果,对CONST的引用被解释成该名字对应的顶层常量而不是A的常量,而且我们必须使用单例方法的全名,因为在A::C的上下文,C本身不是一个已知的常量。

CONST = "outer"
module A
  CONST = "inner"
end

module A
  class begin
    def B.get_const
      CONST
    end
  end
end

A::B.get_const

class A::C
  def (A::C).get_const
    CONST
  end
end

A::C.get_const

22.9.1 从类中创建对象(Creating Objects from Classes)

类class定义的实例方法class#new将被创建接收者对应的类的对象。这是通过调用classexpr.allocate来完成的,你可以重载此方法,但是你的实现必须返回正确的类的对象,然后它调用新创建的对象的initialize,并将传递给new的参数传递给initialize。

如果类定义中重载了类方法new,并且new没有调用super,那么将无法创建该类的对象,并且调用new将返回nil。

和其他方法一样,initialize应该调用super,以保证父类被适当的初始化,如果父类是Object,则不需要这么做,因为Object类不做任何实例相关的初始化。

22.9.2 类属性声明(Class Attribute Declarations)
类属性声明不是Ruby语法的一部分:它们不过是定义在类Module中的方法,该方法会自动创建访问类属性的方法。

class name
  attr attribute
  attr_reader attribute
  attr_writer attribute
  attr_accessor attribute
end

22.10 模块定义(Module Definitions)

module name
  body
end

模块基本上是一个不能被实例化的类,和类一样,在定义过程中模块体将被执行,生成的模块Module对象被存储在一个常量中,模块中可以含有类方法和实例方法。也可以定义常量和类变量。和类一样,通过使用Module对象作为接收者调用模块方法,通过使用“::”域作用符来访问常量。

CONST = "outer"

module Mod
  CONST = 1
  def Mod.method1
    CONST + 1
  end
end

module Mod::Inner
  def (Mod::Inner).method2
    CONST + " scope"
  end
end

Mod::CONST
Mod.method1
Mod::Inner::method2

22.10.1 Mixins——混入模块(Mixins——including Modules)

class | module name
  include expr
end

使用include方法可以将一个模块包含到另一个模块或者类的定义中,含有include的模块或类定义可以访问它所包含模块的常量、类变量和实例方法。

如果一个模块被包括到一个类定义中,那么模块的常量、类变量和实例方法实际上被绑定到该类的一个匿名(且不可访问)超类中,类的对象会响应发送给模块实例方法的消息。

模块函数

尽管include在提供mixin功能时很有用,它也可以把模块的常量、类变量和实例方法带入到另一个名字空间中,然而,实例方法定义的功能不能通过模块方法的实现。

module Math
  def sin(x)
  end
end

方法Module#module_function通过拷贝一个或多个模块实例方法的定义来创建相应的模块方法来解决问题。

module Math
  def sin(x)
  end
end

实例方法和模块方法是两个不同的方法:方法定义被module_function拷贝出来而不是建立别名。

访问控制

22.12 Blocks,Closure和Proc对象

代码block是closure;它能记住其被定义时的上下文,并在被调用时使用该上下文。上下文中包含self的值、常量、类常量、局部变量和任意被截获的block。

class Holder
  CONST = 100
  def call_block
    a= 101
    @a = 102
    @@q = 103
    yield
  end
end


class Creator
  CONST = 0
  def create_block
    a = 1
    @a = 2
    @@a = 3
    proc do
      puts "a = #{a}"
      puts "@a = #@a"
      puts "@@a = #@@a"
      puts yield
    end
  end
end

block = Creator.new.create_block { "original" }
Holder.new.call_block(&block)

返回结果:

a = 1
@a = 2
@@a = 3
original

WHY?????

22.12.1 Proc对象,break和next
什么是block?
是和方法相关联的一堆代码,并在它们被定义的上下文运作。

Block不是对象,但是它们能被转换成类proc的对象。

有3中方式将block转换成proc对象。

  • 通过传递block给一个方法,该方法的最后一个参数前有一个地址符&。该参数会接受block作为Proc对象。
def meth1(p1, p2, &block)
  puts block.inspect
end

meth1(1,2) {"a block"}
meth1(3,4)
  • 通过调用Proc.new,再将它和block关联。
block = Proc.new { "a block" }
block
  • 通过调用方法Kernel.lambda关联block到方法调用
block = lambda{ "a block" }
block

前面两种风格的Proc对象在使用时是相同的。我们称这些对象为raw procs。第三种风格,由lambda生成,为了Proc对象添加一些额外的功能,我们很快就能看到,我们称这种对象为lambdas。

无论在哪种block内,next语句将退出block。block的值是传递给next的值,如果没有值传递给next,则为nil。

def meth
  res = yield
  "The block returns #{res}"
end

meth {next 99}

pr = Proc.new {next 99}
pr.call

pr = lambda {next 99}
pr.call

在raw proc中,break语句可以终止调用block犯法,方法的返回值为传递给break的参数。

22.12.2

return和block

处于作用域block内的return和该作用域的return一样,block内原上下文不再有效的return会引发异常。

22.13 引发异常(Raising EXceptions)

raise
raise string
raise thing

第一种形式重新引发$!中存储异常,如果$!是nil,则引发一个新的RuntimeError。
第二种形式创建一个新的RuntimeError异常,并设置其消息为给定的字符串。
第三种形式通过在其第一个参数上调用Exception方法创建一个异常对象,然后设置异常消息和调用栈为第二个和第三个参数。

类Exception和其对象含有一个称为exception的工厂方法,所以异常类的名字和实例可以用作raise的第一个参数。
当异常发生时,Ruby会将异常对象的引用存储在全局变量$!中。

22.13.2 处理异常(HandingExceptions)

rescue expr

Rescue语句修饰符

一条语句可以含有一个可选的rescue修饰符,该修饰符后跟另一条语句。

22.14 Catch和Throw
方法Kernel.catch将执行与之相关联的block。
catch (symbol | string) do
block
end

方法Kernel.throw将中断语句的正常执行。
throw(symbol | string[, obj])

当throw执行时,Ruby在调用栈中向上搜索直到找到匹配符号或字符串的第一个catch block。

如果找到,则搜索结束,并从被捕获的block后面继续执行,如果throw的第二个参数存在,那么它的值将作为catch的值返回。

第23章 Duck Typing

你应该注意到:Ruby中没有声明变量和方法的类型。

23.1 Classes aren't types
duck typing哲学:对象的类型是根据它能做什么而不是根据它的类决定的。

23.3 标准协议和强制转换

Ruby提供了转换协议(conversion protocals)的概念——对象可以选择把自己转换成另一个类的对象。

Ruby有三种标准的方式实现它。

我们已经遇到了第一种:to_i和to_s方法分别把他们的接收者转换成字符串和整数。

这些转换方法不是严格的:比如,如果对象有某种得体的字符串表示,它可能会有to_s方法。

为了返回数字的字符串表示,我们的Roman类可能会实现to_s方法。

第二种形式的转换函数使用名字如to_str何to_int的方法。

class OneTwo
  def to_ary
    [1, 2]
  end
end

ot = OneTwo.new
a, b = ot

puts "a = #{a}, b = #{b}"
printf("%d--%d\n", *ot)

to_hash
to_int
to_in
to_proc

23.3.1 数字强制转换

coerce

23.4 该做的做,该说的说(Walk the walk, Talk the Talk)

第24章 类与对象

类与对象无疑是Ruby的中心,但是第一眼看上去可能让人有点困惑,

一个RUby对象有三个部分:一组标志、一些实例变量、以及相关联的类。

24.1 类与对象是如何工作的

所有的类/对象的交互,都是使用上面给出的简单模型解释的:对象引用类,而类引用零个或多个类,不过,实现细节可能有些诡异。

一个基本对象、以及它的类和超类

image.png
class Guitar
  def paly()

  end
end

lu = Guitar.new

24.1.1 你的基本的、日常对象(Your Basic, Everyday Object)

24.1.2 什么是Meta(What's the Meta?)

24.1.3 特定于Object的类(Object-Specific Classes)
Ruby允许你创建一个和特定对象绑定的类。

24.1.4 Mixin

24.1.3 扩展对象(extending objects)

24.4 继承与可见性(Inheritance and Visibility)

关于类继承最后一个诡秘的地方,十分含糊。

在一个类定义中,你可以修改祖先类中方法的可见性,例如,你可以像下面这样:

class Base
  def aMethod
    puts "Got here"
  end
  private :aMethod
end


class Derived1 < Base
  public :aMethod
end


class Derived2 < Base
end

在这个例子中,我们可以调用D1类实例中的aMethod,但不能通过Base或D2的实例来调用它。

那么Ruby是如何辗转让一个方法有两个不同的可见性呢?

如果一个子类改变了父类中某个方法的可见性,Ruby实际上在子类中插入了一个隐藏的代理方法,使用了super调用原来的方法,然后,它将这个代理的可见性设置为你所需要的。这意味着,下面的代码:

class Derived1 < Base
  public :aMethod
end

实际上等同于:

class Derived < Base
  def aMethod(*arg)
    super
  end
  public :aMethod
end

super调用可以访问父类中的方法,而不管其可见性,所以重写方法可以让子类覆写父类中的可见性规则。

24.5 冻结对象(freezing Objects)

有时候你费尽力气才让你的对象完全正确,如果允许其他人可以改变它。

第25章 Ruby安全

Walter Webcoder是一个非常棒的想法:

require 'benchmark'
include Benchmark

test = "Stormy Weather"
m = test.method(:length)
n = 100000

bm(12) { |x|
  x.report("call") {n.times {m.call}}
  x.report("send") {n.times {test.send(:length)}}
  x.report("eval") {n.times {eval "test.length"}}
}

26.4 系统钩子(System Hooks)

钩子是一个跟踪(trap)一些Ruby事件的技术,比如跟踪对象创建,在Ruby中,最简单的hook技术是截取程序执行的系统命令,可能你想记录程序执行的所有操作系统命令。

只要重命名Kernel.system方法,用你自己的Kernel.system替换它就可以了。

module Kernel
  alias_method :old_system, :system
  def system(*arg)
    result = old_system(*arg)
    puts "system(#{args.join(', ')}) returned #{result}"
    result
  end
end
system("date")
system("kan", "happ")

26.6 列集和分布式Ruby

Java提供了序列化(serialize)对象的特性,可以在某处保存对象,并且需要的话可以重建(reconstitute)它们,比如可以使用这个功能保存一个对象树,这些对象树表示某部分程序的状态——一份文档、一小段音乐

Ruby把这种类型的序列化成为列集(marshaling)。可以使用Marshal.dump方法来保存一个对象和它的部分或所有组成对象(component)。

26.6.3分布式Ruby(Distributed Ruby)
使用drd的Ruby进程可能会作为服务器、客户机或者两者都是,drd服务器是对象的源,而客户机是对象的使用者,对客户机来说。

26.7 编译时?运行时?任何时?(Compile、Runtime、Anytime)

使用Ruby要记住的一件重要事情是:在“编译时”和“运行时”之间没有太大的差别,它们都是相同的,可以向一个正运行的进程添加代码。

方法

  • sort! 对数组进行排序,在排序的过程中arr将被冻结
a = ['a', 'b', 'e', 'c']
a.sort! -> ["a", "b", "c", "e"]
a -> ["a", "b", "c", "e"]

如果去掉!,a的状态不变

a = ['a', 'b', 'e', 'c']
a.sort -> ["a", "b", "c", "e"]
a -> ['a', 'b', 'e', 'c']

Rails-guide

  • 5分钟快速浏览
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 一、心得体会1、今天完成了什么? 今天看了20页的镐头书(139-160) 看了10个controller 2、今...
    柳辉阅读 317评论 0 0
  • 一、读书笔记3.4 剩余部分当对象需要访问同类的其他对象的内部状态时,使用保护访问(protected acces...
    柳辉阅读 362评论 0 0
  • 一、心得体会 今天完成了什么 看了20页的镐头书 学了bag的10个controller 收获什么? 新增、编辑都...
    柳辉阅读 339评论 0 0
  • 一、心得体会1、今天完成了什么? 看了6个小时的镐头书18章、21章、22章,我想快速把书看一遍,然后看看哪些是需...
    柳辉阅读 396评论 0 0
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,852评论 6 13