教程积累

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

推荐阅读更多精彩内容