1.caching with instance variables
2.dynamic find_by methods
3.find through association
4.move find into mode
5.using with_scope
6.Shortcut Blocks with Symbol to_proc
7.All About Layouts
8.Layouts and content_for
9.Filtering Sensitive Logs
10.Refactoring User Name Part 1
11.Refactoring User Name Part 2
12.Refactoring User Name Part 3
13.Dangers of Model in Session
14.Performing Calculations on Models
15.Fun with Find Conditions
16.Virtual Attributes
17.HABTM Checkboxes
18.Looping Through Flash
19.Where Administration Goes
20.Restricting Access
21.Super Simple Authentication
22.Eager Loading
23.Counter Cache Column
24.The Stack Trace
25.SQL Injection
26.Hackers Love Mass Assignment
27.Cross Site Scripting
28.in_groups_of
29.group_by Month
30.Pretty Page Title
31.Formatting Time
32.Time in Text Field[未實現(xiàn)]
33.Making a Plugin
34.Named Routes
35.Custom REST Actions
36.Subversion on Rails
37.Simple Search Form
38.Multibutton Form
39.Customize Field Error
40.Blocks in View
41.Conditional Validations
42.with_options
46.Catch-all Route
47.Two Many-to-Many
48.Console Tricks【有更新】
49.Reading the API
50.Contributing to Rails
51.will_paginate
52.Update through Checkboxes
53.Handling Exceptions(未實現(xiàn))
54.Debugging Ruby
55.Cleaning Up the View
56.The Logger
57.Create Model Through Text Field
58.How to Make a Generator(未實現(xiàn))
59.Optimistic Locking
60.Testing without Fixtures
61.Sending Email
64.Custom Helper Modules
67.restful_authentication
70.Custom Routes
72.Adding an Environment
78.Generating PDF Documents
80.Simplify Views with Rails 2.0
81.Fixtures in Rails 2.0
82.HTTP Basic Authentication
83.Migrations in Rails 2.0
85.YAML Configuration
89.Page Caching
90.Fragment Caching
96.Git on Rails
97.Analyzing the Production Log
109.Tracking Attribute Changes
111.Advanced Search Form
113.Contributing to Rails with Git
116.Selenium
120.Thinking Sphinx
126.Populating a Database
134.Paperclip
139.Nested Resources
155.Beginning with Cucumber
156.Webrat
158.Factories not Fixtures
159.More on Cucumber
160.Authlogic
169.Dynamic Page Caching
179.Seed Data
180.Finding Unused CSS
182.Cropping Images
187.Testing Exceptions
188.Declarative Authorization
189.Embedded Association
190.Screen Scraping with Nokogiri
191.Mechanize
200.Rails 3 Beta and RVM
201.Bundler
202.Active Record Queries in Rails 3
203.Routing in Rails 3
204.XSS Protection in Rails 3
206.Action Mailer in Rails 3
207.Syntax Highlighting
209.Devise
210.Customizing Devise
225.Upgrading to Rails 3 Part 1
226.Upgrading to Rails 3 Part 2
227.Upgrading to Rails 3 Part 3
231.Routing Walkthrough Part 1
232.Routing Walkthrough Part 2
234.SimpleForm
239.ActiveRecord::Relation Walkthrough
244.Gravatar
250.Authentication from Scratch
253.CarrierWave File Uploads
254.Pagination with Kaminari
257.Request Specs and Capybara
264.Guard
270.Authentication in Rails 3.1
272.Markdown with Redcarpet
274.Remember Me & Reset Password
275.How I Test
278.Search with Sunspot
282.Upgrading to Rails 3.1
283.Authentication with Sorcery
285.Spork
299.Rails Initialization Walkthrough
305.Authentication with Warden
308.Oh My ZSH
314.Pretty URLs with FriendlyId
318.Upgrading to Rails 3.2
319.Rails Middleware Walkthrough
328.Twitter Bootstrap Basics
368.MiniProfiler
372.Bullet
374.Image Manipulation
382.Tagging
385.Authorization from Scratch Part 1
386.Authorization from Scratch Part 2
395.Action Controller Walkthrough
397.Action View Walkthrough
411.Performance Testing
412.Fast Rails Commands
413.Fast Tests
415.Upgrading to Rails 4
417.Foundation
1. caching with instance variables
實現(xiàn)的代碼如下所示:
class ApplicationController < ActionController::Base
def current_user
@current_user ||= User.find(session[:user_id])
end
end
如果按照如下的代碼:
class ApplicationController < ActionController::Base
def current_user
User.find(session[:user_id])
end
end
每次查詢用戶的時候都需要調(diào)用數(shù)據(jù)庫,為了避免每次都調(diào)用數(shù)據(jù)庫的行為,進行如下的優(yōu)化:
@current_user ||= User.find(session[:user_id])
上面的代碼等于于
@current_user = @current_user || User.find(session[:user_id])
當(dāng)首次使用current_user方法的時候,@current_user的值為nil,則進行數(shù)據(jù)庫調(diào)用,User.find(session[:user_id])會賦值給@current_user,當(dāng)?shù)诙握{(diào)用current_user方法的時候,不會使用User.find(session[:user_id])方法,即不會調(diào)用數(shù)據(jù)庫,直接使用被賦值后的@current_user。
注意:用戶退出的時候設(shè)置@current_user=nil
2. dynamic find_by methods
這里的find_by無效,如果要獲得數(shù)組數(shù)據(jù),需要使用where方法
#建立模型
rails g model Task complete:string uncomplete:string
rails destroy model Task #取消建模
Task.find(complete: "false") #該方法會報錯,因為find方法里面只能出現(xiàn)id的值
Task.find_by(complete: "false")#該方法只有一個返回值,見api所示,因此在這個結(jié)果調(diào)用each方法則會報錯,因為該對象沒有each方法
Task.where("complete = ?", "false"),該方法返回全部為false值的數(shù)組對象,因此該結(jié)果可以調(diào)用each方法,而上面Taks.find_by方法只返回滿足條件的第一個值。
3. find through association
在project中有很多的tasks,進行關(guān)聯(lián)查詢:
class Project < ActiveRecord::Base
has_many :tasks
end
class Task < ActiveRecord::Base
belongs_to :project
end
對于存在association的model中,如果查詢某個project中的task,使用下面的語句和代碼:
class ProjectsController < ApplicationController
def show
@project = Project.find(params[:id])
@tasks = @project.tasks.where("complete = ?", "false")
end
end
4. move find into model
將查詢方法置于model中,在controller中可以被多次調(diào)用,避免代碼重復(fù),代碼如下所示:
class Task < ActiveRecord::Base
def self.uncomplete
where(complete: "false")
end
end
class TaskController < ApplicationController
def index
@tasks = Task.uncomplete
end
end
5. using with_scope
with_scope方法在最新api文檔里面已經(jīng)找不到了,相同功能的方法叫做scope,詳細的用法在自己的一篇關(guān)于tag的文章中也有闡述,大概的使用功能及代碼可以見下面所示,即是使用scope創(chuàng)建自定義的方法:
rails g scaffold Article name:string content:text
#model/article.rb
class Article < AcriveRecord::Base
scope :test, lambda{|name| where("name = ? ", name)}
end
#rails console
Article.test("demo")
6. Shortcut Blocks with Symbol to_proc
在如下代碼中:
class Project < ActiveRecord::Base
def self.all_names
all.collect(&:name)
end
end
#終端查詢
Project.all_names #返回所有的Project表中的name值
#下面的等價形式是rails對ruby的擴充
all.collect(&:name)
all.collect{|p| p.name} #這是等價代碼,只返回只有name的值
#ruby形式的(&:name)
array.uniq(&:first).sort_by(&:last)
array.uniq{|a|.a.first}.sort_by{|x|x.last}
#就是按照數(shù)據(jù)的第一個元素去重,然后按照數(shù)組的第二個元素排序
#作用:實現(xiàn)鏈式調(diào)用
all.collect(&:name).collect(&:upcase)
#除了collect,也可以應(yīng)用在其他地方
#對每一個值進行遍歷,并對其進行求值valid?,如果其中任何一個返回為true,則整個值返回為true
#valid?是rails方法,通過validate方法則說明有效
projects.all?(&:valid?)
projects.any?(&:valid?)
#同collect,進行遍歷
projects.each(&:save!)
7. All About Layouts
介紹各種布局形式
1.默認布局
默認的布局形式在views/layouts/application.html.erb文件中
2.自定義布局,針對某個資源有效
建立views/layouts/admin.html.erb文件
#articles_controller.rb文件
class ArticlesController < ApplicationController
#使用admin布局
layout "admin"
end
3.自定義布局,針對某個具體的action有效
如果只是針對某個action生效,可以在controller文件中寫入如下的代碼:
render layout: 'admin'
4.消除布局
render layout: false
5.動態(tài)布局
class ProjectsController < ApplicationController
layout :user_layout
def index
@projects = Project.find(:all)
end
protected
def user_layout
if current_user.admin?
"admin"
else
"application"
end
end
end
8. Layouts and content_for
使用content_for方法對單個的頁面進行樣式重置,實用性不太,因為基本的單個頁面的布局已經(jīng)可以通過layouts布局進行實現(xiàn),遇到content_for案例再進行細究。
疑問:下面的案例提供引用兩個css文件沒有必要,因為rails4.2所有的css文件最終都變成一個css文件被導(dǎo)入。
#需要重置樣式的頁面,比如index.html.erb文件中
<% content_for :head do %>
<%= stylesheet_link_tag 'projects' %>
<% end %>
#在application.html.erb文件中寫入如下代碼
<head>
<%= yield :head %>
</head>
<body>
<%= yield %>
</body>
結(jié)合rails的api可以看出content_for方法是將一個block儲存起來,以備未來使用,當(dāng)執(zhí)行到index,html.erb文件中中時,出現(xiàn)如下的代碼呈現(xiàn)形式:
<head>
<%= stylesheet_link_tag 'projects' %>
</head>
9. Filtering Sensitive Logs
按照railscast中的說明,對于敏感字段password而言,應(yīng)該在下面的代碼中進行設(shè)置:
class ApplicationController < ActionController::Base
filter_parameter_logging "password"
end
但是在rails4.2的項目中,filter_parameter_logging方法會報undefined method錯誤,應(yīng)該是rails4.2中,對這個方法進行了舍棄,參考此文,進行如下設(shè)置:
#config/initializers/filter_parameter_logging.rb
Rails.application.config.filter_parameters += [:password] #其實是rails的默認設(shè)置
按照上面的設(shè)置,在log/development.log文件中,password字段顯示的值為[FILTERED]
10. Refactoring User Name Part 1
對前端頁面進行優(yōu)化的方式,是將方法設(shè)置在model中,然后在view層進行調(diào)用,比如在model中建立full_name方法:
#first_name,middle_name,last_name是Uers的三個屬性
class User < ActiveRecord::Base
def full_name
name = first_name + ' '
name += "#{middle_initial}. " unless middle_initial.nil?
name += last_name
name
end
end
11. Refactoring User Name Part 2
對full_name方法還可以進行優(yōu)化,代碼如下所示:
def full_name
[first_name, middle_initial_with_period,last_name].compact.join(' ')
end
def middle_initial_with_period
"#{middle_initial}." unless middle_initial.blank?
end
12. Refactoring User Name Part 3
對測試進行優(yōu)化,代碼如下所示:
require 'test_helper'
class UserTest < ActiveSupport::TestCase
test "full name" do
#其中“nil middle initial”如果出錯會顯示這條語句
assert_equal "John Smith", full_name('John', nil, 'Smith'), 'nil middle initial'
assert_equal 'Paul P. Hughes', full_name('Paul', 'P', 'Hughes'), 'P middle initial'
assert_equal "John Jones", full_name('John', '', 'Jones'), 'blank middle initial'
end
def full_name(first, middle, last)
User.new(:first_name => first, :middle_initial => middle, :last_name => last).full_name
end
end
13. Dangers of Model in Session
這部分知識闡述的是不要將數(shù)據(jù)存儲在session中,容易造成數(shù)據(jù)的不同步現(xiàn)象,合理的方式是講在session中存儲id值,代碼如下所示:
class UserController < ApplicationController
def prepare
session[:user_id] = User.find(:first).id
redirect_to :action => :'show'
end
def show
@user = User.find(session[:user_id])
end
def update
@user = User.find(session[:user_id])
@user.name = 'Foo'
redirect_to :action => 'show'
end
end
14. Performing Calculations on Models
在ActiveRecord中預(yù)制了對數(shù)據(jù)進行統(tǒng)計的方法,如下所示:
rails scaffold Calculation priority:integer
Calculation.first.priority #查第一個數(shù)值
Calculation.sum(:priority) #查平均數(shù)值
Calculation.minimum(:priority) #查最小數(shù)值
Calculation.maximum(:priority) #查最大數(shù)值
Calculation.average(:priority).to_f #查平均數(shù)值
15. Fun with Find Conditions
使用ActiveRecord的條件查詢,代碼如下所示:
User.where(["name = ? and email = ?", "Joe", "joe@example.com"])
User.where(["name = :name and email = :email", { name: "Joe", email: "joe@example.com" }])
16. Virtual Attributes
一般情況下,在rails中,model中的屬性要和數(shù)據(jù)庫中的字段相對應(yīng),如果model中的屬性沒有和數(shù)據(jù)庫的字段相對應(yīng),則這個屬性就被稱為虛擬屬性,通用版本如下:
#字段如下:
create_table "users", :force => true do |t|
t.string "first_name"
t.string "last_name"
t.string "password"
end
#表單如下:
<h1>Register</h1>
<% form_for @user do |form| %>
<ol class="formList">
<li> <%= form.label :full_name, 'Full Name' %> <%= form.text_field :full_name %> </li>
<li> <%= form.label :password, 'Password' %> <%= form.password_field :password %> </li>
</ol>
<% end %>
#model如下:
class User < ActiveRecord::Base
# Getter
def full_name
[first_name, last_name].join(' ')
end
# Setter
def full_name=(name)
split = name.split(' ', 2)
self.first_name = split.first
self.last_name = split.last
end
end
更新后的版本如下:
for example
17. HABTM Checkboxes
場景是為一個model添加多個可選tag
rails g scaffold product name:string content:text
rails g scaffold category name:string
rails g scaffold categorization product_id:integer category_id:integer
#model
class Product < ActiveRecord::Base
has_many :categorizations
has_many :categories, through: :categorizations
end
class Category < ActiveRecord::Base
has_many :categorizations
has_many :products, through: :categorizations
end
class Categorization < ActiveRecord::Base
belongs_to :product
belongs_to :category
end
#controller
def product_params
#需要添加強參{category_ids:[]}
params.require(:product).permit(:name, :content, {category_ids: []})
end
#view
<div class = "field">
#如果不添加hidden_field_tag參數(shù),則勾選已經(jīng)有的tag,則該tag不會刪除
<%= hidden_field_tag "product[category_ids][]", nil %>
<% Category.all.each do |category| %>
#下面product[category_ids][]的依據(jù)可以參考rails guides的內(nèi)容
<%= check_box_tag "product[category_ids][]", category.id, @product.category_ids.include?(category.id) %>
<%= category.name %></br>
<% end %>
</div>
18. Looping Through Flash
一般在使用flash的時候都會迭代顯示里面的信息,自己在實踐的過程中按照如下代碼進行設(shè)置和呈現(xiàn):
#在controller文件中
def create
if @user.save
flash[:success] = "congratulation"
.....
end
end
#在application.html.erb文件中,進行如下的代碼呈現(xiàn)
<% flash.each do |key, value| %>
<%= key %>:<%= value%>
<% end %>
在本文的呈現(xiàn)中,flash在前端頁面的呈現(xiàn)如下所示:
#關(guān)注api中content_tag的使用
<% flash.each do |key,msg| %>
<%= content_tag :p, msg, :id => key %>
<% end %>
**19. Where Administration Goes **
略
20. Restricting Access
略
21. Super Simple Authentication
以上這三個章節(jié)是介紹權(quán)限管理系統(tǒng),我認為里面的提到很多方法和實際的rails4.2版本已經(jīng)過時,但是思想是一致的,建立admin方法,對前端頁面的展示進行過濾和分別呈現(xiàn),現(xiàn)在比較合適的解決方案在ruby on rails tutorial第三版中能找到。
22. Eager Loading
eager loading的意思是貪婪加載,使用的場景出現(xiàn)在“1+N”的情形中,解決的方式是通過joins和includes方法對兩個mode進行關(guān)聯(lián)
joins 在數(shù)據(jù)庫中表示: left outer join
includes 在數(shù)據(jù)庫中表示: innner outer join
代碼參考guides中的代碼:
#從includes中的單復(fù)數(shù)判斷,category has many articles, article has many comments
Article.includes(:category, :comments)
#出現(xiàn)嵌套形式
#category has many articles
#artilce has many comments and tags
#guest has many comments
Category.includes(articles: [{ comments: :guest},:tags])
#關(guān)聯(lián)之后指定條件,下面兩條內(nèi)容一致
#使用hash形式
Article.includes(:comments).where(comments: { visible: true })
#使用string形式必須指定references
Article.includes(:comments).where("comments.visible = true").references(:comments)
#進行排序order
#tag has many articles
Article.joins(:tag).order("articles.name")
Article.joins(:tag).order("tags.name")
23. Counter Cache Column
出現(xiàn)的場景如下所示:
Class Article < ActiveRecord::Base
has_many :comments
end
Class Comment <ActiveRecord::Base
belongs_to :article
end
在一篇文章中,有很多的評論,如果每一篇文章的評論數(shù)量,在執(zhí)行下面的語句的過程中會有進行大量的數(shù)據(jù)庫查詢:
<% @articles.each do |article| %>
<li><%= article.name %> (<%= article.comments.size %)</li>
<% end %>
解決的方式如下所示:
參考此文
#增加
rails g migration add_comments_count_to_article comments_count:integer
#修改表格
class AddCommentsCountToArticle < ActiveRecord::Migration
def change
add_column :articles, :comments_count, :integer, :default => 0
#如果不執(zhí)行下面的語句,則article.comments.size的值都是增加了該字段之后的數(shù)據(jù)
Article.pluck(:id).each do |i|
Article.reset_counters(i, :articles) # 全部重算一次
end
end
end
#添加counter_cache=>true值
class Comment < ActiveRecord::Base
belongs_to :article, :counter_cache => true
end
使用@article.comments.size,就會自動變成使用@article.comments_count
log/development.log文件中出現(xiàn)下面語句:
#只調(diào)用了一次數(shù)據(jù)庫而已
Article Load (0.1ms) SELECT "articles".* FROM "articles"
24. The Stack Trace
略
25. SQL Injection
參考
經(jīng)過實踐下面的代碼:
@articles = Article.where("name like '#{params[:search]}%'")
如果在輸入框中輸入
';drop table demo;
這樣子會報錯誤,但是其實drop table demo的語句是不會執(zhí)行的,這樣子的錯誤也就是SQL注入錯誤。解決的方式是通過Array或者Hash的形式:
Article.where( { :name => params[:search] } )
# or
Article.where( ["name = ?", params[:search] ] )
在執(zhí)行下面的查詢方法的過程中,都需要使用上面的形式來規(guī)避SQL注入問題:
find_by_sql
execute
where 用字串參數(shù)
group
order
26. Hackers Love Mass Assignment
在之前版本的rails系統(tǒng)中其實有mass assignment,這個功能很方便,但是用戶可以從url中操作而惡意改變數(shù)據(jù)庫中的數(shù)據(jù),因此為了繼續(xù)使用mass assignment同時規(guī)避惡意竄改數(shù)據(jù),而使用strong paramete方式,比如User這個model中有三個字段,包括name,age,admin,其中admin是敏感字段,因此將name,age兩個字段放入mass assignment中,具體代碼實現(xiàn)如下,admin字段通過其他方式實現(xiàn)數(shù)據(jù)輸入。
def user_params
params.require(:user).permit(:name,:age)
end
27. Cross Site Scripting
這個問題主要是用戶在提交內(nèi)容的時候提交了可以運行的腳本文件,在rails3之后對這寫腳本文件進行了禁止,因為在最新的rails項目上其實這個問題已經(jīng)不存在了,因為默認對XSS(腳本跨站攻擊),如果顯示用戶提交的腳本內(nèi)容并且進行呈現(xiàn),有下面的幾種方式:
#第一種:使用raw
raw("<p>safe</p>")
#第二種:使用html_safe
"<p>safe</p>".html_safe
#第三種:使用sanitize,一般情況下顯示腳本使用這個方法
這個方法是應(yīng)用白名單(認為有些參數(shù)是安全的,有限進行應(yīng)用)的功能
28. in_groups_of
這個場景主要應(yīng)用在數(shù)據(jù)多列展示,在傳統(tǒng)的數(shù)據(jù)展示中,是按照單列進行數(shù)據(jù)展示,但是應(yīng)用了這個方法可以對數(shù)據(jù)進行多列展示,如下代碼:
<% @articles.in_groups_of(3) do |articles|%>
<tr>
<% articles.each do |article| %>
<td><%= article.name %></td>
<% end %>
</tr>
<% end %>
#上面的代碼顯示的是按照3列進行數(shù)據(jù)排列,但是如果如果出現(xiàn)空缺的話,會出現(xiàn)undefined method for NilClass錯誤,避免這個錯誤,可以添加可選參數(shù)
#當(dāng)選擇false作為可選參數(shù)時,則空項為空顯示
<% @articles.in_groups_of(3, false) do |articles| %>
#也可以選擇其他參數(shù),其他參數(shù)作為填充使用,出現(xiàn)空項,則填充該數(shù)據(jù)
<% @articles.in_groups_of(3, "demo") do |article|%>
rails console
(1..10).to_a.in_groups_of(3, "demo") #顯示列如下:
[1,2,3]
[4,5,6]
[7,demo, demo]
#注意,經(jīng)過實際演示,結(jié)果與api中演示不一致,說明api中數(shù)據(jù)陳列方式有誤
29. group_by Month
railscast中的這篇東西比較煩,原理和例子可以參考這篇:
>> a=(1..20).to_a=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
>> a.group_by{|num| num/5}=> {0=>[1, 2, 3, 4], 1=>[5, 6, 7, 8, 9], 2=>[10, 11, 12, 13, 14], 3=>[15, 16, 17, 18, 19], 4=>[20]}>>
從上面的代碼可以得知,通過一個block提出的條件將一個數(shù)組轉(zhuǎn)化為一個hash。hash的key是數(shù)組元素執(zhí)行block之后得到的結(jié)果,value是原數(shù)組中執(zhí)行block得到key的元素組成的數(shù)組。
應(yīng)用代碼如下所示:
#controller文件中
@students=Student.find(:all)
@student_groups=@students.group_by{|s| s.gender}
#view文件中
<% @student_groups.each do |gender,students| %>
<%= gender %>
<ul>
<% students.each do |student| %>
<li>
<%= student.name%>
</li>
<% end %>
</ul>
<% end %>
#執(zhí)行結(jié)果如下所示:
female
.lucy
.jessi
malejack
.jim
.mike
30. Pretty Page Title
應(yīng)用場景:對顯示的每一篇文章,瀏覽器的顯示標(biāo)題欄應(yīng)該是文章的題目,具體的代碼演示如下:
rails g scaffold Article name:string content:text
#使用episode8中使用的content_for方法,保存塊以備后用
module ApplicationHelper
def title_name(title_name)
content_for(:title){title_name}
end
end
#在application.html.erb文件中寫入如下代碼
<head>
<title>
<% yield(:title)%>
</title>
</head>
#articles/show.html.erb文件中寫入如下代碼
<% title_name(@article.name)%>
31. Formatting Time
兩種方式來對資源中的時間進行格式化,具體代碼如下:
#第一種:直接在view層寫如下代碼
article.created_at.strftime(“%F %T”)
#第二種:在config/environment.rb文件中添加配置信息
Time::DATE_FORMATS[:time] = "%F %T"
view中調(diào)用該方法
article.created_at.to_s(:time)
32. Time in Text Field
這個片段的是出現(xiàn)在編輯時間字段的時候,將時間字段集中在一個字符框中進行,而不是在多個選框中進行。
出現(xiàn)時間選框的代碼如下:
rails g scaffold Article name:string time:datetime
33. Making a Plugin
使用最新的文檔進行plugin的代碼演示,然后回過頭來看這邊的代碼,關(guān)于plugin制作的格式可以參考最新的,但是這個片段中的代碼的一些方法可以參考如何使用。
34. Named Routes
視頻中信息陳舊,可以參考rails guides中的內(nèi)容,具體代碼如下所示:
#url打開/test,獲得welcome#index的值
get 'test', to: 'welcome#index', as: :demo
#url代開 welcome/index,也會返回welcome#index的值
get 'welcome/index', as: :demo
上述的兩個route的值,可以生成兩個命名路由,分別是demo_path,和demo_url,前者可以生成當(dāng)前路徑,后者會生成全路徑。
35. Custom REST Actions
視頻信息陳舊,主要講的是通過一般情況下如下的代碼其實可以實現(xiàn)一般的路由設(shè)置,代碼如下所示:
resources :articles
但是這個資源只能實現(xiàn)index,show,edit,new,update,destroy,create這七個action,對于如果要在資源中設(shè)置其他的action需要自己設(shè)定,代碼如下:
#在controller中進行設(shè)置
class ArticlesController < ApplicationController
def search
end
end
#在route.rb中進行設(shè)置
resources :photos do
collection do
get 'search'
end
end
#或者如下形式:
resources :photos do
get 'search', on: :collection
end
#上面的代碼會形成如下的語句:
/photos/search
search_photos_url
#在views中建立test.html.erb文件
36. Subversion on Rails
略
37. Simple Search Form
這個章節(jié)的內(nèi)容主要做一個簡單的全文檢索,然后我自己在此基礎(chǔ)上擴展功能,從單字段的檢索發(fā)展到多字段的檢索。
簡單的全文檢索代碼如下所示:
#projects/index.html.erb
#和form_for不同,form_for需要model,而form_tag不需要#model,因此對于需要
#model的form_for,若或許參數(shù)是通過params[:session][:email],
#而對于不需要model的form_tag,獲取參數(shù)只需要params[:search]
<%= form_tag projects_path, :method => 'get' do %>
<p>
<%= text_field_tag :search%>
<%= submit_tag "Search" %>
</p>
<% end %>
#projects_controller.rb
def index
@projects = Project.search(params[:search])
end
#models/project.rb
def self.search(search)
#這是針對name這個單字段的檢索
where (["name LIKE ?", "#{search}%"])
#下面是針對name和content兩個字段的檢索
where(["name like ? or content like ?", "#{search}%", "#{search}%"])
end
38. Multibutton Form
這個場景主要出現(xiàn)在對文章進行預(yù)覽,代碼如下所示:
#終端執(zhí)行下面的代碼
rails g scaffold Article name:string content:text
#在controller中改寫如下代碼
def create
@article = Article.new(article_params)
#如果params[:preview_button]存在,則后面的!@article.save不執(zhí)行,如果params[:preview_button]不存在,則執(zhí)行后面的語句
if params[:preview_button] || !@article.save
render 'new'
else
flash[:notice] = "successfully created project"
redirect_to @article
end
end
#在new.html.erb中改寫如下代碼:
<% if params[:preview_button]%>
<%= @article.content%>
<% end %>
#在form表單中添加預(yù)覽表單
<%= submit_tag "Preview", name: "preview_button" %>
39. Customize Field Error
這個章節(jié)的內(nèi)容應(yīng)用場景是當(dāng)對某個字段進行validates的時候,這個字段在內(nèi)容顯示的時候自動被下面的樣式所包圍:
<div class="field_with_errors">
<label for="article_name">
Name
</label>
</div>
為了改變這個scaffold自動生成的樣式,可以進行如下的調(diào)整:
兩篇參考分別是參考一和參考二
#config/environment.rb添加如下代碼:
#下面的代碼會將class= "field_with_errors"這個class進行去除
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
"#{html_tag}".html_safe
end
#如果要編程其他樣式的話,比如將class設(shè)置為field_error,見如下代碼:
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
"<span class='field_error'>#{html_tag}</span>".html_safe
end
按照參考一內(nèi)容,也可以通過下面的形式設(shè)置:
.field_with_errors {display: inline;}
40. Blocks in View
41. Conditional Validations
這個場景出現(xiàn)選擇某個情景進行驗證的情況下,具體代碼呈現(xiàn)如下:
rails g scaffold Article name:string content:text
#article.rb文件中
class Article < ActiveRecord::Base
#下面這條語句在進行@article.save的過程中就會執(zhí)行
validates :name, presence:true
#下面這條語句只有在方法is_test?為真的情況下才會執(zhí)行
validates :content, presence:true, if: :is_test?
def is_test?
false
end
end
42. with_options
這個功能主要是為了避免代碼重復(fù),演示代碼如下所示:
#article.rb文件中
class Article < ActiveRecord::Base
validates :name, presence:true, if: :is_test?
validates :content, presence:true, if: :is_test?
def is_test?
false
end
end
使用with_options減少重復(fù)代碼:
class Article < ActiveRecord::Base
with_options if: :is_test? do |user|
user.validates :name, presence:true
user.validates :content, presence:true
end
def is_test?
false
end
end
46. Catch-all Route
這個應(yīng)用場景是使用類似正則表達式的方式匹配路由,對于任何滿足正則表達式的路由,都匹配該路徑。代碼如下所示:
#route.rb文件中
get "demos/*other", to: "demos#unknow"
#controller文件中
def unknow
end
#建立unknow.html.erb文件
47. Two Many-to-Many
講述兩種方式,在自己的博客tag文中有詳細講述,這里就不展開,核心代碼如下:
has_and_belongs_to_many
belongs_to
has_many through
48. Console Tricks
有更新
49. Reading the API
略
50. Contributing to Rails
視頻不用看,已經(jīng)陳舊。
最新的文檔
51. will_paginate
自己比較喜歡bootstrap這個js框架,所以做開發(fā)的時候一般前端產(chǎn)品都用這個。使用will_paginate這個gem的詳細代碼如下所示:
下面的代碼因為涉及到配置文件,需要重啟才能有效。
#添加gem
gem 'will_paginate-bootstrap'
#controller中添加如下代碼
@blogs = current_user.blogs.paginate(:page => params[:page], :per_page => 5)
#view中進行代碼顯示
<%= will_paginate @blogs %>
#定制
在config/initializers中生成will_paginate.rb文件,寫入下代碼
WillPaginate::ViewHelpers.pagination_options[:previous_label ] = "前一頁"
WillPaginate::ViewHelpers.pagination_options[:next_label ] = "后一頁"
52. Update through Checkboxes
場景:應(yīng)用在批量對屬性進行更新
具體代碼如下:
#終端執(zhí)行
rails g scaffold Task name:string success:boolean
#根據(jù)success的情況將task分為complete和uncomplete
#controller中
@completes = Task.where("success = ?", true)
@uncompletes = Task.where("success= ?" false)
#接下來批量對success為false的task進行更新
#routes.rb文件中
routes :tasks do
patch "complete", on: :collection
end
#在view文件中
<%= form_tag complete_tasks_path, method: :patch do %>
<ul>
<% @uncompletes.each do |uncomplete| %>
<li>
<%= check_box_tag "uncomplete_ids[]", uncomplete.id %>
<%= uncomplete.name %>
</li>
<% end %>
</ul>
<%= submit_tag "mark as complete" %>
#controller文件中
def complete
Task.where(id: params[:uncomplete_ids]).update_all(success: true)
redirect_to tasks_path
end
53. Handling Exceptions
54. Debugging Ruby
這個章節(jié)主要是如何進行調(diào)試,在ruby2.0以前,使用的是debugger這個gem,在ruby2.0以后,使用的是byebug這個gem,該代碼是示例和使用方式如下:
rails g scaffold Task name:string due_at:datetime
#建立controller文件
class TasksController < ApplicationController
def index
debugger
@today_tasks = Task.due_on(Date.today)
@tomorrow_tasks = Task.due_on(Date.tomorrow)
end
end
#建立model文件
class Task < ActiveRecord::Base
def self.due_on(date)
range = date.to_time...(date+1).to_time
where(due_at: range)
end
end
#進行調(diào)試
在想要進行調(diào)試的地方增加下面的語句
debugger
help # 查看哪些方法
next # 執(zhí)行需要調(diào)試的下一條語句
pp @today_tasks #打印這條值
step #進入該方法中的內(nèi)部方法,如果不是自己想要的,可以執(zhí)行next,可以跳到該方法中的另外一個方法
irb #可以在平臺中執(zhí)行該語句puts where(due_at: range).to_sql
byebug的其他用法可以見API
55. Cleaning Up the View
這個章節(jié)的內(nèi)容主要講的是消除前端的臃腫,把邏輯代碼放在controller或者是model中。具體的代碼案例來自于agile development with rails.
56. The Logger
在log文件中查看程序中的執(zhí)行情況,代碼如下:
def index
@articles = Article.all
logger.debug "Articles Count: #{Article.count}"
end
設(shè)置log等級,大于或者等于這個等級的log才能被載入:
#/config/environments/development.rb
config.log_level = :warn
#等級依次為:debug, :info, :warn, :error, :fatal, and :unknown
給log設(shè)置標(biāo)簽
#/config/environments/development.rb
Blog::Application.configure do
config.log_tags = ["Hello World"]
#或者如下
config.log_tags = [:uuid, :remote_ip]
#也可以添加塊
config.log_tags = [:uuid, :remote_ip, lambda { |req| Time.now }]
end
格式化輸入標(biāo)簽內(nèi)容
#/config/initializers/log_formatter.rb
class Logger::SimpleFormatter
def call(severity, time, progname, msg)
"[#{severity}] #{msg}\n"
end
end
不要輸入asset的內(nèi)容
#去除asset pipeline
gem 'quiet_assets', group: :development
#去除warning messages.
gem 'thin', group: :development
#使用thin服務(wù)器開啟web服務(wù)
rails s thin
57. Create Model Through Text Field
這個章節(jié)實現(xiàn)兩個功能,分別是通過選擇框添加tag和通過輸入框添加tag,詳細的代碼演示如下:
#終端執(zhí)行下面代碼
rails g scaffold category name:string
rails g scaffold product name:string content:text category:references
#model中
class Product < ActiveRecord::Base
belongs_to :category
attr_accessor :new_category_name
before_save :create_category_from_name
def create_category_from_name
create_category(name: new_category_name) unless new_category_name.blank?
end
end
#controller中
def create
@product = Product.new(product_params)
if @product.save
redirect_to product_path(@product)
else
render 'new'
end
end
#這段代碼在進行第一次模仿的時候遺漏了,因此new_category_name參數(shù)會被遺漏,不能從view傳遞到model
def product_params
params.require(:product).permit(:name, :content, :category_id, :new_category_name)
end
#view中
<div class="field">
#注意下面選擇框的格式
<%= f.collection_select(:category_id, Category.all, :id, :name, prompt: "請選擇")%>
<%= f.text_field :new_category_name %>
</div>
58. How to Make a Generator
59. Optimistic Locking
應(yīng)用場景,當(dāng)用戶對一個字段進行編輯時,另外一個用戶剛好更新過了這個字段,然后就會報錯,這里介紹兩種解決方式。
第一種,使用樂觀鎖字段lock_version
rails g scaffold product name:string price:float
rails g migration add_lock_version_to_products
#生成下面的形式
class AddLockVersionToProducts < ActiveRecord::Migration
#默認值必須為0
def change add_column :products, :lock_version, :integer, default: 0, null: false
end
end
#/app/views/products/_form.html.erb
<%= f.hidden_field :lock_version %>
#在strong parameter 添加lock_version這個參數(shù)
#product.rb這個model中添加下面的方法
#/app/models/products.rb
def update_with_conflict_validation(*args)
update_attributes(*args)
rescue ActiveRecord::StaleObjectError
#了解樂觀鎖的原理
self.lock_version = lock_version_was
errors.add :base, "This record changed while you were editing it."
changes.except("updated_at").each do |name, values|
errors.add name, "was #{values.first}"
end
false
end
#/app/controllers/products_controller.rb
def update
@product = Product.find(params[:id])
if @product.update_with_conflict_validation(params[:product])
redirect_to @product, notice: "Updated product."
else
render :edit
end
end
第二種方法:不適用鎖機制。上面的這種方法功能已經(jīng)比較完善,第二種方法不理解,下次遇到再說。
**60. Testing without Fixtures **
看不懂,完整懂了測試章節(jié)再看。
61. Sending Email
略
64. Custom Helper Modules
定制一個helper方法,對所有的controller都有用
#在app/helpers中建立如下文件
category_helper.rb
#在controllers/application_controller.rb中寫入如下語句
helper :category #將category_helper.rb中代碼應(yīng)用到所有controller中
helper :all #所有在app/helpers中的文件應(yīng)用到controller中
67. restful_authentication
一種用戶登錄的方案,感覺已經(jīng)過時,替代方案是devise
70.Custom Routes
定制routes,見最新的guides
72. Adding an Environment
rails默認有三個環(huán)境,分別是development,production,test,其實可以自己定制屬于自己的環(huán)境,具體代碼如下:
#建立如下的文件
config/environments/staging.rb
#可以將production.rb文件中的內(nèi)容復(fù)制到該文件中
#開始這個系統(tǒng)的代碼如下:
rails s -e staging
#到這個環(huán)境的console平臺中
rails c staging
RAILS_ENV=staging rails s #和上面的功能類似
#如果設(shè)置默認的環(huán)境為staging,則可以有如下的表示方式
export RAILS_ENV=staging
#可以在gem文件中添加專門給staging的gem
group :staging do
gem 'ruby-prof'
end
#在/config/application.rb文件中設(shè)置專門針對某個group的gem
#下面這段代碼不是很懂,下次遇到問題再說
if defined?(Bundler)
Bundler.require(*Rails.groups(:assets => %w(development test), :profiling => %w[staging development]))
78. Generating PDF Documents
pdf-writer 這個gem已經(jīng)被prawn取代。
80.Simplify Views with Rails 2.0
這個場景就是前端模塊化,默認在使用scaffold的過程中,表格是會被提取出來單獨使用的,比如_form.html.erb,這個章節(jié)將的是講資源的單個內(nèi)容抽取出來,并在show.html.erb和index.html.erb文件中進行使用:
rails g scaffold Article name:string
#views/articles建立article.html.erb
<%= link_to article.name, article%>
#views/articles中修改show.html.erb內(nèi)容
<%= render partial: @article %>
#views/articles中修改index.html.erb內(nèi)容
<%= render partial: @articles%>
81. Fixtures in Rails 2.0
就是進行測試的時候放在test/fixtrues文件夾下面的固件,好處在于不用和ActiveRecord進行交互,但是其實有其他替代方法。視頻內(nèi)容略。
82. HTTP Basic Authentication
場景應(yīng)用在對某個action實現(xiàn)進行過濾,實現(xiàn)的代碼如下:
#controller中
before_filter :authenticate, only: :show
protected
def authenticate
authenticate_or_request_with_http_basic do |username, password| username == "foo" && password == "bar"
end
end
類似的代碼:
http_basic_authenticate_with
83. Migrations in Rails 2.0
這個章節(jié)的內(nèi)容在guides中都都可以找到,主要是講migration的命令以及建立刪除數(shù)據(jù)庫或者字段的語句,容易遺漏的地點,建立的數(shù)據(jù)庫的語句如下:
rake db:create
因為通常情況下默認是sqlite數(shù)據(jù)庫,默認已經(jīng)建立,所以這條語句可以省略,如果換做是其他數(shù)據(jù)庫的話,需要使用這條語句。
85. YAML Configuration
應(yīng)用場景:將一些隱私的信息寫在配置文件里面,不要出現(xiàn)在MVC架構(gòu)中,詳細代碼如下所示:
#controller文件
http_basic_authenticate_with name: ENV["BLOG_USERNAME"], password: ENV["BLOG_PASSWORD"]
#config文件中
#建立application.yml文件,寫入如下內(nèi)容
BLOG_USERNAEM: "jayzen"
BLOG_PASSWORD: "111111"
#在application.rb文件中添加如下內(nèi)容
#每次文件進行加載的時候都會這個application.yml文件進行載入
ENV.update YAML.load(File.read(File.expand_path('../application.yml', __FILE__)))
89.Page Caching
參考guides,page caching已經(jīng)被單獨成為一個gem,但是這個gem不能被rails5使用,以后遇到再說,可能這個gem已經(jīng)被更新。
90.Fragment Caching
參考guides,guides中內(nèi)容不能在log文件中找到對應(yīng)的顯示,log中沒有顯示caching內(nèi)容。
96. Git on Rails
略
109. Tracking Attribute Changes
場景主要應(yīng)用在追蹤最近更新的數(shù)據(jù)變化,代碼顯示操作如下所示:
rails g scaffold Task name:string
#預(yù)存了一段內(nèi)容,其中name為jayzen
rails console
p = Task.first
p.changed? #false
p.changes #{}
p.name = "jay"
p.changed? true
p.changes #{"name"=>["jayzen","jay"]}
111. Advanced Search Form
這個片段體現(xiàn)了下面的幾個場景:1.實現(xiàn)了高級查詢,其實就是多條件查詢 2.對用戶的查詢習(xí)慣進行保存 3.用戶自行建立task任務(wù)
代碼如下所示:
#使用collection_select改寫下面的兩段代碼
rails g scaffold category name:string
rails g scaffold product name:string price:decimal category:references
#建立第三個資源find
rails g scaffold search keywords:string min_price:decimal max_price:decimal category:references
#model
class Search < ActiveRecord::Base
def products
@products ||= find_products
end
private
def find_products
products = Product.where("name like ?", "%#{keywords}%") if keywords.present?
products = products.where(category_id: category_id) if category_id.present?
products = products.where("price >= ?", min_price) if min_price.present?
products = products.where("price <= ?", max_price) if max_price.present?
products
end
end
#controller
class SearchesController < ApplicationController
def new
@search = Search.new
end
def create
@search = Search.create!(params[:search])
redirect_to @search
end
def show
@search = Search.find(params[:id])
end
end
#new.html.erb
<h1>Advanced Search</h1>
<%= form_for @search do |f| %>
<div class="field">
<%= f.label :keywords %><br />
<%= f.text_field :keywords %>
</div>
<div class="field">
<%= f.label :category_id %><br />
<%= f.collection_select :category_id, Category.order(:name), :id, :name, include_blank: true %>
</div>
<div class="field">
<%= f.label :min_price, "Price Range" %><br />
<%= f.text_field :min_price, size: 10 %> - <%= f.text_field :max_price, size: 10 %>
</div>
<div class="actions">
<%= f.submit "Search" %>
</div>
<% end %>
#show.html.erb
<h1>Search Results</h1>
<%= render @search.products %>
#使用task方法對保存的查詢記錄進行刪除
#lib/tasks/searches.rake
desc "Remove searches older than a month"
#如果要與數(shù)據(jù)庫進行交互,必須使用指明:environment
task :remove_old_searches => :environment do
Search.delete_all ["created_at < ?", 1.month.ago]
end
#執(zhí)行上面的代碼rake task names
#rake remove_old_searches
**113.Contributing to Rails with Git **
內(nèi)容略
116.Selenium
內(nèi)容略,講述的是在瀏覽器端對內(nèi)容進行測試。
120. Thinking Sphinx
Sphinx沒有安裝成功
126. Populating a Database
populator沒有支持rails3,更沒有支持rails4,不過可以從這里學(xué)習(xí)到在lib/tasks/文件夾下面,建立task后綴文件,終端執(zhí)行rake db:taskname文件
139.Nested Resources
嵌套路由,見最新的guides
155.Beginning with Cucumber
cucumber是一個測試框架,內(nèi)容略。
156. Webrat
測試框架,內(nèi)容略。
158.Factories not Fixtures
講述測試內(nèi)容fixture,內(nèi)容略。
159.More on Cucumber
內(nèi)容略,講述關(guān)于測試框架cucumber的更多內(nèi)容。
160. Authlogic
一種authentication solution,建議直接使用和熟悉devise
169.Dynamic Page Caching
參考最新的rails guides和episode 89 page caching
179. Seed Data
使用seed方式生成數(shù)據(jù)庫數(shù)據(jù),下面介紹兩種:
#第一種從網(wǎng)絡(luò)上抓取數(shù)據(jù)
rails g model country code:string name:string
require 'open-uri'
open("http://openconcept.ca/sites/openconcept.ca/files/country_code_drupal_0.txt") do |countries|
countries.read.each_line do |country|
code, name = country.chomp.split("|")
Country.create!(:name => name, :code => code)
end
end
#第二種從fixtrue中獲取
rails g model operating name:string
require 'active_record/fixtures'
ActiveRecord::Fixtures.create_fixtures("#{Rails.root}/test/fixtures", "operatings")
180.Finding Unused CSS
在系統(tǒng)中發(fā)現(xiàn)一些未被使用的CSS。
182. Cropping Images
應(yīng)用場景:用戶對上傳的圖片進行個性定制
187.Testing Exceptions
進行測試,內(nèi)容略。
188.Declarative Authorization
內(nèi)容略,用戶的權(quán)限管理機制,推薦簡單的處理方式,比如使用在user中增加admin字段。
189.Embedded Association
內(nèi)容略,權(quán)限管理機制,推薦使用cancancan
190. Screen Scraping with Nokogiri
實現(xiàn)案例:獲取某個網(wǎng)頁下面的某個鏈接內(nèi)容,進入該鏈接,獲取該鏈接下面的內(nèi)容
require "nokogiri"
require "open-uri"
url = "http://www.xixizhan.com/forum-39-2.html"
doc = Nokogiri::HTML(open(url))
doc.css(".xst").each do |item|
doc_one = Nokogiri::HTML(open(item[:href]))
if doc_one.at_css(".t_f span a").nil?
puts "#{item.text}該節(jié)點為空"
else
puts doc_one.at_css(".t_f span a")[:href]
end
end
常用方法
#生成nokogiri對象
doc = Nokogiri::HTML(open(url))
#獲取多個元素
doc.css(".xst")
#獲取單個元素
doc_one.at_css(".t_f span a")
result = @doc.css("name").first
#獲取其中的文本內(nèi)容
doc_one.at_css(".t_f span a").text
#對獲取的文本內(nèi)容記性匹配
doc_one.at_css(".t_f span a").text[/\$[0-9\.]+/]
#獲取其中的鏈接
doc_one.at_css(".t_f span a")[:href]
191. Mechanize
從人人上面獲得用戶的名字
require "mechanize" #引入Mechanize
require "nokogiri"
agent = Mechanize.new #新建一個Mechanize對象
login_page = agent.get "http://www.renren.com/SysHome.do" #獲取登錄頁面
login_form = login_page.forms[0] #獲取該頁面第一個表單
email_field = login_form.field_with(:name => "email") #獲取name為email的輸入框
username_field.value = "email名稱"
password_field = login_form.field_with(:name => "password")
password_field.value = "密碼值"
result_page = agent.submit login_form
puts "loading..."
result = result_page.at_css(".hd-name")
puts result.content #值為鄭佳俊
在rails/lib/tasks建立demo.task,格式如下所示
#內(nèi)容格式
desc "Fetch product prices"
task :fetch_prices => :environment do
#db/seed.rb內(nèi)容一致
end
#執(zhí)行這里面的代碼
rake demo.task
200.Rails 3 Beta and RVM
內(nèi)容都已經(jīng)清楚,略。
201.Bundler
內(nèi)容略,但是在這里發(fā)現(xiàn)了在rake db:migrate的時候經(jīng)常出現(xiàn)的一個問題,出現(xiàn)的問題顯示為gemfile.lock中rake版本太低,而rails項目已經(jīng)出發(fā)了最新的版本,我一般的解決方法是在gemfile.lock中將rake的版本按照提示提高,但是本文的介紹的兩外一種方法:
bundle exec rake db:migrate
這條語句意思是按照gemfile.lock中rake版本執(zhí)行rake,就不會出現(xiàn)上面的錯誤。
202. Active Record Queries in Rails 3
查詢的內(nèi)容查看guides內(nèi)容,下面具體說下使用scope
scope的兩種形式
#使用macro-style形式
class Article < ApplicationRecord
scope :visible, -> { where("hidden=?", true) }
#必須使用塊對象的形式,下面的格式產(chǎn)生同樣作用
scope :view, -> {where("hidden=?", true)}
end
#使用類方法進行定義
class Article < ApplicationRecord
def self.published
where("published=?", true)
end
end
默認scope的形式:
class Article < ApplicationRecord
#default_scope使用塊,而不使用塊對象
default_scope { where("published=?", true) }
end
#也可以參考上面的形式,使用類方法定義,這里省略
scope定義的方法可以使用鏈式調(diào)用
Article.visible.view
203. Routing in Rails 3
內(nèi)容已經(jīng)陳舊,看最新的guides內(nèi)容
204.XSS Protection in Rails 3
參看上面的episode27內(nèi)容,默認情況下rail3以及以后對用戶提交的html進行了轉(zhuǎn)義,防止xss攻擊,如果要顯示html標(biāo)簽內(nèi)容,可以參考episode27中內(nèi)容,一般使用sanitize方法會認為是安全的,另外兩個方法會存在安全漏洞,在并不是很了解的rails安全措施的情況下。
206. Action Mailer in Rails 3
內(nèi)容略,已經(jīng)過時。
207. Syntax Highlighting
場景:實現(xiàn)語法高亮和markdown
使用gem:pygments.rb對整個屬性實現(xiàn)代碼高亮
#添加gem
gem "pygments.rb"
#show.html.erb
<%= raw Pygments.highlight(@article.content) %>
#/app/assets/stylesheets/pygments.css.erb
#在上面這個文件夾中添加pygments.css.erb這個文件,內(nèi)容如下
<%= Pygments.css %>
使用simple_format方法也可以對整條語句顯示格式
<%= simple_format @article.content %>
#如果里面添加諸如<strong></strong>的標(biāo)簽會文字進行屬性miao
使用redcarpet進行markdown,結(jié)合pygment進行highlight
#添加gem
gem 'redcarpet'
#show.html.erb
<%= markdown @article.content %>
#application_helper.rb
def block_code(code, language)
sha = Digest::SHA1.hexdigest(code)
#caching highlighted code
Rails.cache.fetch ["code", language, sha].join('-') do
Pygments.highlight(code, lexer:language)
end
end
def markdown(text)
renderer = HTMLwithPygments.new(hard_wrap: true, filter_html: true)
options = {
autolink: true,
no_intra_emphasis: true,
fenced_code_blocks: true,
lax_html_blocks: true,
strikethrough: true,
superscript: true }
Redcarpet::Markdown.new(renderer, options).render(text).html_safe
end
209. Devise
參考這篇文章
210.Customizing Devise
參考上面的文章,遇到問題再討論。
225.Upgrading to Rails 3 Part 1
略
226.Upgrading to Rails 3 Part 2
略
227.Upgrading to Rails 3 Part 3
略
231.Routing Walkthrough Part 1
研究routing的源碼
232.Routing Walkthrough Part 2
研究routing的源碼
234.SimpleForm
該片段是通過simple_form來簡化rails默認的form_for,下面先通過默認的form_for的形式來書寫一篇代碼,然后給出相應(yīng)的simple_for形式。
下面介紹rails的數(shù)據(jù)類型和sql數(shù)據(jù)類型
:benlean #=>TINYINT(1),1個字節(jié),表示0~255的整數(shù)
:date #=>DATE
:time #=>TIME
:datetime #=>DATETIME
:timestamp #=>DATETIME
:float #=>FLOAT
:decimal #=>DECIMAL,decimal和foat的精度不同
:integer #=>INT
:string #=>VARCHAR
該episode中的數(shù)據(jù)結(jié)構(gòu)如下
#model
product publisher tag
product belongs_to publisher
publisher has_many products
product has_and_belongs_to_many tags
tag has_and_belongs_to_many products
#scaffold
rails g scaffold publisher name
rails g scaffold product name price:decimal release_on:date discontinued:boolean rating:integer publisher:references
rails g scaffold category name
#migration
def change
create_join_table :products, :categories do |f|
f.index : product_id
f.index : category_id
end
end
在form_for表單中的數(shù)據(jù)呈現(xiàn)如下:
#_form.html.erb
<%= form_for(product) do |f| %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :price %>
<%= f.text_field :price %>
</div>
<div class="field">
<%= f.label :release_on %>
<%= f.date_select :release_on %>
</div>
<div class="field">
<%= f.label :discontinued %>
<%= f.check_box :discontinued %>
</div>
<div class="field">
<%= f.label :rating %>
<%= f.radio_button :rating, 1 %> 1
<%= f.radio_button :rating, 2 %> 2
<%= f.radio_button :rating, 3 %> 3
<%= f.radio_button :rating, 4 %> 4
<%= f.radio_button :rating, 5 %> 5
</div>
<div class="field">
<%= f.label :publisher %>
<%= f.collection_select :publisher_id, Publisher.all, :id, :name, prompt: true %>
</div>
<div class="field">
<%= hidden_field_tag "product[category_ids][]", nil %>
<% Category.all.each do |category| %>
<%= check_box_tag "product[category_ids][]", category.id, @product.category_ids.include?(category.id), id: dom_id(category) %>
<%= label_tag dom_id(category), category.name %><br />
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
#show.html.erb
<%= @product.categories.all.map(&:name).join(",") %>
#product_controller.rb
def product_params
params.require(:product).permit(:name, :price, :release_on, :discontinued, :rat ing, :publisher_id, {category_ids: []})
end
239.ActiveRecord::Relation Walkthrough
源碼解析
244.Gravatar
給郵件名稱建立統(tǒng)一標(biāo)識圖像,具體見tutorial。
250. Authentication from Scratch
一個權(quán)限系統(tǒng),詳細見tutorial教程
253. CarrierWave File Uploads
實現(xiàn)場景包括:文件(包括圖片)上傳,文件下載(包括圖片展示)
#添加carrierwave
gem 'carrierwave'
#添加資源
rails g scaffold Resume name:string attachment:string
#建立upload
rails g uploader attachment
#在model中標(biāo)記那個屬性值需要上傳
class Resume < ActiveRecord::Base
mount_uploader :attachment, AttachmentUploader
end
#上傳附件表單new.html.erb,適合多個資源提交
<%= form_for(@resume) do |f|%>
<%= f.label :name%>
<%= f.text_field :name %>
<%= f.label :attachment %>
<%= f.file_field :attachment %> #注意是file_field,而不是text_field
<%= f.submit "save" %>
<% end %>
#適合單個資源提交,場景還未遇到,遇到了再分析
<%= form_tag({action: :upload}, multipart: true) do %>
<%= file_field_tag 'picture' %>
<% end %>
#顯示附件下載和圖片顯示index.html.erb
<% @resumes.each do |resume| %>
<%= resume.name %>
#文件下載
<%= link_to "download", resume.attachment_url %>
#圖片呈現(xiàn)
<%= image_tag resume.attachment_url %>
<% end %>
#編輯上傳文件
class AttachmentUploader < CarrierWave::Uploader::Base
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
#建立白名單,名單之外的不能上傳
def extension_white_list
%w(pdf doc htm html docx)
end
end
#使用鏈接上傳
<%= f.text_field :remote_avatar_url %>
254.Pagination with Kaminari
場景:使用kaminari進行分頁
gem 'kaminari'
#controller
def index
@artilces = Article.page(params[:page]).per(10)
end
#view
<%= paginate @articles %>
257.Request Specs and Capybara
測試,內(nèi)容略。
264.Guard
自動測試時使用,內(nèi)容略
270. Authentication in Rails 3.1
介紹3.1中關(guān)于權(quán)限的三個feature
1.http_basci_authenticate_with
2.has_secure_password/password_digest
3.force_ssl
272 Markdown with Redcarpet
已經(jīng)過時,見207 Syntax Highlighting
274. Remember Me & Reset Password
記住和密碼重置,詳見tutorial代碼
275.How I Test
內(nèi)容略,講述測試內(nèi)容。
278. Search with Sunspot
搜素的解決方案,這里只介紹安裝和一般用法,具體內(nèi)容可以重新看wiki和asciicast,具體代碼參見如下:
#需要安裝Java環(huán)境
#兩個model
rails g scaffold Article name:stirng content:string
rails g scaffold Comment content:string articles:references
#添加兩個gem
gem 'sunspot_rails'
gem 'sunspot_solr'
#model
searchable do
#boost是提高權(quán)重
text :name, :boost => 5
text :content
#關(guān)聯(lián)comment
text :comments do
comments.map(&:content)
end
end
#controller
def index
@search = Article.search do
fulltext params[:search]
#對搜索結(jié)果進行分頁
paginate :page => params[:page] || 1, :per_page => 5
end
@articles = @search.results
end
#view
<%= form_tag articles_path, :method => :get do %>
<p> <%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
<% end %>
#安裝和啟動語句
rails g sunspot_rails:install
rake sunspot:solr:start
rake sunspot:reindex
282.Upgrading to Rails 3.1
略
283.Authentication with Sorcery
一種authentication solution,建議熟悉和使用devise
285. Spork
內(nèi)容略,作用為加快測試的啟動時間。
299.Rails Initialization Walkthrough
源碼解析。
305.Authentication with Warden
一種權(quán)限驗證系統(tǒng),現(xiàn)在流行devise,建議直接使用和熟悉devise.
308.Oh My ZSH
內(nèi)容略,在自己的簡書的工具篇中已經(jīng)有介紹。
314. Pretty URLs with FriendlyId
應(yīng)用場景,在url中根據(jù)model的name進行訪問,而不是根據(jù)id進行訪問,下面是具體的代碼:
沒有解決的問題有兩個:history(不能訪問歷史記錄)&internationalization(訪問中文出現(xiàn)問題)
rails g scaffold Article name:string content:text
#第一種方式是在model中重寫to_param方法
def to_param
"#{id}#{name}".parameterize
#或者使用類方法to_param
#to_param :name
end
上面的方法可以實現(xiàn)/articles/1name方法對article進行訪問,同時articles/1也是可以實現(xiàn)訪問
#第二種方法通過使用friendlyid方法實現(xiàn)
gem 'friendly_id'
class Article < ActiveRecord::Base
extend FriendlyId
friendly_id :name
end
class ArticlesController < ApplicationController
private
def set_article
@article = Article.friendly.find(params[:id])
end
end
上面的方法可以有/article/id和/article/name兩種實現(xiàn)方法來訪問article,但是問題是如果name中出現(xiàn)有空格或者是標(biāo)點符號則會在url中出現(xiàn)轉(zhuǎn)義字符,為了解決這個問題,下面給出解決方案
#article.rb
class Article < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
end
rails g migration add_slug_to_articles slug:string:uniq
class AddSlugToArticles < ActiveRecord::Migration
def change
add_column :articles, :slug, :string
add_index :articles, :slug, unique: true
#設(shè)置了slug,slug的索引值為true,使用相同的name時候會使用不同的后綴
end
end
#取消sha
#若對name進行了修改,但是在url中slug是不會被修改的,這次采取的方式是修改默認的方法。
#article.rb
class Article < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
#修改默認的方法,則每次name變動,那么slug值也會變動
def should_generate_new_friendly_id?
name_changed?
end
end
#如果slug是之后進行migration的,需要進行如下操作,更新每個slug的值
Article.find_each(&:save) #因為是新創(chuàng)建的字段,這條語句進行字段賦值
318.Upgrading to Rails 3.2
略
319.Rails Middleware Walkthrough
源碼解析
328.Twitter Bootstrap Basics
略,前端框架
368.MiniProfiler
默認在開發(fā)環(huán)境下加入下面的gem,就能在視圖界面看到具體的消耗時間
gem 'rack-mini-profiler'
下面介紹在開發(fā)環(huán)境下面顯示MiniProfiler
啟動開發(fā)環(huán)境:
rails assets:precompile
rails db:setup RAILS_ENV=production
rails s -e production
在開發(fā)環(huán)境中沒有啟動成功該插件,遇到的時候再討論。
372.Bullet
在development環(huán)境下添加gem,用于檢測兩個內(nèi)容,是否存在1+N問題和是否缺少counter cache column.自己未實現(xiàn),遇到情況再討論。
#gemfile
gem 'bullet', group: :development
#/config/initializers/bullet.rb
if defined? Bullet
Bullet.enable = true
Bullet.alert = true
end
374. Image Manipulation
略,功能介紹:通過使用rmagic這個工具在程序端實現(xiàn)改變照片的顏色,rmagic可以在終端通過命令行改變照片的一些屬性。
382. Tagging
講述通過兩種方法制作標(biāo)簽,一種通過gem,一種通過自己制作
第一種通過gem
#添加gem
gem 'acts-as-taggable-on'
#執(zhí)行終端
rake acts_as_taggable_on_engine:install:migrations #針對最新版本
rake db:migrate
#避免mysql的特殊字符錯誤
rake acts_as_taggable_on_engine:tag_names:collate_bin
#user.rb中添加
class Article < ActiveRecord::Base
acts_as_taggable
end
#添加強參數(shù)
class ArticlesController < ApplicationController
def user_params
params.require(:user).permit(:name, :content, :tag_list)
end
end
#view中添加字段
<div class="field">
<%= f.label :tag_list, "Tags (separated by commas)" %><br />
<%= f.text_field :tag_list %>
</div>
#view中顯示字段
Tags: <%= article.tag_list.map { |t| link_to t, tag_path(t) }.join(', ') %>
#config/routes.rb
get 'tags/:tag', to: 'articles#index', as: :tag
#點擊標(biāo)簽獲得相應(yīng)標(biāo)簽的文章:articles_controller.rb
def index
if params[:tag]
@articles = Article.tagged_with(params[:tag])
else
@articles = Article.all
end
end
#添加標(biāo)簽云
<div id="tag_cloud">
<% tag_cloud Article.tag_counts, %w{s m l} do |tag, css_class| %>
<%= link_to tag.name, tag_path(tag.name), class: css_class %>
<% end %>
</div>
#修飾標(biāo)簽云
#tag_cloud {
width: 400px;
line-height: 1.6em;
.s { font-size: 0.8em; }
.m { font-size: 1.2em; }
.l { font-size: 1.8em; }
}
385.Authorization from Scratch Part 1
案例是登錄用戶是否有權(quán)限,具體案例見tutorial
386.Authorization from Scratch Part 2
案例是登錄用戶是否有權(quán)限,具體案例見tutorial
Action Controller Walkthrough
源碼解析。
397.Action View Walkthrough
源碼解析。
**411.Performance Testing **
查看程序的瓶頸,類似miniprofile
412.Fast Rails Commands
加快程序運行的三種方式,分別是command,spring和zeus
413.Fast Tests
通過各種方式加快測試,內(nèi)容略。
415.Upgrading to Rails 4
略
417. Foundation
略,是一個前端框架,類似bootstrap。