1.rails中使用bootstrap
2.局部变量和块
3.flash用法
4.email.downcase
5.对象属性
6.限制方法
7.改变淘宝源
8.send email
9.if语句使用赋值语句
10.使用tag
11.Kernel中的module function
12.render partial
1.rails中使用bootstrap
#gemfile中添加gem
gem 'bootstrap-sass'
#定义自定义的custom.css.scss
#如上文件中,添加如下代码,这两行代码会引入bootstrap框架
@import "bootstrap-sprockets";
@import "bootstrap";
#下拉框生效
#application.js中引入bootstrap的javascript库
//= require bootstrap
2.局部变量和块
局部变量可以被代入块中,但是块中的局部变量不能被带出块的作用范围内,其实这是闭包的知识
class Demo
number = 2
define_method :my_method do
puts number
person = "this is the demo"
end
Demo.new.my_method
puts person
end
#上面的代码执行结果如下:
#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
疑惑:是第二个email是何种表示形式,是一个局部变量,还是一个方法
before_save{self.email = email.downcase}
追根溯源,在这本书的第四个章节,找到这段代码的最初解释:
class Word < String
# 如果字符串和反转后相等就返回 true
def palindrome?
self == self.reverse # self 代表这个字符串本身
end
end
s = Word.new("level") # 创建一个 Word 实例,初始值为 "level"
s.palindrome? # => true
根据第四章的解释,self代表的就是对象本身,在类中调用方法或访问属性时可以不用 self(赋值时不行)。
下面的语句是等价的:
self == self.reverse
self == reverse
下面的两条语句也是等价的:
#左侧的self是必须,右侧的self是可选的
self.email = email.downcase
self.email = self.email.downcase
为什么左边的self是必须的,如果没有 self,创建的是一个局部变量。
使用 self 的目的是确保把值赋给用对象属性。
在元编程的书(中文第二版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
其中这条语句:
my_attribute = n
不确定是想给局部变量赋值,还是调用名为my_attribute=的拟态方法
在没有确定答案的情况下,Ruby默认选择第一种方法,它定义了一个名为my_attribute的局部变量。
为了避免这个问题,给当前对象的属性赋值时,应该显性地使用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
这也是为什么在上面的代码中,左侧的self不能省略的原因。
5.对象属性
对象的属性:一个对象的外部可见部分被称其为属性。ruby通过对象的实例变量来表示对象的内部状态,即,属性。
既然是对外部可见的。Ruby中,实例变量无法直接为对象外使用,只能通过对象定义的操作方法访问。
同理,实例变量也不能变成public变量,同样是通过方法访问,那就是可以通过某种方式读取和修改的。
Ruby中是通过定义方法来访问属性。有两种方法方式
1.直接定义类属性的方法
2.通过Module的方法定义
1.直接定义类属性的方法:
#这个就是定义一个对象的实例变量name,作为Test的属性
class Test
def initialize(name)
@name=name
end
def name
@name
end
def name=(att)
@name=att
end
end
2.通过Module的方法定义
class Test
attr_accessor :name
#attr_accessor :"name" #和上面的功能是一样的,也能够达到给@name赋值的效果
def to_s
"Test: #{@name}"
end
end
#attr_accessor其实是设置了两个实例方法,分别是“name=”和“name”方法,可以从如下的代码中获知:
Test.new.instance_methods.grep(/name/) #=>:name, :name=
#如果没有执行"name="方法,则下面的Test类对象的属性值为nil
Test.new.instance_variables #=>[]
#如果执行了“name=”方法,则相当于赋值给了属性@name
obj = Test.new
obj.name = "demo"
puts obj #=>Test:demo
obj.instance_variables #=>@name
6.限制方法
1.public:使用实例方法的形式进行调用
2.private:不能显式调用
3.protected:在同一个类中可以作为实例方法使用,但是其他地方无法使用
#public方法
默认情况下public方法,除了initialize,它是一个private方法
#private方法
不能被显式调用,可以其类或者子类中被隐式调用
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:在同一个类中(及其子类)可以作为实例方法使用,但是其他地方无法使用
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 #在同一个类中protected方法可以被调用
end
end
p1 = Point.new(1,1)
p2 = Point.new(2,2)
p1.swap(p2)
puts p1.x #返回2
p1.x = 10 #NoMethodError方法 #在类之外不能被调用
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的使用规则类似,在终端运行下面的代码
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
#建立两个视图文件,分别是welcome_email.html.erb文件和welcome_email.text.erb文件:
#进行文件配置,在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 }
#在终端执行下面的文件,邮件可以从gmail邮箱发送至foxmail邮箱中:
UserMailer.welcome_email.deliver_now
9.if语句使用赋值语句
#if语句的通常表示形式是如下:
if condition then
expressions
end
#在此基础上可以添加elsif、else:
if condition then
expressions
elsif condition then
expressions
else
expressions
end
#下面介绍另外一种形式的if表达式:
def current_user
if(user = nil)
"the user is nil"
elsie(user = nil)
"the other situation"
end
end
puts current_user.nil? #true
上面的代码说明,两个条件表达式都不满足,因此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
总结:该篇文章只是说明赋值语句也可以被作为条件表达式的逻辑判断,其中逻辑判断的值为赋值语句中被赋值的变量,如果该变量的值为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
#新建一个model
rails g model Tag name:string
#如果使用has_and_belongs_to_many方法,需要使用使用关联表,因此migrate表中使用如下代码:
class CreateTags < ActiveRecord::Migration
def change
create_table :tags do |t|
t.string :name
t.timestamps
end
#设置的表格是字母表靠前的排前面,比如post比tag靠前,同时不需要该表的id值,因此将id值设置为false.
create_table :posts_tags, :id => false do |t|
t.integer :post_id
t.integer :tag_id
end
end
end
#建立和取消数据库表
rake db:migrate
rake db:rollback VERSION=id值
#在两个model中做相应的声明
class Post < ActiveRecord::Base
has_and_belongs_to_many :tags
end
class Tag < ActiveRecord::Base
has_and_belongs_to_many :posts
end
#在rails console中对文章进行tag
rails console
#创建两个tag
Tag.create(name: "beautiful")
Tag.create(name: "ugly")
#给首篇文章添加两个tag
Post.first.tags << Tag.first
Post.first.tags << Tag.second
#使用has_and_belongs_to_many的特点是,建立了posts_tags表,但是没有在建立相应的model.
2.使用has_many through
class CreateTags < ActiveRecord::Migration
def change
create_table :tags do |t|
t.string :name
t.timestamps
end
end
#同时建立tagging 这个model
rails g model Tagging post_id:integer tag_id:integer
#同时修改两个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
#创建两个tag
Tag.create(name: "beautiful")
Tag.create(name: "ugly")
#给首篇文章添加两个tag
Post.first.tags << Tag.first
Post.first.tags << Tag.second
Tagging.all #显示有结果,能看到tag和post的关联
#在Post这个model中建立查询方法,查询存在某个特定tag的post
def self.post(tag_name)
#这个try方法是在tag对象上调用posts方法
Tag.find_by(name: tag_name).try(:posts)
end
#然后在终端查询存在某个tag的文章的时候,代码如下所示:
rails console
Article.tag_with("ugly")
#使用另外的scope方法也可以实现如上的效果,使用scope的好处是该方法可以实现链式调用:
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中可以实现单独调用,也可以实现链式调用,见下面所示:
rails console
Post.tag_with("ugly") #scope方法单独调用
Post.tag_with("ugly").latter_than(Time.now) #scope方法实现链式调用
11.Kernel中的module function
#Kernel中方法的解释
The Kernel instance methods are documented in class Object
while the module methods are documented here.
我对这句话的理解是Kernel的实例方法已经在Object类中进行了说明
Kernel文档中的方法实现了Module类中的module_function功能。
#module function方法
1.可以直接通过模块名直接调用该方法。
2.该方法将会作为私有实例方法被隐式调用,因为Kernel模块被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中私有实例变量的个数,刚好是文档中所示个数:
Kernel.private_instance_method.size #67
puts "this is private instance method" #被main对象进行隐式调用
Kernel.puts " the method can be called with the module as a receiver"
#其实send是Kernel的公开实例方法
Kernel.public_instance_methods.grep(/send/) # [:public_send, :send]
12.render partial
将articles的提取出来/article/_article.html.erb,同时在/article/index.html.erb显示如下代码:
<%= render @articles%>