RailsCasts

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[未实现]
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(未实现)
54.Debugging Ruby
55.Cleaning Up the View
56.The Logger
57.Create Model Through Text Field
58.How to Make a Generator(未实现)
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

实现的代码如下所示:

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

每次查询用户的时候都需要调用数据库,为了避免每次都调用数据库的行为,进行如下的优化:

@current_user ||= User.find(session[:user_id]) 

上面的代码等于于

@current_user = @current_user || User.find(session[:user_id]) 

当首次使用current_user方法的时候,@current_user的值为nil,则进行数据库调用,User.find(session[:user_id])会赋值给@current_user,当第二次调用current_user方法的时候,不会使用User.find(session[:user_id])方法,即不会调用数据库,直接使用被赋值后的@current_user。
注意:用户退出的时候设置@current_user=nil

2. dynamic find_by methods
这里的find_by无效,如果要获得数组数据,需要使用where方法

#建立模型
rails g model Task complete:string uncomplete:string
rails destroy model Task  #取消建模

Task.find(complete: "false") #该方法会报错,因为find方法里面只能出现id的值
Task.find_by(complete: "false")#该方法只有一个返回值,见api所示,因此在这个结果调用each方法则会报错,因为该对象没有each方法
Task.where("complete = ?", "false"),该方法返回全部为false值的数组对象,因此该结果可以调用each方法,而上面Taks.find_by方法只返回满足条件的第一个值。

3. find through association
在project中有很多的tasks,进行关联查询:

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中可以被多次调用,避免代码重复,代码如下所示:

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文档里面已经找不到了,相同功能的方法叫做scope,详细的用法在自己的一篇关于tag的文章中也有阐述,大概的使用功能及代码可以见下面所示,即是使用scope创建自定义的方法:

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}
#就是按照数据的第一个元素去重,然后按照数组的第二个元素排序

#作用:实现链式调用
all.collect(&:name).collect(&:upcase)

#除了collect,也可以应用在其他地方
#对每一个值进行遍历,并对其进行求值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.动态布局

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方法对单个的页面进行样式重置,实用性不太,因为基本的单个页面的布局已经可以通过layouts布局进行实现,遇到content_for案例再进行细究。
疑问:下面的案例提供引用两个css文件没有必要,因为rails4.2所有的css文件最终都变成一个css文件被导入。

#需要重置样式的页面,比如index.html.erb文件中
<% content_for :head do %> 
  <%= stylesheet_link_tag 'projects' %>
<% end %>

#在application.html.erb文件中写入如下代码

  <%= yield :head %>



  <%= yield %>

结合rails的api可以看出content_for方法是将一个block储存起来,以备未来使用,当执行到index,html.erb文件中中时,出现如下的代码呈现形式:


  <%= stylesheet_link_tag 'projects' %>

9. Filtering Sensitive Logs
按照railscast中的说明,对于敏感字段password而言,应该在下面的代码中进行设置:

class ApplicationController < ActionController::Base
  filter_parameter_logging "password" 
end

但是在rails4.2的项目中,filter_parameter_logging方法会报undefined method错误,应该是rails4.2中,对这个方法进行了舍弃,参考此文,进行如下设置:

#config/initializers/filter_parameter_logging.rb
Rails.application.config.filter_parameters += [:password] #其实是rails的默认设置

按照上面的设置,在log/development.log文件中,password字段显示的值为[FILTERED]

10. Refactoring User Name Part 1
对前端页面进行优化的方式,是将方法设置在model中,然后在view层进行调用,比如在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方法还可以进行优化,代码如下所示:

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
对测试进行优化,代码如下所示:

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
这部分知识阐述的是不要将数据存储在session中,容易造成数据的不同步现象,合理的方式是讲在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中预制了对数据进行统计的方法,如下所示:

rails scaffold Calculation priority:integer
Calculation.first.priority #查第一个数值
Calculation.sum(:priority)  #查平均数值
Calculation.minimum(:priority)  #查最小数值
Calculation.maximum(:priority) #查最大数值
Calculation.average(:priority).to_f #查平均数值

15. Fun with Find Conditions
使用ActiveRecord的条件查询,代码如下所示:

