写在前面:这里的提取是个人提取(只记录不知道的东西)。
电子书地址:http://railsbook.tw/
提示:在学RUBY基础时,有时不要把它和rails混在一起思考。先有ruby才有rails,ruby不了解rails,但rails很了解ruby....
开发工具和常用指令
-
如果出门在外,忘了带mac,怎么写代码???答案是可以用三线编辑器:
后两款:自带开发环境!!!!
-
常用指令:
-
sudo
暂时取得权限
-
第一个应用程式
scaffold
的作用:自动完成增删改查的功能,包括MVC。在新增migration时,数据类型string可以省略(因为是默认)。
-
N+1查询问题,就是会额外查询关联的资料库,对系统资源很浪费)。解法:
-
用
includes
来减少不必要的资料库查询。def index @posts = Post.all end
改成:(里是关联了user)
def index @posts = Post.includes(:user) end
-
變數、常數、流程控制、迴圈
-
如果想交换x,y两个变数的值,怎么写最ruby???
x, y = y, x
-
if
可以放到程式的后面(这样读起来更像英文文章)a=1 if b > a #如果b > a,那么a = 1
-
三元连算�子:(if ….. else …..这个语法放到同一行)
if a > b a = 1 else a = 2 end #上面的程式码,可以压缩成一行: a > b ? a = 1 : a = 2 #帅到掉渣,有木有!
數字、字串、陣列、雜湊、符號
注意
=
==
的问题。一个是赋值,一个是比较!整数的除法,其中一个数为小数,结果才为小数。
-
取余数
%
- 判断是否为单数:
.odd?
- 判断是否为复数:
.even?
- 判断是否为单数:
四舍五入
.round(x)
字串中要插入变量,可以用
#{}
!!!字串可以直接当成数组来用,取字。
-
如何获得字串的长度:
- 长度:
.size
- 字节:
.bytesize
- 长度:
计算几个字几个单词:
.sqlite.count
-
大小写转换:
- 转大写:
upcase
- 转小写:
downcase
- 转大写:
-
对比首尾字母:
- start_with?
- end_with?
-
替换掉其中的片段:
- 只换第一个:
sub
- 只换第一个:
- 全部换掉:`gsub`
```
puts "PHP is good, and I love PHP".sub(/PHP/, "Ruby")
# sub 只會換掉最先遇到的那個字串
# => 印出「Ruby is good, and I love PHP」
puts "PHP is good, and I love PHP".gsub(/PHP/, "Ruby")
# gsub 會換掉全部符合的字串
# => 印出「Ruby is good, and I love Ruby」
```
-
map
方法示例:list = [1, 2, 3, 4, 5] p list.map { |i| i * 2 - 1 } # [1, 3, 5, 7, 9]
-
reduce
方法示例:(只作数值与index的运算)puts [*1..100].reduce(:+)
-
select
方法示例:(相当于一个过滤器)p [*1..100].select(&:odd?)
-
取随机数的方法:
-
shuffle
洗牌:puts [*1..52].shuffle.first(5)
-
sample
不重复的乱数:puts [*1..100].sample(5)
-
object_id
可以检测是否同一物件。什么是
symbol
:<u>一个带有名字的物件</u>(其他物件都没有名字,只有它有)-
string
与symbol
的对比:- string可以被改变,symbol不行
- symbol可以直接从内存中取得相同的东西,不会像string总是新建物件,所以一定程度上symbol是比较省内存的。
- symbol的比较会比string快!
- string和symbol是可以相互转换的!
方法與程式碼區塊(block)
在 Ruby 執行方法,經常省略小括號,目的是為了讓程式碼看起來更不像程式碼,反而像是一般的文章。
-
定义方法时,可以加个预设值:
def say_something(message = "something") "message: #{message}" end p say_something "hi" # => message: hi p say_something # => message: something
ruby很爱省略小括号和大括号,这里日后可能会掉坑~
-
什么是程式码区块?
{ ... }
以及do ... end
,在 Ruby 稱之一個程式碼區塊(Block) -
程式码区块不是:
不是物件:无法单独存在
-
不是参数:无法当参数,放在方法后一般不会执行。要如何才能执行:
def say_hello puts "開始" yield # 把控制權暫時讓給 Block puts "結束" end say_hello { puts "這裡是 Block" }
6666,原来这两个地方都可以传参数……:
def say_hello puts "開始" yield 123 # 把控制權暫時讓給 Block,並且傳數字 123 給 Block puts "結束" end say_hello { |x| # 這個 x 是來自 yield 方法 puts "這裡是 Block,我收到了 #{x}" }
-
<u>block的物件化:</u>
say_hello_to = Proc.new { |name| puts "你好,#{name}"} say_hello_to.call("尼特羅會長") say_hello_to.call("尼特羅會長") # 使用 call 方法 say_hello_to.("尼特羅會長") # 使用小括號(注意,有多一個小數點) say_hello_to["尼特羅會長"] # 使用中括號 say_hello_to === "尼特羅會長" # 使用三個等號 say_hello_to.yield "尼特羅會長" # 使用 yield 方法
類別(Class)與模組(Module)
类别
-
什么类别:
物件(object) = 狀態(state) + 行為(behavior)
一个精妙的类比:
不知道大家有沒有在夜市有看過或吃過雞蛋糕,有小貓、小狗等可愛動物造型,只要把調配好的麵粉糊倒進模具,蓋上蓋子,幾分鐘後就會有香噴噴又造型可愛的雞蛋糕可以吃了。
那個烤盤模具,就是類別(Class)的概念。如果沒意外,一樣形狀的模具,放一樣的原料進去,做出來雞蛋糕的型狀應該都會長得一樣。而這個做出來的雞蛋糕,以物件導向程式設計的概念來說便稱之「實體(Instance)」。
-
传参数初始化:
class Cat def initialize(name, gender) @name = name @gender = gender end def say_hello puts "hello, my name is #{@name}" end end kitty = Cat.new("kitty", "female") kitty.say_hello # => hello, my name is kitty
-
attr_accessor
的作用:帮助设定和取用实体变数的值!(ruby没有【属性】一说!)
所以,以下这个:
class Cat def initialize(name, gender) @name = name @gender = gender end def say_hello puts "hello, my name is #{@name}" end def name @name end def name=(new_name) @name = new_name end end kitty = Cat.new("kitty", "female") kitty.name = "nancy" puts kitty.name # => nancy
可以直接变成:
class Cat attr_accessor :name def initialize(name, gender) @name = name @gender = gender end def say_hello puts "hello, my name is #{@name}" end end
有了这个设定后,我们就可以直接用这个参数,像属性一样方便用!!!
-
什么实体方法,什么是类别方法:
作用在实体上的方法,叫做:实体方法。
-
作用在类别上的方法,叫做:类别方法。这个有几种表现:
class Cat def self.all # ... end end
- ``` class Cat class << self def all # ... end end end
有很多类别方法时,可以用这种!
继承:可以让代码更简洁
open class: 可以方便地为方法“加料”!
-
如果想要分开定义一些方法,可以用到模组,方法:
module Flyable def fly puts "I can fly!" end end
class Dog include Flyable end
-
模组和类别的不同之处:
- 模组没办法
new
一个新的实体出来。 - 模组没办法继承别的模组。
- 模组没办法
-
定义外部键时,使用
references
来自动增加外部键:rails g model post user:references
这样,
references
会做多两件事:- 自动加上索引,加快查询速度。
- 自动帮model加入关联。
Layout,Render 與 View Helper
-
在特定的controller 的action里,如何你想用不同的layout可以这样:
class CandidatesController < ApplicationController def index @candidates = Candidate.all render layout: "backend" end # ...[略]... end
-
如果想给每个页面定义网页title,这个好!可以这样做:
- 方法1:使用 provide:
<!DOCTYPE html> <html> <head> <title><%= yield :my_title %></title> <%= csrf_meta_tags %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> </head> <body> <div class="container"> <%= yield %> </div> </body> </html>
<% provide :my_title, "你好,我是 Title" %> <h1>候選人列表</h1> <%= link_to "新增候選人", new_candidate_path %> <table class="table"> <thead> <tr> <td>投票</td> <td>候選人姓名</td> ...[略]...
- 使用 content_for:
<% content_for :my_title do %> 你好,我是 Title <% end %> <h1>候選人列表</h1> <%= link_to "新增候選人", new_candidate_path %> <table class="table"> <thead> <tr> <td>投票</td> <td>候選人姓名</td> ...[略]...
-
更好地用
render
:- partial里尽量用区域变量。
- 使用时再传递这个变量。
例子:
<div class="advertisement"> <div>廣告</div> <div> <%= content %> </div> </div>
<%= render "banner", content: "我是廣告的內容" %>
- partial里有一个
collection
的方法,使用时传递这个参数,就可以迭代输出partial。(回圈效果)
<%= render partial: "candidate", collection: @candidates %>
这里还可以简化成:
<%= render @candidates %>
但要满足以下条件:(利用了rails的惯例)
-
_xxx.html.erb
的名字必须是这包资料的<u>单数</u> - 位置必须放在同一目录下。
-
_xxx.html.erb
里不要写回圈,里面的区域变数必须是单数。
善用
View Helper
!
待续……