对于接受id参数

时间:2015-07-07 17:48:05

标签: ruby-on-rails unit-testing rspec

我正在尝试在我的Rails应用程序中测试ArticlesController。所有不接受参数的路线都在经过。但是所有期望id param的路由都失败了。

故障:

  1) ArticlesController should find article by id
     Failure/Error: get :info, id: @article[:id]
     ActionController::UrlGenerationError:
       No route matches {:action=>"info", :controller=>"articles", :id=>"60"}
     # ./spec/controllers/articles_controller_spec.rb:26:in `block (2 levels) in <top (required)>'

  2) ArticlesController should export folder
     Failure/Error: get :export_folder, id: @article[:id]
     ActionController::UrlGenerationError:
       No route matches {:action=>"export_folder", :controller=>"articles", :id=>"60"}
     # ./spec/controllers/articles_controller_spec.rb:56:in `block (2 levels) in <top (required)>'

  3) ArticlesController should export an article by id
     Failure/Error: get :export, id: @article[:id]
     ActionController::UrlGenerationError:
       No route matches {:action=>"export", :controller=>"articles", :id=>"60"}
     # ./spec/controllers/articles_controller_spec.rb:50:in `block (2 levels) in <top (required)>'

配置/ routes.rb中

get '/articles/list' => 'articles#list', defaults: { format: :html }
  get '/articles/trendlist' => 'articles#trendlist', defaults: { format: :html }
  get '/articles/show/:id' => 'articles#show', defaults: { format: :html }, as: :show_article
  get '/articles/index'
  get '/articles/info/:id' => 'articles#info', as: :article_info
  get '/articles/export/:id' => 'articles#export', as: :export_article
  get '/articles/view/:id' => 'articles#view'
  get '/articles/favorite/:id' => 'articles#favorite'
  get '/articles/trending' => 'articles#trending', defaults: { format: :json }
  get '/articles/deleted' => 'articles#deleted', defaults: { format: :json }
  get '/articles/csv/:id' => 'articles#csv'
  get '/articles/export_folder/:id' => 'articles#export_folder', as: :export_folder

规格/控制器/ articles_controller.rb

require 'spec_helper'

describe ArticlesController do
  before(:all) do
    Article.destroy_all
    Comfy::Cms::Layout.destroy_all
    Comfy::Cms::Site.destroy_all
    site = FactoryGirl.create(:cms_site)
    layout = FactoryGirl.create(:cms_layout, site_id: site[:id])
    @article = FactoryGirl.create(:cms_page, layout_id: layout[:id], site_id: site[:id])
  end

  it 'should index articles' do
    get :index
    expect(response.response_code).to eq(200)
    expect(response.headers).to include( 'Content-Type' => 'application/json; charset=utf-8')
  end

  its 'should list articles' do
    get :list
    expect(response.response_code).to eq(200)
    expect(response.headers).to include( 'Content-Type' => 'text/html; charset=utf-8')
  end

  it 'should find article by id' do
    get :info, id: @article[:id]
    expect(response.response_code).to eq(200)
    expect(response.headers).to include( 'Content-Type' => 'application/json; charset=utf-8')
  end

  it 'should list deleted articles' do
    get :deleted
    expect(response.response_code).to eq(200)
    expect(response.headers).to include( 'Content-Type' => 'application/json; charset=utf-8')
  end

  it 'should list trending articles' do
    get :trending
    expect(response.response_code).to eq(200)
    expect(response.headers).to include( 'Content-Type' => 'application/json; charset=utf-8')
  end

  it 'should update trending articles' do
    get :trendlist
    expect(response.response_code).to eq(200)
    expect(response.headers).to include( 'Content-Type' => 'text/html; charset=utf-8')
  end

  it 'should export an article by id' do
    get :export, id: @article[:id]
    expect(response.response_code).to eq(200)
    expect(response.headers).to include( 'Content-Type' => 'text/csv; charset=utf-8')
  end

  it 'should export folder' do
    get :export_folder, id: @article[:id]
    response.response_code.should eq(200)
    expect(response.headers).to include( 'Content-Type' => 'text/html; charset=utf-8')
  end
end

佣金路线