User.where(["name = ? and email = ?", "Joe", "[email protected]"])
User.where(["name = :name and email = :email", { name: "Joe", email: "[email protected]" }])

16. Virtual Attributes
一般情况下,在rails中,model中的属性要和数据库中的字段相对应,如果model中的属性没有和数据库的字段相对应,则这个属性就被称为虚拟属性,通用版本如下:

#字段如下:
create_table "users", :force => true do |t| 
  t.string "first_name" 
  t.string "last_name" 
  t.string "password" 
end

#表单如下:

Register

<% form_for @user do |form| %>
  1. <%= form.label :full_name, 'Full Name' %> <%= form.text_field :full_name %>
  2. <%= form.label :password, 'Password' %> <%= form.password_field :password %>
<% 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
#如果不添加hidden_field_tag参数,则勾选已经有的tag,则该tag不会删除 <%= hidden_field_tag "product[category_ids][]", nil %> <% Category.all.each do |category| %> #下面product[category_ids][]的依据可以参考rails guides的内容 <%= check_box_tag "product[category_ids][]", category.id, @product.category_ids.include?(category.id) %> <%= category.name %>
<% end %>

18. Looping Through Flash
一般在使用flash的时候都会迭代显示里面的信息,自己在实践的过程中按照如下代码进行设置和呈现:

#在controller文件中
def create
  if @user.save
    flash[:success] = "congratulation"
    .....
  end
end

#在application.html.erb文件中,进行如下的代码呈现
<% flash.each do |key, value| %>
  <%= key %>:<%= value%>
<% end %>

在本文的呈现中,flash在前端页面的呈现如下所示:

#关注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
以上这三个章节是介绍权限管理系统,我认为里面的提到很多方法和实际的rails4.2版本已经过时,但是思想是一致的,建立admin方法,对前端页面的展示进行过滤和分别呈现,现在比较合适的解决方案在ruby on rails tutorial第三版中能找到。

22. Eager Loading
eager loading的意思是贪婪加载,使用的场景出现在“1+N”的情形中,解决的方式是通过joins和includes方法对两个mode进行关联
joins 在数据库中表示: left outer join
includes 在数据库中表示: innner outer join
代码参考guides中的代码:

#从includes中的单复数判断,category has many articles, article has many comments
Article.includes(:category, :comments)

#出现嵌套形式
#category has many articles
#artilce has many comments and tags
#guest has many comments
Category.includes(articles: [{ comments: :guest},:tags])

#关联之后指定条件,下面两条内容一致
#使用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
出现的场景如下所示:

Class Article < ActiveRecord::Base
  has_many :comments
end

Class Comment 

在一篇文章中,有很多的评论,如果每一篇文章的评论数量,在执行下面的语句的过程中会有进行大量的数据库查询:

