`
zqhxuyuan
  • 浏览: 32365 次
  • 性别: Icon_minigender_1
  • 来自: 福建
社区版块
存档分类
最新评论

Agile Web Development with Rails 4E 学习笔记1

阅读更多

 

Agile Web Development with Rails 4E 2011.03   

========zqhxuyuan@gmail.com 2011.10========

 

===========================================

Chapter6. Task A: Creating the Application

1.1 创建Rails项目depot:

> rails new depot 

1.2 切换到depot目录下:

> cd depot 

使用Rails3默认的数据库SQLite3

1.3 创建项目的脚手架:

> rails generate scaffold Product 

title:string description:text image_url:string price:decimal

生成数据库脚本: db/migrate/create_products.rb 如果想查看表结构:db/schema.rb

Model: app/models/product.rb

View: app/views/products/*.html.erb

Controller: app/controllers/products_controller.rb

test: test/unit/product_test.rb  test/functional/products_controller_test.rb

(注意:Model是单数,以及Model的单元测试test/unit/product_test.rb

复数的有:View:products/ 

Controller:products_controller.rb 以及Controller的Fucntional测试:products_controller_test.rb)  

1.4 修改Product对应的表的某个字段的长度和精度,修改后需要和原先的数据库进行migrate:

-> db/migrate/create_products.rb

class CreateProducts < ActiveRecord::Migration

t.decimal :price, :precision => 8, :scale => 2

end

> rake db:migrate  

1.5 启动Rails内置服务器WEBrick,访问以上URL,查看Products列表:

> rails server

@ http://localhost:3000/products

点击列表页面的New Product进入http://localhost:3000/products/new

在新增页面输入数据,提交,并返回 http://localhost:3000/products 则可以看到新增的记录

分析CRUD的流程1--页面跳转:

http://localhost:3000/products/ 满足app/controllers/products_controller.rb ProductsController 

的URL命名约定: GET /products 对应的方法是: index 

在index方法里取得所有的products: @products = Product.all

页面指向respond_to -> format.html # index.html.erb 即app/views/products/index.html.erb

(# index.html.erb是注释,因为该方法名为index,所以format.html的值为:index.html.erb)

在index.html.erb中@products.each do |product|取出所有的products循环输出每个Product的信息

数据的获取是通过Json方式,Controller中在指向index.html.erb时获取到了Json数据: format.json { render json: @products }

新增Product,路径为:link_to new_product_path 根据Rails的命名约定满足 

GET /products/new 的URL(link_to: Get; new_product_path: /products/new ). 会调用Controller的new方法并指向new.html.erb

new.html.erb 只有一行代码: <%= render 'form' %> 指向_form.html.erb

_form.html.erb 有两部分组成,一是错误信息的显示,比如提交时数据验证失败显示错误信息;第二部分即是表单的数据了

在新增页面提交表单 最终会调用到Controller的create方法,保存数据...

1.7 测试以上所写的代码是否正确:

> rake test

This is for the unit, functional, and integration tests that 

Rails generates along with the scaffolding. 注意当修改了Controller,Model中的代码时,

运行rake test可能会报错,这时候需要对test/中相应的测试文件进行修改.

1.8 在服务器启动时,进行初始化数据的导入.下面这种方式更加对象化,而不是用insert SQL语句:

-> db/seeds.rb

Product.create(:title=>'sth',:description=>'sth',:image_url=>'spath',:price=>11.22)

> rake db:seed  

@ http://localhost:3000/products

 

1.9 关于全局Layout:

app/views/layouts/application.html.erb 

所有的views/*/*.html.erb都将继承application.html.erb的布局.可以在这里写每个页面固定的开头和结尾.

Rails keeps a separate file that is used to create a standard page environment for the entire application

 

application.html.erb, be the layout used for all views for all controllers that don’t otherwise provide a layout.

除非Controller有自己的Layout会覆盖掉全局的Layout.否则Application Layout会应用到所有的视图里.

 

We loaded some test data into the database(1.8), we rewrote the index.html.erb file

that displays the listing of products, we added a depot.css stylesheet, and that

stylesheet was loaded into our page by the layout file application.html.erb(1.9). 

 

===========================================

Chapter 7. Task B: Validation and Unit Testing

2.1 给Product Model添加字段验证:

-> app/models/product.rb

class Product < ActiveRecord::Base

validates :title, :description, :image_url, :presence => true

validates :price, :numericality => {:greater_than_or_equal_to => 0.01}

validates :title, :uniqueness => true

validates :image_url, :format => {

:with => %r{\.(gif|jpg|png)$}i,

:message => 'must be a URL for GIF, JPG or PNG image.'

}

end

访问http://localhost:3000/products/new 提交时会对输入域进行验证 如果验证失败则会在页面顶部显示错误信息.

2.2 给Model添加验证后的单元测试:

> rake test

运行测试脚本,会发现报错test/functional/products_controller_test.rb:

test_should_create_product test_should_update_product 

很显然当我们增加了Model的验证代码,测试部分也需要更改:

在测试脚本文件中ProductsControllerTest 的setup方法里初始化一个Product对象@update

并在2个报错的方法里把product: @product.attributes 改为 :product => @update指向初始化的product对象

setup方法第一行: @product = products(:one) 获取test/fixtures/products.yml中的数据

这是测试文件初始化加载的数据,正如seeds.rb是项目启动时初始化加载的数据

2.3 test类型有2种:

unit针对Model测试 test/unit/product_test.rb 

class ProductsControllerTest < ActionController::TestCase

可以运行:> rake test:units

functional针对Controller测试 test/functional/products_controller_test.rb 

class ProductTest < ActiveSupport::TestCase 

可以运行命令:>rake test:functionals

rake test 会测试整个项目是否有错误

===========================================

Chapter 8. Task C: Catalog Display

3.1 创建前台Product展示的控制器和页面:

> rails generate controller store index

创建StroeController和对应的Controller的index方法

和rails generate scaffold不同的是创建脚手架会创建Model,Controller,View,数据库脚本,测试文件等

而generate controller则只创建Controller:

app/controllers/store_controller.rb

app/views/store/index.html.erb

test/functional/store_controller_test.rb

还有一点区别是用generate scaffold创建的View和Controller是复数形式,Model是单数;

而generate controller则是单数.

3.2 上面的命令创建了StoreContoller以及index方法,通过URL: 

http://localhost:3000/store/index则会调用对应的方法.进入views/store/index.html.erb

-> config/routes.rb 

root :to => 'store#index', :as => 'store'

3.3 删除原先根目录下对应的文件:

> rm public/index.html 

当访问 http://localhost:3000 等价于上面的http://localhost:3000/store/index

进入的页面是: views/store/index.html.erb

3.4 访问规则测试:

http://localhost:3000/products 进入后台ProductList的显示页面views/products/index.html.erb

http://localhost:3000/products/index 则会报错:

ActiveRecord::RecordNotFound in ProductsController#show Couldn't find Product with id=index

http://localhost:3000/store 报错:Routing Error No route matches [GET] "/store"

由此可见通过generate scaffold,URL:/products代表访问的是ProductsController的index方法.

但是不能这样子访问:/products/index.

而通过generate controller,contoller中定义了哪些方法,

要访问该方法对应的页面则在controller后加上/方法名即可对应.

===========================================

Chapter 9. Task D: Cart Creation

4.1 创建购物车对象脚手架.但是没有给Cart指定字段:

> rails generate scaffold cart

> rake db:migrate

-> app/controllers/application_controller.rb

class ApplicationController < ActionController::Base

protect_from_forgery

private

def current_cart

Cart.find(session[:cart_id])

rescue ActiveRecord::RecordNotFound

cart = Cart.create

session[:cart_id] = cart.id

cart

end

 

4.2 创建购物项的脚手架:

> rails generate scaffold line_item product_id:integer cart_id:integer

> rake db:migrate

4.3 目前为止的数据库脚本(schema.rb):

create_table "carts"

end

 

create_table "line_items"

t.integer  "product_id"

t.integer  "cart_id"

end

 

create_table "products"

t.string   "title"

t.text     "description"

t.string   "image_url"

t.decimal  "price",       :precision => 8, :scale => 2

end

由此可见line_items可以当做carts和products的中间表.

 

4.3 Connecting Products to Carts: 将Product和Cart互相关联

-> app/models/cart.rb

Cart 

has_many :line_items

-> app/models/line_item.rb

LineItem 

belongs_to :product 

belongs_to :cart

-> app/models/product.rb

Product 

has_many :line_items

Cart 1---->N LineItem N<----1 Product ...Order

一个Cart可能有多个LineItem,一个Product也可能有多个LineItem(多个LineItem可能对应一个Product)

 

4.4 line_items涉及到的级联删除:

 

4.5 给前台的每个Product添加一个购买按钮:

-> app/views/store/index.html.erb

<%= button_to 'Add to Cart', line_items_path(:product_id => product) %>

button_to line_items_path(:product_id => product) 是如何调用到LineItemsController的create方法?

button_to : POST ; line_items_path : /line_items

LineItemsController中满足POST /line_items的只有create方法

如果是link_to line_items_path. link_to : GET line_items_path 则对应的方法为index

-> app/controllers/line_items_controller.rb

def create

@cart = current_cart

product = Product.find(params[:product_id])

@line_item = @cart.line_items.build(:product => product)

#...

end

为什么是LineItemsController.create而不是CartsController.create.

而且ApplicationController中Cart.create是在哪里定义的?(这个稍后解释)

把Product加入购物车中,即创建了一个购物项.所以使用的是LineItemsController.create.

find the shopping cart for the current session(@cart = current_cart), 

add the selected product to that cart(@cart.line_items.build), and display the cart contents.

pass that product we found into @cart.line_items.build. 

This causes a new line item relationship to be built between the @cart object and the product.

4.6 添加一个购物项后指向Cart页面,而不是购物项本身:

在LineItemsController.create方法中,

if @line_item.save #保存后

format.html { redirect_to @line_item.cart }

Since the line item object knows how to find the cart object, 

all we need to do is add .cart to the method call

那么调用的是CartsController的哪个方法index? show? 换句话说进入的是哪个页面?

@line_item.cart 通过LineItem得到Cart对象,所以实际上是传递了cart_id这个参数.

所以URL的形式应该是/carts/cart_id 类型为GET.满足的方法是show

可以这么理解:将一个购物项加入购物车中,而且这个购物车是Session中唯一的.

如果是/casts即所有的购物车List.显然在我们的应用中是说不通的.

所以app/views/carts/show.html.erb 通过Cart取出当前购物车中所有的购物项

<% @cart.line_items.each do |item| %>

<li><%= item.product.title %></li>

<% end %>

4.7 添加购物项的Functional测试:

因为LineItemsController修改的是create方法.接收参数:product_id

所以test/functional/line_items_controller_test.rb 修改的也是对应的create方法并传递需要的参数:

post :create, :product_id => products(:ruby).id 

products(:ruby)是test/fixtures/products.yml中的ruby:对应的记录.

测试重定向: assert_redirected_to cart_path(assigns(:line_item).cart)

cart_path:/carts/ assigns(:line_item).cart把购物项对应的购物车对象的id取出来并设置值,即cart_id

运行测试命令: rake test:functionals

有点不明白这里的Functional测试,在前台Product展示页面添加一个购物项到购物车中,

这里能调用到测试的代码吗? 

4.8 测试Session:

在Window上跑Ruby有点慢.有时候启动服务器,刷页面,但是没有反应.

还有更奇怪的问题是,有时候点击Add To Cart,浏览器的地址不是:http://localhost:3000/carts/3

而是http://localhost:3000/line_items?product_id=1 页面会报错说没有line_items这个方法.

这时候可以对服务器Ctrl+C终止下. 然后他就会报一堆的错,但页面却恢复正常了. 这里估计没有完全中止服务器.

测试Session,可以这样子做.关掉浏览器.Session中保留的cart_id消失.

重新访问http://localhost:3000. 点击某个Product购买,URL变为: http://localhost:3000/carts/4 

这里的4是新生成的Session中的cart_id.因为如果Session中找不到cart_id 

则会重新创建一个新的Cart对象,并把cart_id放入Session中.

同时购物车中的数据只会显示当前添加的Product.

关掉浏览器之前的那次会话的数据(sessionId=3)是不会存在在当前的这个Session中(sessionId=4).

4.9 查看别的数据:

如果想看LineItems,即所有Cart对应哪些Product. 访问:http://localhost:3000/line_items

似乎有点难以理解. 因为一般来说一个浏览器在当前只会有一个Cart,即一个Session中只能有一个Cart.

不过这个结果可以理解为另一种概念: 浏览器的访问历史记录.

如果访问http://localhost:3000/carts 则是看不到数据的.

但是会有多个Show Edit Destroy链接.不过这样的URL没有什么意义了.

 

1
1
分享到:
评论

相关推荐

    Agile+Web+Development+with+Rails中文版.pdf

    在《Agile Web Development with Rails》中,读者可以学习到如何运用敏捷方法来规划项目,实施增量式开发,并通过频繁的反馈来提高产品质量。 Ruby on Rails(简称Rails)是一个基于Ruby语言的开源Web开发框架,它...

    Agile Web Development with Rails 4

    Ruby on Rails helps you produce high-quality, beautiful-looking web applications quickly. You concentrate on creating the application, and Rails takes care of the details., Tens of thousands of ...

    Agile Web Development with Rails

    《Agile Web Development with Rails》(敏捷Web开发:Ruby on Rails)这本书,作为Rails开发新手的教材,强调了敏捷开发方法,并以其帮助开发者建立起一个实用的Web应用。从给出的文件信息来看,这本书正在编写过程...

    Agile Web Development with Rails 1-14节_ppt(老师发的修正版)

    Agile Web Development with Rails 1-14节_ppt(老师发的修正版)

    agile web development with rails 5(英文电子书)

    agile web development with rails 5(英文电子书).............................................................................................................................................................

    Agile Web Development with Rails (PDF)

    《敏捷Web开发与Rails》是一本深度探讨如何利用Ruby on Rails框架进行敏捷Web开发的指导书籍,由Dave Thomas、David Heinemeier Hansson等多位在Rails社区有着深厚贡献的作者共同编写。本书不仅覆盖了Rails的基本...

    Agile Web Development with Rails 3nd Edition Beta.pdf

    ### 敏捷Web开发与Rails 3:关键知识点解析 #### 一、Rails版本与兼容性 本书《敏捷Web开发与Rails》第三版是基于Rails 2编写的。截至本书印刷时,当前可用的Rails Gem版本为2.1。书中所包含的所有代码均已在该...

    Agile Web Development with Rails 4th edition(敏捷Web开发与Rails:程序指南 第四版)

    《敏捷Web开发与Rails:程序指南 第四版》是一本深度探讨使用Ruby on Rails框架进行敏捷Web应用开发的专业书籍。本书旨在帮助开发者充分利用Rails 4的特性,提高开发效率,实现快速迭代和高质量的代码编写。 Rails是...

    Agile Web Development with Rails,Fourth Edition 第四版

    《敏捷Web开发与Rails》第四版是一本专为软件开发者设计的权威指南,全面涵盖了使用Ruby on Rails框架进行敏捷Web应用开发的知识。Rails 3是该版本的重点,它引入了许多新特性和改进,使得开发过程更为高效且灵活。...

    Agile Web Development With Ruby On Rails第一及第二版

    在学习这两本书时,你可以从Pragmatic Programmer - Agile Web Development With Ruby On Rails_05.12.24.pdf和Pragmatic.Bookshelf.Agile.Web.Development.with.Rails.2nd.Edition.pdf中获取详细教程。这些PDF文件...

    Pragmatic - Agile Web Development with Rails

    《Pragmatic - Agile Web Development with Rails》是Ruby on Rails框架的经典教材,旨在引导初学者高效地学习敏捷Web开发。这本书的第三版于2009年发布,它结合了Pragmatic Programmers的实用主义理念与Ruby on ...

    Agile Web Development with Rails, 2nd Edition

    Agile Web Development with Rails, 2nd Edition &lt;br&gt;有两份PDF文件,大小分别是7.39MB和6.55MB &lt;br&gt;作者: Dave Thomas , David Heinemeier Hansson , Leon Breedt , Mike Clark , James Duncan Davidson ,...

    Agile Web Development with Rails for Rails 3.2

    ### Agile Web Development with Rails for Rails 3.2 #### 核心知识点概览 - **Rails 3.2概述** - **敏捷开发方法论** - **Model-View-Controller (MVC) 模式** - **Ruby on Rails基础与高级特性** - **面向对象...

    Agile Web Development with Rails 4th(正式版).pdf

    Agile Web Development with Rails 4th(正式版).pdf

    Agile Web Development With Rails Fourth Edition

    ### Agile Web Development with Rails 第四版 #### 书籍概述与价值 《Agile Web Development with Rails》第四版是一本经典的Rails开发指南,旨在为开发者提供一套全面、实用且高效的敏捷开发方法论。本书由Sam ...

Global site tag (gtag.js) - Google Analytics