有意练习--Rails RESTful(一)
书要反复提及《哪里有天才》在说,大多数所谓的天才是通过反复刻意练习获得。
当你的练习时间达到10000几个小时后,。你将成为该领域的专家。
近期在学习rails怎样实现RESTful Web Service。
自己想给自己设计一个练习的模板,进行重复练习。
开发过程採用的是TDD的方式进行开发。
练习背景:
我们涉及三个Domain对象,Products、Orders、Payment
1.新建projectrails-rest-practice
rails new rails-rest-practice
cd !$
bundle install
2.安装rspec-rails
在Gemfile中加入
gem "rspec-rails", :group => [:development, :test]
然后
bundle install
rails g rspec:install
在.rspec 中去掉 --warnings
3.GET /products => user get list of products
step 1:创建controller,返回HTTP Status 200
user products api例如以下:
GET /products user get list of products
创建文件:spec/products/products_controller_spec.rb
require 'rails_helper'
describe ProductsController, :type => :controller do
describe 'products controller' do
it 'get index of products' do
get :index
expect(response).to have_http_status(200)
end
end
end
have_http_status:http://rubydoc.info/gems/rspec-rails/RSpec/Rails/Matchers#have_http_status-instance_method
创建文件:app/controllers/products_controller.rb
class ProductsController < ApplicationController
def index
end
end
执行rake spec。得到错误:
ActionController::UrlGenerationError:
No route matches {:action=>"index", :controller=>"products"}
配置相关config/routes.rb
resources :products do
collection do
get :index
end
end
执行rake spec,得到错误:
Failure/Error: get :index
ActionView::MissingTemplate:
改动app/controllers/products_controller.rb
class ProductsController < ApplicationController
def index
render :nothing => true
end
end
这样就完毕我们的第一个步骤。尽管看似这个步骤什么都没測,事实上不然,在这一步中。我们搭建好了routes。同一时候创建了必要的controller类和其相应的方法。
step 2:返回JSON
安装rabl
在Gemfile中加入rabl
gem 'rabl'
bundle install
改动測试:spec/products/products_controller_spec.rb
render_views
describe 'products controller' do
before(:all) do
@products = [
Product.new({:id => 1, :name => 'apple juice', :description => 'good'}),
Product.new({:id => 2, :name => 'banana juice', :description => 'just so so'})
]
end
it 'get index of products' do
expect(Product).to receive(:all).and_return(@products).once
get :index, {:format => :json}
expect(response).to have_http_status(200)
products_json = JSON.parse(response.body)
expect(products_json.size).to eq(2)
end
end
执行測试rake spec
得到错误:
NameError:
uninitialized constant Product
创建model Product:
rails g model Product name:string description:text
rake db:migrate
执行測试rake spec
得到错误:
Failure/Error: products_json = JSON.parse(response.body)
JSON::ParserError:
A JSON text must at least contain two octets!
这是由于我们的response不正确,而且我们没有配置怎么获取json格式的输出。
创建文件: app/views/products/index.json.rabl
collection @products, :object_root => false
attributes :name
再次执行測试rake spec,測试通过
step3: 加入很多其它的字段
在 spec/products/products_controller_spec.rb中
products_json = JSON.parse(response.body)
expect(products_json.size).to eq(2)
expect(products_json[0]['id']).to eq(1)
expect(products_json[1]['id']).to eq(2)
expect(products_json[0]['name']).to eq('apple juice')
expect(products_json[1]['name']).to eq('banana juice')
expect(products_json[0]['description']).to eq('good')
expect(products_json[1]['description']).to eq('just so so')
expect(products_json[0]['uri']).to end_with('/products/1')
expect(products_json[1]['uri']).to end_with('/products/2')
在app/views/products/index.json.rabl中
collection @products, :object_root=>false
attributes :id, :name, :description
node :uri do |product|
product_url product
end
4.GET /products => user get a product of specified id
step 1: 创建相应的controller方法。返回HTTP 200
加入測试:spec/products/products_controller_spec.rb
it 'get product by product id' do
get :show, {:id => 1}
expect(response).to have_http_status(200)
end
相应改动:app/controllers/products_controller.rb
def show
render :nothing => true
end
相应改动:config/routes.rb
resources :products do
collection do
get :index
end
member do
get :show
end
end
rake spec測试通过
step 2:创建相应的JSON显示
加入測试:spec/products/products_controller_spec.rb
before(:all) do
#... ...
@product = Product.new({:id => 1, :name => 'apple juice', :description => 'good'})
end
it 'get product by product id' do
expect(Product).to receive(:find).with(1).and_return(@product).once
get :show, {:id => 1, :format => :json}
expect(response).to have_http_status(200)
product_json = JSON.parse(response.body)
expect(product_json['id']).to eq(1)
expect(product_json['name']).to eq('apple juice')
expect(product_json['description']).to eq('good')
expect(product_json['uri']).to end_with('/products/1')
end
相应改动:app/controllers/products_controller.rb
def show
@product = Product.find(params[:id].to_i)
end
Q:params[:id].to_i,为什么这里从測试代码过来的params[:id]它使一个string类型呢
加入JSON显示:app/views/products/show.json.rabl
object false
node(:id) { |product| @product.id }
node(:name) { |product| @product.name }
node(:description) { |product| @product.description }
node(:uri) { |product| product_url @product }
执行測试,通过
step 3:重构rabl
改动app/views/products/show.json.rabl
object @product
attributes :id, :name, :description
node(:uri) { |product| product_url product }
改动app/views/products/index.json.rabl
collection @products
extends 'products/show'
配置rabl:创建文件config/initializers/rabl_config.rb
Rabl.configure do |config|
config.include_json_root = false
end
执行測试,通过,这样降低了rabl间的反复代码
step 4:HTTP 404
加入測试:spec/products/products_controller_spec.rb
it 'get 404 when product not found' do
expect(Product).to receive(:find).with(100).and_raise(ActiveRecord::RecordNotFound)
get :show, {:id => 100, :format => :json}
expect(response).to have_http_status(404)
end
相应改动:
class ProductsController < ApplicationController
rescue_from ActiveRecord::RecordNotFound, with: :product_not_found
#... ...
def show
@product = Product.find(params[:id])
end
protected
def product_not_found
response.status = :not_found
end
end
(更新中,欢迎不吝赐教)
将会要改动的部分是怎样笔试rspec,参考:http://betterspecs.org/
版权声明:本文博主原创文章,博客,未经同意不得转载。
有意练习--Rails RESTful(一)的更多相关文章
- 从0使用Ruby on Rails打造企业级RESTful API项目实战之我的云音乐
本节对我们项目实现的功能和知识点做一个简单的介绍,因为是RESTful API项目,所以对于后端来说基本上没有什么UI界面可展示,那我们就在关键的点,使用客户端(Android)实现的效果图. 课程简 ...
- Rails ---> routes.rb 详解
理解路由的目的 看懂routes.rb文件中的代码 使用经典的hash风格或者现在比较流行的Restful风格构造你自己的路径 断定一个路径会映射到哪一个controller和action 路由的双重 ...
- Rails : 产品环境(生产环境)的部署
bundle install rails server (默认为开发环境) rails server -p80 -e production (指定为生产环境 ,并自定义指定站点端口) rake RAI ...
- RESTFUL接口
原文地址:http://kb.cnblogs.com/page/512047/ 1. 什么是REST REST全称是Representational State Transfer,中文意思是表述(编者 ...
- Building a RESTful Web Service Using Spring Boot In Eclipse
一.构建restful web service 创建Maven的java web工程,maven的pom文件加入依赖包 创建包hello Greeting.java package hello; pu ...
- RESTful架构详解(转)
1. 什么是REST REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移. 它首次出现在2000年Roy Fielding的 ...
- 虚拟研讨会:如何设计好的RESTful API?
http://www.infoq.com/cn/articles/how-to-design-a-good-restful-api/ REST架构风格最初由Roy T. Fielding(HTTP/1 ...
- 使用 Struts 2 开发 RESTful 服务
REST 简介 REST 是英文 Representational State Transfer 的缩写,这个术语由 Roy Thomas Fielding 博士在他的论文<Architectu ...
- 【转】REST on Rails指南
REST on Rails指南1:理解资源 这是来自http://www.softiesonrails.com的REST简明指南. PART I 在理解REST on Rails之前,有必要先思考一下 ...
随机推荐
- 測试JSON RPC远程调用(JSONclient)
#include <string> #include <iostream> #include <curl/curl.h> /* 标题:JSonclient Auth ...
- Windows phone 8 学习笔记(8) 定位地图导航
原文:Windows phone 8 学习笔记(8) 定位地图导航 Windows phone 8 已经不使用自家的bing地图,新地图控件可以指定制图模式.视图等.bing地图的定位误差比较大,在模 ...
- 为VS2013添加SQLCE的支持
解决 下载SQL Server Compact Toolbox by ErikEJ并安装 打开VS2013,新建一工程,在“视图>其它窗口>SQL Server Compact Toolb ...
- Just like normal variables,
Just like normal variables, pointers can be declared constant. There are two different ways that poi ...
- leetCode Min Stack解决共享
原标题:https://oj.leetcode.com/problems/min-stack/ Design a stack that supports push, pop, top, and ret ...
- C语言中main函数的參数具体解释
main函数的定义形式 main函数能够不带參数,也能够带參数,这个參数能够觉得是 main函数的形式參数.C语言规定main函数的參数仅仅能有两个,习惯上这两个參数写为argc和ar ...
- 使用require.js和backbone实现简单单页应用实践
前言 最近的任务是重做公司的触屏版,于是再园子里各种逛,想找个合适的框架做成Web App.看到了叶大(http://www.cnblogs.com/yexiaochai/)对backbone的描述和 ...
- bootstrap的popover在trigger设置为hover时不隐藏popover
使用bootstrap的popover,trigger设置为hover时,可以实现当鼠标放置到目标元素上时显示popover,可是无法实现当鼠标移动到popover上时不隐藏popover,在网上找了 ...
- jQuery来源学习笔记:扩展的实用功能
// 扩展的实用功能 jQuery.extend({ // http://www.w3school.com.cn/jquery/core_noconflict.asp // 释放$的 jQuery 控 ...
- AccountManager教程
API阅读 此类提供所述用户接口到集中登记帐户. 用户只需输入一次帐号password后,您将能够访问internet资源. 不同的在线服务用不同的方式来管理用户,所以account manager ...