<% @articles.each do |article| %> 
  
  • <%= article.name %> (<%= article.comments.size %)
  • <% 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
        #如果不执行下面的语句,则article.comments.size的值都是增加了该字段之后的数据
        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文件中出现下面语句:

    #只调用了一次数据库而已
    Article Load (0.1ms)  SELECT "articles".* FROM "articles"
    

    24. The Stack Trace

    25. SQL Injection
    参考
    经过实践下面的代码:

    @articles = Article.where("name like '#{params[:search]}%'")
    

    如果在输入框中输入

    ';drop table demo;
    

    这样子会报错误,但是其实drop table demo的语句是不会执行的,这样子的错误也就是SQL注入错误。解决的方式是通过Array或者Hash的形式:

    Article.where( { :name => params[:search] } )
    # or
    Article.where( ["name = ?", params[:search] ] )
    

    在执行下面的查询方法的过程中,都需要使用上面的形式来规避SQL注入问题:

    find_by_sql
    execute
    where 用字串参数
    group
    order
    

    26. Hackers Love Mass Assignment
    在之前版本的rails系统中其实有mass assignment,这个功能很方便,但是用户可以从url中操作而恶意改变数据库中的数据,因此为了继续使用mass assignment同时规避恶意窜改数据,而使用strong paramete方式,比如User这个model中有三个字段,包括name,age,admin,其中admin是敏感字段,因此将name,age两个字段放入mass assignment中,具体代码实现如下,admin字段通过其他方式实现数据输入。

    def user_params
      params.require(:user).permit(:name,:age)
    end
    

    27. Cross Site Scripting
    这个问题主要是用户在提交内容的时候提交了可以运行的脚本文件,在rails3之后对这写脚本文件进行了禁止,因为在最新的rails项目上其实这个问题已经不存在了,因为默认对XSS(脚本跨站攻击),如果显示用户提交的脚本内容并且进行呈现,有下面的几种方式:

    #第一种:使用raw
    raw("

    safe

    ") #第二种:使用html_safe "

    safe

    ".html_safe #第三种:使用sanitize,一般情况下显示脚本使用这个方法 这个方法是应用白名单(认为有些参数是安全的,有限进行应用)的功能

    28. in_groups_of
    这个场景主要应用在数据多列展示,在传统的数据展示中,是按照单列进行数据展示,但是应用了这个方法可以对数据进行多列展示,如下代码:

     <% @articles.in_groups_of(3) do |articles|%>
       
         <% articles.each do |article| %>
           <%= article.name %>
         <% end %>
      
     <% end %>
    #上面的代码显示的是按照3列进行数据排列,但是如果如果出现空缺的话,会出现undefined method for NilClass错误,避免这个错误,可以添加可选参数
    #当选择false作为可选参数时,则空项为空显示
    <% @articles.in_groups_of(3, false) do |articles| %>
    #也可以选择其他参数,其他参数作为填充使用,出现空项,则填充该数据
    <% @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]
    #注意,经过实际演示,结果与api中演示不一致,说明api中数据陈列方式有误
    

    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提出的条件将一个数组转化为一个hash。hash的key是数组元素执行block之后得到的结果,value是原数组中执行block得到key的元素组成的数组。
    应用代码如下所示:

    #controller文件中
    @students=Student.find(:all)
    @[email protected]_by{|s| s.gender}
    
    #view文件中
    <% @student_groups.each do |gender,students| %>
      <%= gender %>
      
      <% students.each do |student| %>
    • <%= student.name%>
    • <% end %>
    <% end %> #执行结果如下所示: female .lucy .jessi malejack .jim .mike

    30. Pretty Page Title
    应用场景:对显示的每一篇文章,浏览器的显示标题栏应该是文章的题目,具体的代码演示如下:

    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文件中写入如下代码
    
      
        <% yield(:title)%>
      
    
    
    #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中调用该方法
    article.created_at.to_s(:time)
    

    32. Time in Text Field
    这个片段的是出现在编辑时间字段的时候,将时间字段集中在一个字符框中进行,而不是在多个选框中进行。
    出现时间选框的代码如下:

    rails g scaffold Article name:string time:datetime
    

    33. Making a Plugin
    使用最新的文档进行plugin的代码演示,然后回过头来看这边的代码,关于plugin制作的格式可以参考最新的,但是这个片段中的代码的一些方法可以参考如何使用。

    34. Named Routes
    视频中信息陈旧,可以参考rails guides中的内容,具体代码如下所示:

    #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,前者可以生成当前路径,后者会生成全路径。

    35. Custom REST Actions
    视频信息陈旧,主要讲的是通过一般情况下如下的代码其实可以实现一般的路由设置,代码如下所示:

    resources :articles
    

    但是这个资源只能实现index,show,edit,new,update,destroy,create这七个action,对于如果要在资源中设置其他的action需要自己设定,代码如下:

    #在controller中进行设置
    class ArticlesController < ApplicationController
      def search
      end
    end
    #在route.rb中进行设置
    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
    这个章节的内容主要做一个简单的全文检索,然后我自己在此基础上扩展功能,从单字段的检索发展到多字段的检索。
    简单的全文检索代码如下所示:

    #projects/index.html.erb
    #和form_for不同,form_for需要model,而form_tag不需要#model,因此对于需要
    #model的form_for,若或许参数是通过params[:session][:email],
    #而对于不需要model的form_tag,获取参数只需要params[:search]
    <%= form_tag projects_path, :method => 'get' do %>
      

    <%= text_field_tag :search%> <%= submit_tag "Search" %>

    <% 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
    这个场景主要出现在对文章进行预览,代码如下所示:

    #终端执行下面的代码
    rails g scaffold Article name:string content:text
    
    #在controller中改写如下代码
    def create
      @article = Article.new(article_params)
      #如果params[:preview_button]存在,则后面的[email protected]不执行,如果params[:preview_button]不存在,则执行后面的语句
      if params[:preview_button] || [email protected]
        render 'new'
      else
        flash[:notice] = "successfully created project"
        redirect_to @article
      end
    end
    
    #在new.html.erb中改写如下代码:
    <% if params[:preview_button]%>
      <%= @article.content%>
    <% end %>
    
    #在form表单中添加预览表单
    <%= submit_tag "Preview", name: "preview_button" %>
    

    39. Customize Field Error
    这个章节的内容应用场景是当对某个字段进行validates的时候,这个字段在内容显示的时候自动被下面的样式所包围:

    为了改变这个scaffold自动生成的样式,可以进行如下的调整:
    两篇参考分别是参考一和参考二

    #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设置为field_error,见如下代码:
    ActionView::Base.field_error_proc = Proc.new do |html_tag, instance| 
      "#{html_tag}".html_safe
    end
    

    按照参考一内容,也可以通过下面的形式设置:

    .field_with_errors {display: inline;}
    

    40. Blocks in View

    41. Conditional Validations
    这个场景出现选择某个情景进行验证的情况下,具体代码呈现如下:

    rails g scaffold Article name:string content:text
    
    #article.rb文件中
    class Article < ActiveRecord::Base
      #下面这条语句在进行@article.save的过程中就会执行
      validates :name, presence:true
      #下面这条语句只有在方法is_test?为真的情况下才会执行
      validates :content, presence:true, if: :is_test?
    
      def is_test?
        false
      end
    end
    

    42. with_options
    这个功能主要是为了避免代码重复,演示代码如下所示:

    #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减少重复代码:

    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
    这个应用场景是使用类似正则表达式的方式匹配路由,对于任何满足正则表达式的路由,都匹配该路径。代码如下所示:

    #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
    视频不用看,已经陈旧。
    最新的文档

    51. will_paginate
    自己比较喜欢bootstrap这个js框架,所以做开发的时候一般前端产品都用这个。使用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
    场景:应用在批量对属性进行更新
    具体代码如下:

    #终端执行
    rails g scaffold Task name:string success:boolean
    
    #根据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 %>
      
      <% @uncompletes.each do |uncomplete| %>
    • <%= check_box_tag "uncomplete_ids[]", uncomplete.id %> <%= uncomplete.name %>
    • <% end %>
    <%= 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
    这个章节主要是如何进行调试,在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
    
    #进行调试
    在想要进行调试的地方增加下面的语句
    debugger
    
    help # 查看哪些方法
    next # 执行需要调试的下一条语句
    pp @today_tasks #打印这条值
    step #进入该方法中的内部方法,如果不是自己想要的,可以执行next,可以跳到该方法中的另外一个方法
    irb  #可以在平台中执行该语句puts where(due_at: range).to_sql
    

    byebug的其他用法可以见API
    55. Cleaning Up the View
    这个章节的内容主要讲的是消除前端的臃肿,把逻辑代码放在controller或者是model中。具体的代码案例来自于agile development with rails.

    56. The Logger
    在log文件中查看程序中的执行情况,代码如下:

    def index 
      @articles = Article.all 
      logger.debug "Articles Count: #{Article.count}"
    end
    

    设置log等级,大于或者等于这个等级的log才能被载入:

    #/config/environments/development.rb
    config.log_level = :warn
    #等级依次为:debug, :info, :warn, :error, :fatal, and :unknown
    

    给log设置标签

    #/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
    

    格式化输入标签内容

    #/config/initializers/log_formatter.rb
    class Logger::SimpleFormatter 
      def call(severity, time, progname, msg) 
        "[#{severity}] #{msg}\n"
      end
    end
    

    不要输入asset的内容

    #去除asset pipeline
    gem 'quiet_assets', group: :development
    #去除warning messages.
    gem 'thin', group: :development
    #使用thin服务器开启web服务
    rails s thin
    

    57. Create Model Through Text Field
    这个章节实现两个功能,分别是通过选择框添加tag和通过输入框添加tag,详细的代码演示如下:

    #终端执行下面代码
    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参数会被遗漏,不能从view传递到model
    def product_params
      params.require(:product).permit(:name, :content, :category_id, :new_category_name)
    end
    
    #view中
    
    #注意下面选择框的格式 <%= f.collection_select(:category_id, Category.all, :id, :name, prompt: "请选择")%> <%= f.text_field :new_category_name %>

    58. How to Make a Generator
    59. Optimistic Locking
    应用场景,当用户对一个字段进行编辑时,另外一个用户刚好更新过了这个字段,然后就会报错,这里介绍两种解决方式。
    第一种,使用乐观锁字段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这个参数
    
    #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
    

    第二种方法:不适用锁机制。上面的这种方法功能已经比较完善,第二种方法不理解,下次遇到再说。

    **60. Testing without Fixtures **
    看不懂,完整懂了测试章节再看。

    61. Sending Email

    64. Custom Helper Modules
    定制一个helper方法,对所有的controller都有用

    #在app/helpers中建立如下文件
    category_helper.rb
    
    #在controllers/application_controller.rb中写入如下语句
    helper :category  #将category_helper.rb中代码应用到所有controller中
    helper :all  #所有在app/helpers中的文件应用到controller中
    

    67. restful_authentication
    一种用户登录的方案,感觉已经过时,替代方案是devise
    70.Custom Routes
    定制routes,见最新的guides

    72. Adding an Environment
    rails默认有三个环境,分别是development,production,test,其实可以自己定制属于自己的环境,具体代码如下:

    #建立如下的文件
    config/environments/staging.rb
    #可以将production.rb文件中的内容复制到该文件中
    #开始这个系统的代码如下:
    rails s -e staging
    #到这个环境的console平台中
    rails c staging
    RAILS_ENV=staging rails s #和上面的功能类似
    #如果设置默认的环境为staging,则可以有如下的表示方式
    export RAILS_ENV=staging
    #可以在gem文件中添加专门给staging的gem
    group :staging do 
      gem 'ruby-prof'
    end
    #在/config/application.rb文件中设置专门针对某个group的gem
    #下面这段代码不是很懂,下次遇到问题再说
    if defined?(Bundler) 
      Bundler.require(*Rails.groups(:assets => %w(development test), :profiling => %w[staging development])) 
    

    78. Generating PDF Documents
    pdf-writer 这个gem已经被prawn取代。

    80.Simplify Views with Rails 2.0
    这个场景就是前端模块化,默认在使用scaffold的过程中,表格是会被提取出来单独使用的,比如_form.html.erb,这个章节将的是讲资源的单个内容抽取出来,并在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内容
    <%= render partial: @article %>
    
    #views/articles中修改index.html.erb内容
    <%= render partial: @articles%>
    

    81. Fixtures in Rails 2.0
    就是进行测试的时候放在test/fixtrues文件夹下面的固件,好处在于不用和ActiveRecord进行交互,但是其实有其他替代方法。视频内容略。

    82. HTTP Basic Authentication
    场景应用在对某个action实现进行过滤,实现的代码如下:

    #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
    这个章节的内容在guides中都都可以找到,主要是讲migration的命令以及建立删除数据库或者字段的语句,容易遗漏的地点,建立的数据库的语句如下:

    rake db:create
    

    因为通常情况下默认是sqlite数据库,默认已经建立,所以这条语句可以省略,如果换做是其他数据库的话,需要使用这条语句。

    85. YAML Configuration
    应用场景:将一些隐私的信息写在配置文件里面,不要出现在MVC架构中,详细代码如下所示:

    #controller文件
    http_basic_authenticate_with name: ENV["BLOG_USERNAME"], password: ENV["BLOG_PASSWORD"]
    
    #config文件中
    #建立application.yml文件,写入如下内容
    BLOG_USERNAEM: "jayzen"
    BLOG_PASSWORD: "111111"
    
    #在application.rb文件中添加如下内容
    #每次文件进行加载的时候都会这个application.yml文件进行载入
    ENV.update YAML.load(File.read(File.expand_path('../application.yml', __FILE__)))
    

    89.Page Caching
    参考guides,page caching已经被单独成为一个gem,但是这个gem不能被rails5使用,以后遇到再说,可能这个gem已经被更新。

    90.Fragment Caching
    参考guides,guides中内容不能在log文件中找到对应的显示,log中没有显示caching内容。

    96. Git on Rails

    109. Tracking Attribute Changes
    场景主要应用在追踪最近更新的数据变化,代码显示操作如下所示:

    rails g scaffold Task name:string
    
    #预存了一段内容,其中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
    这个片段体现了下面的几个场景:1.实现了高级查询,其实就是多条件查询 2.对用户的查询习惯进行保存 3.用户自行建立task任务
    代码如下所示:

    #使用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
    

    Advanced Search

    <%= form_for @search do |f| %>
    <%= f.label :keywords %>
    <%= f.text_field :keywords %>
    <%= f.label :category_id %>
    <%= f.collection_select :category_id, Category.order(:name), :id, :name, include_blank: true %>
    <%= f.label :min_price, "Price Range" %>
    <%= f.text_field :min_price, size: 10 %> - <%= f.text_field :max_price, size: 10 %>
    <%= f.submit "Search" %>
    <% end %> #show.html.erb

    Search Results

    <%= render @search.products %> #使用task方法对保存的查询记录进行删除 #lib/tasks/searches.rake desc "Remove searches older than a month" #如果要与数据库进行交互,必须使用指明:environment task :remove_old_searches => :environment do Search.delete_all ["created_at < ?", 1.month.ago] end #执行上面的代码rake task names #rake remove_old_searches

    **113.Contributing to Rails with Git **
    内容略
    116.Selenium
    内容略,讲述的是在浏览器端对内容进行测试。

    120. Thinking Sphinx
    Sphinx没有安装成功

    126. Populating a Database
    populator没有支持rails3,更没有支持rails4,不过可以从这里学习到在lib/tasks/文件夹下面,建立task后缀文件,终端执行rake db:taskname文件

    139.Nested Resources
    嵌套路由,见最新的guides

    155.Beginning with Cucumber
    cucumber是一个测试框架,内容略。
    156. Webrat
    测试框架,内容略。

    158.Factories not Fixtures
    讲述测试内容fixture,内容略。

    159.More on Cucumber
    内容略,讲述关于测试框架cucumber的更多内容。

    160. Authlogic
    一种authentication solution,建议直接使用和熟悉devise

    169.Dynamic Page Caching
    参考最新的rails guides和episode 89 page caching

    179. Seed Data
    使用seed方式生成数据库数据,下面介绍两种:

    #第一种从网络上抓取数据
    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
    在系统中发现一些未被使用的CSS。

    182. Cropping Images
    应用场景:用户对上传的图片进行个性定制

    187.Testing Exceptions
    进行测试,内容略。
    188.Declarative Authorization
    内容略,用户的权限管理机制,推荐简单的处理方式,比如使用在user中增加admin字段。
    189.Embedded Association
    内容略,权限管理机制,推荐使用cancancan

    190. Screen Scraping with Nokogiri
    实现案例:获取某个网页下面的某个链接内容,进入该链接,获取该链接下面的内容

    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}该节点为空"
      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
    #获取其中的文本内容
    doc_one.at_css(".t_f span a").text
    #对获取的文本内容记性匹配
    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,格式如下所示

    #内容格式
    desc "Fetch product prices" 
    task :fetch_prices => :environment do 
    #db/seed.rb内容一致
    end
    
    #执行这里面的代码
    rake demo.task
    

    200.Rails 3 Beta and RVM
    内容都已经清楚,略。

    201.Bundler
    内容略,但是在这里发现了在rake db:migrate的时候经常出现的一个问题,出现的问题显示为gemfile.lock中rake版本太低,而rails项目已经出发了最新的版本,我一般的解决方法是在gemfile.lock中将rake的版本按照提示提高,但是本文的介绍的两外一种方法:

    bundle exec rake db:migrate
    

    这条语句意思是按照gemfile.lock中rake版本执行rake,就不会出现上面的错误。
    202. Active Record Queries in Rails 3
    查询的内容查看guides内容,下面具体说下使用scope
    scope的两种形式

    #使用macro-style形式
    class Article < ApplicationRecord
      scope :visible, -> { where("hidden=?", true) }
      #必须使用块对象的形式,下面的格式产生同样作用
      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定义的方法可以使用链式调用

    Article.visible.view
    

    203. Routing in Rails 3
    内容已经陈旧,看最新的guides内容

    204.XSS Protection in Rails 3
    参看上面的episode27内容,默认情况下rail3以及以后对用户提交的html进行了转义,防止xss攻击,如果要显示html标签内容,可以参考episode27中内容,一般使用sanitize方法会认为是安全的,另外两个方法会存在安全漏洞,在并不是很了解的rails安全措施的情况下。

    206. Action Mailer in Rails 3
    内容略,已经过时。
    207. Syntax Highlighting
    场景:实现语法高亮和markdown

    使用gem:pygments.rb对整个属性实现代码高亮

    #添加gem
    gem "pygments.rb"
    
    #show.html.erb
    <%= raw Pygments.highlight(@article.content) %>
    
    #/app/assets/stylesheets/pygments.css.erb
    #在上面这个文件夹中添加pygments.css.erb这个文件,内容如下
    <%= Pygments.css %>
    

    使用simple_format方法也可以对整条语句显示格式

    <%= simple_format @article.content %>
    #如果里面添加诸如的标签会文字进行属性miao
    

    使用redcarpet进行markdown,结合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的形式来书写一篇代码,然后给出相应的simple_for形式。

    下面介绍rails的数据类型和sql数据类型

    :benlean #=>TINYINT(1),1个字节,表示0~255的整数
    :date #=>DATE
    :time #=>TIME
    :datetime #=>DATETIME
    :timestamp #=>DATETIME
    :float #=>FLOAT
    :decimal #=>DECIMAL,decimal和foat的精度不同
    :integer #=>INT
    :string #=>VARCHAR
    

    该episode中的数据结构如下

    #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表单中的数据呈现如下:

    #_form.html.erb
    <%= form_for(product) do |f| %>
      
    <%= f.label :name %> <%= f.text_field :name %>
    <%= f.label :price %> <%= f.text_field :price %>
    <%= f.label :release_on %> <%= f.date_select :release_on %>
    <%= f.label :discontinued %> <%= f.check_box :discontinued %>
    <%= 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
    <%= f.label :publisher %> <%= f.collection_select :publisher_id, Publisher.all, :id, :name, prompt: true %>
    <%= 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 %>
    <% end %>
    <%= f.submit %>
    <% 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
    给邮件名称建立统一标识图像,具体见tutorial。

    250. Authentication from Scratch
    一个权限系统,详细见tutorial教程

    253. CarrierWave File Uploads
    实现场景包括:文件(包括图片)上传,文件下载(包括图片展示)

    #添加carrierwave
    gem 'carrierwave'
    
    #添加资源
    rails g scaffold Resume name:string attachment:string
    
    #建立upload
    rails g uploader attachment
    
    #在model中标记那个属性值需要上传
    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 %>
      #图片呈现
      <%= 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
    测试,内容略。

    264.Guard
    自动测试时使用,内容略
    270. Authentication in Rails 3.1
    介绍3.1中关于权限的三个feature

    1.http_basci_authenticate_with
    2.has_secure_password/password_digest
    3.force_ssl
    

    272 Markdown with Redcarpet
    已经过时,见207 Syntax Highlighting

    274. Remember Me & Reset Password
    记住和密码重置,详见tutorial代码

    275.How I Test
    内容略,讲述测试内容。

    278. Search with Sunspot
    搜素的解决方案,这里只介绍安装和一般用法,具体内容可以重新看wiki和asciicast,具体代码参见如下:

    #需要安装Java环境
    #两个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是提高权重
      text :name, :boost => 5 
      text :content
      #关联comment
      text :comments do 
        comments.map(&:content) 
      end 
    end
    
    #controller
    def index 
      @search = Article.search do 
        fulltext params[:search]
        #对搜索结果进行分页
        paginate :page => params[:page] || 1, :per_page => 5 
      end 
      @articles = @search.results
    end
    
    #view
    <%= form_tag articles_path, :method => :get do %> 
    

    <%= 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
    内容略,作用为加快测试的启动时间。

    299.Rails Initialization Walkthrough
    源码解析。
    305.Authentication with Warden
    一种权限验证系统,现在流行devise,建议直接使用和熟悉devise.
    308.Oh My ZSH
    内容略,在自己的的工具篇中已经有介绍。

    314. Pretty URLs with FriendlyId
    应用场景,在url中根据model的name进行访问,而不是根据id进行访问,下面是具体的代码:
    没有解决的问题有两个:history(不能访问历史记录)&internationalization(访问中文出现问题)

    rails g scaffold Article name:string content:text
    
    #第一种方式是在model中重写to_param方法
    def to_param
      "#{id}#{name}".parameterize
      #或者使用类方法to_param
      #to_param :name
    end
    上面的方法可以实现/articles/1name方法对article进行访问,同时articles/1也是可以实现访问
    
    #第二种方法通过使用friendlyid方法实现
    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两种实现方法来访问article,但是问题是如果name中出现有空格或者是标点符号则会在url中出现转义字符,为了解决这个问题,下面给出解决方案
    
    #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
        #设置了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) #因为是新创建的字段,这条语句进行字段赋值
    
    
    
    

    318.Upgrading to Rails 3.2

    319.Rails Middleware Walkthrough
    源码解析

    328.Twitter Bootstrap Basics
    略,前端框架

    368.MiniProfiler
    默认在开发环境下加入下面的gem,就能在视图界面看到具体的消耗时间

    gem 'rack-mini-profiler'
    

    下面介绍在开发环境下面显示MiniProfiler
    启动开发环境:

    rails assets:precompile
    rails db:setup RAILS_ENV=production
    rails s -e production
    

    在开发环境中没有启动成功该插件,遇到的时候再讨论。

    372.Bullet
    在development环境下添加gem,用于检测两个内容,是否存在1+N问题和是否缺少counter cache column.自己未实现,遇到情况再讨论。

    #gemfile
    gem 'bullet', group: :development
    
    #/config/initializers/bullet.rb
    if defined? Bullet 
      Bullet.enable = true 
      Bullet.alert = true
    end
    

    374. Image Manipulation
    略,功能介绍:通过使用rmagic这个工具在程序端实现改变照片的颜色,rmagic可以在终端通过命令行改变照片的一些属性。
    382. Tagging
    讲述通过两种方法制作标签,一种通过gem,一种通过自己制作
    第一种通过gem

    #添加gem
    gem 'acts-as-taggable-on'
    
    #执行终端
    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
    
    #添加强参数
    class ArticlesController < ApplicationController 
      def user_params 
        params.require(:user).permit(:name, :content, :tag_list) 
      end
    end
    
    #view中添加字段
    
    <%= f.label :tag_list, "Tags (separated by commas)" %>
    <%= f.text_field :tag_list %>
    #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 #点击标签获得相应标签的文章:articles_controller.rb def index if params[:tag] @articles = Article.tagged_with(params[:tag]) else @articles = Article.all end end #添加标签云
    <% 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 %>
    #修饰标签云 #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
    案例是登录用户是否有权限,具体案例见tutorial
    386.Authorization from Scratch Part 2
    案例是登录用户是否有权限,具体案例见tutorial
    Action Controller Walkthrough
    源码解析。
    397.Action View Walkthrough
    源码解析。
    **411.Performance Testing **
    查看程序的瓶颈,类似miniprofile
    412.Fast Rails Commands
    加快程序运行的三种方式,分别是command,spring和zeus
    413.Fast Tests
    通过各种方式加快测试,内容略。

    415.Upgrading to Rails 4

    417. Foundation
    略,是一个前端框架,类似bootstrap。

    你可能感兴趣的:(RailsCasts)