Prefix Verb   URI Pattern                                                               Controller#Action
                                        tags GET    /tags(.:format)                                                           tags#index
                               articles_list GET    /articles/list(.:format)                                                  articles#list
                          articles_trendlist GET    /articles/trendlist(.:format)                                             articles#trendlist
                                    articles GET    /articles/show/:id(.:format)                                              articles/articles#show
                              articles_index GET    /articles/index(.:format)                                                 articles#index
                                             GET    /articles/info/:id(.:format)                                              articles/articles#info
                                             GET    /articles/export/:id(.:format)                                            articles/articles#export
                                             GET    /articles/view/:id(.:format)                                              articles/articles#view
                                             GET    /articles/favorite/:id(.:format)                                          articles/articles#favorite
                           articles_trending GET    /articles/trending(.:format)                                              articles#trending
                            articles_deleted GET    /articles/deleted(.:format)                                               articles#deleted
                                             GET    /articles/csv/:id(.:format)                                               articles/articles#csv
                                             GET    /articles/export_folder/:id(.:format)                                     articles/articles#export_folder

应用程序/控制器/ articles_controller.rb

class ArticlesController < ApplicationController
  include ArticlesHelper

  before_action :set_default_response_format, except: [:pdf, :show, :list, :trendlist, :export_folder]

  def index
    @articles = SearchArticlesCommand.new(params).execute
  end

  def deleted
    @dlist = Article.deleted.map(&:article_id)
    render :ids, status: :ok
  end

  def info
    id = params[:id].to_i
    @article = Article.published.find_by(id: id)
  end

  def list
    @articles = Article.folder
    render 'articles/list'
  end

  def favorite
    ...
    render json: { result: true, is_liked: "#{is_liked}" }
  end

  def view
    ...
    render json: { result: true }
  end

  def trending
    load_trending_articles
  end

  def trendlist
    load_trending_articles
    render 'articles/trendlist'
  end

  def export
    id = params[:id].to_i
    @article = Article.published.find_by(id: id)

    render pdf: @article.label.gsub(/\s/, '_'),
           template: 'articles/export.pdf.erb',
           dispostion: 'attachment',
           locals: { paragraphs: @article.paragraphs, images: @article.images }

2 个答案:

答案 0 :(得分:2)

这不是namespace的用途。您可以在其上阅读更多内容here。请改用resources并为member

指定id
resources :articles, only: [] do
  collection do 
    get :list
    get :trendlist
    get :trending
    get :deleted
  end

  member do
    get :info
    get :export
    get :view
    get :favorite
    get :csv
    get :export_folder
  end
end

get 'articles/index', to: 'articles#index'
get 'articles/show/:id', to: 'articles#show'

答案 1 :(得分:2)

如果查看rake routes的输出,您可以看到Rails正在寻找articles/articles#show等。namespace用于创建位于名称空间(duh)中的路由,例如{ {1}}根据/admin/tools

您可以使用Admin::ToolsController添加网址前缀但不添加命名空间或scope

resources

我还会质疑为什么你真的需要超出标准CRUD集的那么多路由。 特别是在视图和节目以及列表和索引等语义极其类似的路径。

我会在较小的路由集周围使用查询参数,因为它会减少所有级别的重复数量。

resources :articles, only: [:show, :index] do
  member do
    get 'info'
    get 'export' # Use /articles/1.format instead.
    get 'view' # Do you need this? Code smell!
    get 'favorite' # should be post - GET should never create or alter a resource.
    get 'csv' # remove - use /articles/1.csv instead
    get 'show' # /articles/show/3
  end
  collection do
    get 'trending'
    get 'deleted'
    get 'trendlist'
    get 'list' # Do you need this? Code smell!
    get 'index' # /articles/index
  end
end

Rails还有内置的CSV mime类型,您可以这样做:

/articles?filter=deleted => index /articles?filter=trending

/articles/5.csv

使用class ProductsController < ApplicationController def show @article = Article.order(:name) respond_to do |format| format.html format.csv { render text: @article.to_csv } end end end vs @article[:id]确实有效,但由于rails必须通过@article.id方法才能找到getter方法,因此它非常简单且速度稍慢。在这种情况下,这并不是一件大事,但在处理大量物体时并不是很好。