1.rails中使用bootstrap
2.局部變量和塊
3.flash用法
4.email.downcase
5.對(duì)象屬性
6.限制方法
7.改變淘寶源
8.send email
9.if語(yǔ)句使用賦值語(yǔ)句
10.使用tag
11.Kernel中的module function
12.render partial
1.rails中使用bootstrap
#gemfile中添加gem
gem 'bootstrap-sass'
#定義自定義的custom.css.scss
#如上文件中,添加如下代碼,這兩行代碼會(huì)引入bootstrap框架
@import "bootstrap-sprockets";
@import "bootstrap";
#下拉框生效
#application.js中引入bootstrap的javascript庫(kù)
//= require bootstrap
2.局部變量和塊
局部變量可以被代入塊中,但是塊中的局部變量不能被帶出塊的作用范圍內(nèi),其實(shí)這是閉包的知識(shí)
class Demo
number = 2
define_method :my_method do
puts number
person = "this is the demo"
end
Demo.new.my_method
puts person
end
#上面的代碼執(zhí)行結(jié)果如下:
#2
#undefined local variable or method 'person'
3.flash用法
class PostsController < ActionController::Base
def create # save post
flash[:notice] = "Post successfully created"
redirect_to @post
end
def show
end
end
#show.html.erb
<% if flash[:notice] %>
<div class="notice">
<%= flash[:notice] %>
</div>
<% end %>
4.email.downcase
疑惑:是第二個(gè)email是何種表示形式,是一個(gè)局部變量,還是一個(gè)方法
before_save{self.email = email.downcase}
追根溯源,在這本書(shū)的第四個(gè)章節(jié),找到這段代碼的最初解釋:
class Word < String
# 如果字符串和反轉(zhuǎn)后相等就返回 true
def palindrome?
self == self.reverse # self 代表這個(gè)字符串本身
end
end
s = Word.new("level") # 創(chuàng)建一個(gè) Word 實(shí)例,初始值為 "level"
s.palindrome? # => true
根據(jù)第四章的解釋,self代表的就是對(duì)象本身,在類中調(diào)用方法或訪問(wèn)屬性時(shí)可以不用 self(賦值時(shí)不行)。
下面的語(yǔ)句是等價(jià)的:
self == self.reverse
self == reverse
下面的兩條語(yǔ)句也是等價(jià)的:
#左側(cè)的self是必須,右側(cè)的self是可選的
self.email = email.downcase
self.email = self.email.downcase
為什么左邊的self是必須的,如果沒(méi)有 self,創(chuàng)建的是一個(gè)局部變量。
使用 self 的目的是確保把值賦給用對(duì)象屬性。
在元編程的書(shū)(中文第二版p220):
class MyClass
attr_accessor :my_attribute
def set_attribute(n)
my_attribute = n
end
end
obj = MyClass.new
obj.set_attribute(10)
obj.my_attribute #=>nil
其中這條語(yǔ)句:
my_attribute = n
不確定是想給局部變量賦值,還是調(diào)用名為my_attribute=的擬態(tài)方法
在沒(méi)有確定答案的情況下,Ruby默認(rèn)選擇第一種方法,它定義了一個(gè)名為my_attribute的局部變量。
為了避免這個(gè)問(wèn)題,給當(dāng)前對(duì)象的屬性賦值時(shí),應(yīng)該顯性地使用self,代碼如下所示:
class MyClass
attr_accessor :my_attribute
def set_attribute(n)
self.my_attribute = n
end
end
obj = MyClass.new
obj.set_attribute(10)
obj.my_attribute #=>10
這也是為什么在上面的代碼中,左側(cè)的self不能省略的原因。
5.對(duì)象屬性
對(duì)象的屬性:一個(gè)對(duì)象的外部可見(jiàn)部分被稱其為屬性。ruby通過(guò)對(duì)象的實(shí)例變量來(lái)表示對(duì)象的內(nèi)部狀態(tài),即,屬性。
既然是對(duì)外部可見(jiàn)的。Ruby中,實(shí)例變量無(wú)法直接為對(duì)象外使用,只能通過(guò)對(duì)象定義的操作方法訪問(wèn)。
同理,實(shí)例變量也不能變成public變量,同樣是通過(guò)方法訪問(wèn),那就是可以通過(guò)某種方式讀取和修改的。
Ruby中是通過(guò)定義方法來(lái)訪問(wèn)屬性。有兩種方法方式
1.直接定義類屬性的方法
2.通過(guò)Module的方法定義
1.直接定義類屬性的方法:
#這個(gè)就是定義一個(gè)對(duì)象的實(shí)例變量name,作為T(mén)est的屬性
class Test
def initialize(name)
@name=name
end
def name
@name
end
def name=(att)
@name=att
end
end
2.通過(guò)Module的方法定義
class Test
attr_accessor :name
#attr_accessor :"name" #和上面的功能是一樣的,也能夠達(dá)到給@name賦值的效果
def to_s
"Test: #{@name}"
end
end
#attr_accessor其實(shí)是設(shè)置了兩個(gè)實(shí)例方法,分別是“name=”和“name”方法,可以從如下的代碼中獲知:
Test.new.instance_methods.grep(/name/) #=>:name, :name=
#如果沒(méi)有執(zhí)行"name="方法,則下面的Test類對(duì)象的屬性值為nil
Test.new.instance_variables #=>[]
#如果執(zhí)行了“name=”方法,則相當(dāng)于賦值給了屬性@name
obj = Test.new
obj.name = "demo"
puts obj #=>Test:demo
obj.instance_variables #=>@name
6.限制方法
1.public:使用實(shí)例方法的形式進(jìn)行調(diào)用
2.private:不能顯式調(diào)用
3.protected:在同一個(gè)類中可以作為實(shí)例方法使用,但是其他地方無(wú)法使用
#public方法
默認(rèn)情況下public方法,除了initialize,它是一個(gè)private方法
#private方法
不能被顯式調(diào)用,可以其類或者子類中被隱式調(diào)用
class Demo
def test
private_test
end
private
private_test
puts "this is the private test"
end
end
obj = Demo.new
obj.test #=>this is the private test
class Child<Demo
def child_test
private_test
end
end
obj = Child.new
obj.child_test #=>this is the private test
#protected:在同一個(gè)類中(及其子類)可以作為實(shí)例方法使用,但是其他地方無(wú)法使用
class Point
attr_accessor :x, :y
protected :x=, :y=
def initialize(x, y)
@x, @y = x, y
end
def swap(obj)
tempx, tempy = @x, @y
@x, @y = obj.x, obj.y
obj.x, obj.y = tempx,tempy #在同一個(gè)類中protected方法可以被調(diào)用
end
end
p1 = Point.new(1,1)
p2 = Point.new(2,2)
p1.swap(p2)
puts p1.x #返回2
p1.x = 10 #NoMethodError方法 #在類之外不能被調(diào)用
7.改變淘寶源
#查看淘寶源
gem sources -l
#移除https://rubygems.org源
gem sources -remove https://rubygems.org/
#增加http://ruby.taobao.org/源
gem sources -a https://gems.ruby-china.org
8.send email
#與controller的使用規(guī)則類似,在終端運(yùn)行下面的代碼
rails g mailer UserMailer
#在user_mailer.rb文件中建立如下的代碼:
class UserMailer < ApplicationMailer
default from: "zhengjiajun121@gmail.com"
def welcome_email
mail(to: "zheng_jiajun@foxmail.com", subject: "Welcome to My Awesome Site")
end
end
#建立兩個(gè)視圖文件,分別是welcome_email.html.erb文件和welcome_email.text.erb文件:
#進(jìn)行文件配置,在config/environments/developments.rb中添加如下代碼:
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: "smtp.gmail.com",
port: 587,
user_name: "zhengjiajun121",
password: "xxx",
authentication: "plain",
enable_starttls_auto: true }
#在終端執(zhí)行下面的文件,郵件可以從gmail郵箱發(fā)送至foxmail郵箱中:
UserMailer.welcome_email.deliver_now
9.if語(yǔ)句使用賦值語(yǔ)句
#if語(yǔ)句的通常表示形式是如下:
if condition then
expressions
end
#在此基礎(chǔ)上可以添加elsif、else:
if condition then
expressions
elsif condition then
expressions
else
expressions
end
#下面介紹另外一種形式的if表達(dá)式:
def current_user
if(user = nil)
"the user is nil"
elsie(user = nil)
"the other situation"
end
end
puts current_user.nil? #true
上面的代碼說(shuō)明,兩個(gè)條件表達(dá)式都不滿足,因此current_user方法的返回值是nil.
#上面代碼的變形如下:
def current_user
if(user = "cc")
"the user is nil"
elsie(user = nil)
"the other situation"
end
end
puts current_user.nil? #false
總結(jié):該篇文章只是說(shuō)明賦值語(yǔ)句也可以被作為條件表達(dá)式的邏輯判斷,其中邏輯判斷的值為賦值語(yǔ)句中被賦值的變量,如果該變量的值為nil或者false,則該邏輯判斷的值為false.
如果該變量的值為除了nil或者false之外的其他值,則該邏輯判斷的值為true.
#tutorial教程中代碼
def current_user
if (user_id = session[:user_id])
@current_user ||= User.find_by(id: user_id)
elsif (user_id = cookies.signed[:user_id])
user = User.find_by(id: user_id)
if user && user.authenticated?(cookies[:remember_token])
log_in user
@current_user = user
end
end
end
10.使用tag
介紹has_and_belongs_to_many和has_many
1.使用has_and_belongs_to
#新建一個(gè)model
rails g model Tag name:string
#如果使用has_and_belongs_to_many方法,需要使用使用關(guān)聯(lián)表,因此migrate表中使用如下代碼:
class CreateTags < ActiveRecord::Migration
def change
create_table :tags do |t|
t.string :name
t.timestamps
end
#設(shè)置的表格是字母表靠前的排前面,比如post比tag靠前,同時(shí)不需要該表的id值,因此將id值設(shè)置為false.
create_table :posts_tags, :id => false do |t|
t.integer :post_id
t.integer :tag_id
end
end
end
#建立和取消數(shù)據(jù)庫(kù)表
rake db:migrate
rake db:rollback VERSION=id值
#在兩個(gè)model中做相應(yīng)的聲明
class Post < ActiveRecord::Base
has_and_belongs_to_many :tags
end
class Tag < ActiveRecord::Base
has_and_belongs_to_many :posts
end
#在rails console中對(duì)文章進(jìn)行tag
rails console
#創(chuàng)建兩個(gè)tag
Tag.create(name: "beautiful")
Tag.create(name: "ugly")
#給首篇文章添加兩個(gè)tag
Post.first.tags << Tag.first
Post.first.tags << Tag.second
#使用has_and_belongs_to_many的特點(diǎn)是,建立了posts_tags表,但是沒(méi)有在建立相應(yīng)的model.
2.使用has_many through
class CreateTags < ActiveRecord::Migration
def change
create_table :tags do |t|
t.string :name
t.timestamps
end
end
#同時(shí)建立tagging 這個(gè)model
rails g model Tagging post_id:integer tag_id:integer
#同時(shí)修改兩個(gè)model:
class Post < ActiveRecord::Base
has_many :taggings
has_many :tags, :through => :taggings
end
class Tag < ActiveRecord::Base
has_many :taggings
has_many: posts, :through => :taggings
end
class Tagging < ActiveRecord::Base
belongs_to :posts
belongs_to :tags
end
rails console
#創(chuàng)建兩個(gè)tag
Tag.create(name: "beautiful")
Tag.create(name: "ugly")
#給首篇文章添加兩個(gè)tag
Post.first.tags << Tag.first
Post.first.tags << Tag.second
Tagging.all #顯示有結(jié)果,能看到tag和post的關(guān)聯(lián)
#在Post這個(gè)model中建立查詢方法,查詢存在某個(gè)特定tag的post
def self.post(tag_name)
#這個(gè)try方法是在tag對(duì)象上調(diào)用posts方法
Tag.find_by(name: tag_name).try(:posts)
end
#然后在終端查詢存在某個(gè)tag的文章的時(shí)候,代碼如下所示:
rails console
Article.tag_with("ugly")
#使用另外的scope方法也可以實(shí)現(xiàn)如上的效果,使用scope的好處是該方法可以實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用:
scope :tag_with, lambda{ |tag_name| joins(:tags).where(" tags.name = ?", tag_name)}
scope :latter_with, lambda{ |time| joins(:taggings).where("taggings.created_at > ?", time)}
#在rails console中可以實(shí)現(xiàn)單獨(dú)調(diào)用,也可以實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用,見(jiàn)下面所示:
rails console
Post.tag_with("ugly") #scope方法單獨(dú)調(diào)用
Post.tag_with("ugly").latter_than(Time.now) #scope方法實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用
11.Kernel中的module function
#Kernel中方法的解釋
The Kernel instance methods are documented in class Object
while the module methods are documented here.
我對(duì)這句話的理解是Kernel的實(shí)例方法已經(jīng)在Object類中進(jìn)行了說(shuō)明
Kernel文檔中的方法實(shí)現(xiàn)了Module類中的module_function功能。
#module function方法
1.可以直接通過(guò)模塊名直接調(diào)用該方法。
2.該方法將會(huì)作為私有實(shí)例方法被隱式調(diào)用,因?yàn)镵ernel模塊被include到Object類中。
module Mod
def one
"This is one"
end
module_function :one
end
class Cls
include Mod
def call_one
one
end
end
Mod.one #=> "This is one"
c = Cls.new
c.call_one #=> "This is one"
#返回Kernel中私有實(shí)例變量的個(gè)數(shù),剛好是文檔中所示個(gè)數(shù):
Kernel.private_instance_method.size #67
puts "this is private instance method" #被main對(duì)象進(jìn)行隱式調(diào)用
Kernel.puts " the method can be called with the module as a receiver"
#其實(shí)send是Kernel的公開(kāi)實(shí)例方法
Kernel.public_instance_methods.grep(/send/) # [:public_send, :send]
12.render partial
將articles的提取出來(lái)/article/_article.html.erb,同時(shí)在/article/index.html.erb顯示如下代碼:
<%= render @articles%>