在测试中传递属性 url - Rspec / Addressable gem

Passing attributes in test url - Rspec / Addressable gem

我从视图文件中传递属性 url:

%= link_to piece_path(@current_piece, file: file, rank: rank), method: :patch do %>

这给出 url 就像 http://localhost:3030/pieces/%23?file=8&rank=8

我需要从这个 url 中提取文件的值和排名,以更新数据库字段(走棋后的棋子坐标)。

在控制器中,我正在尝试使用可寻址 gem:

def update
    (some code)
    current_piece.update_attributes(piece_params)
    (more code)
end

private

def piece_params
    uri = Addressable::URI.parse(request.original_url)
    file = uri.query_values.first    ## I don't know if "first" 
    rank = uri.query_values.last     ## and "last" methods will work
    params.require(:piece).permit({:file => file, :rank => rank})
end

当我检查 uri 时,我得到:#<Addressable::URI:0x3fa7f21cc01c URI:http://test.host/pieces/2> url 后面没有属性散列。因此 uri.query_values returns nil。我不知道如何在测试中镜像这样的东西

错误信息:

1) PiecesController pieces#update should update the file and rank of the chess piece when moved
     Failure/Error: file = uri.query_values.first

     NoMethodError:
       undefined method `first' for nil:NilClass

在Controller_spec中:

describe "pieces#update" do
    it "should update the file and rank of the chess piece when moved" do
      piece = FactoryGirl.create(:piece)
      sign_in piece.user
      patch :update, params: { id: piece.id, piece: { file: 3, rank: 3}}
      piece.reload
      expect(piece.file).to eq 3
      expect(piece.rank).to eq 3
   end

我无法从本地主机浏览器检查逻辑是否有效(我目前没有 pieces 对象,所以我 运行 出错了)。也在努力。

我的问题是关于考试的;但是,如果有建议以不同的方式从 url 中提取属性,我会洗耳恭听!

如果您的URL是http://localhost:3030/pieces/%23?file=8&rank=8,您应该能够做到:

def piece_params
    params.require(:piece).permit(:rank, :file)
end

然后通过 params[:rank]params[:file] 在您的操作中访问它们 在尝试分配值之前,我通常使用 params[:file].present? 来确保参数在那里。这样的事情应该有效:

p = {}
if params[:rank].present?
  p[:rank] = params[:rank]
end
if params[:file].present?
  p[:file] = params[:file]
end
current_piece.update_attributes(p)

FWIW,您可能不应该使用 URL 字符串将参数传递给 PATCH/PUT 请求。您可以考虑通过表格或其他方式传递它们。

您不需要手动解析请求 URI 来获取 Rails 中的查询参数。

Rails 建立在 Rack CGI 接口之上,它解析请求 URI 和请求主体,并提供参数作为参数哈希。

例如,如果您有:

resources :things

class ThingsController < ApplicationController
  def index
    puts params.inspect
  end
end

请求/things?foo=1&bar=2会输出如下内容:

{
  foo: 1,
  bar: 2,
  action: "index",
  controller: "things"
}

link_to method: :patch 使用 JQuery UJS 让您使用 <a> 元素通过 GET 以外的其他方法发送请求。它通过附加一个创建表单并将其发送到 HREF 属性中的 URI 的 javascript 处理程序来实现。

但是与 rails 中的 "normal forms" 不同,参数没有嵌套:

<%= link_to piece_path(@current_piece, file: file, rank: rank), method: :patch do %>

将给出以下参数散列:

{
  file: 1,
  rank: 2
}

没有

{
  piece: {
    file: 1,
    rank: 2
  } 
}

如果你想要嵌套的键,你必须提供如下参数:

<%= link_to piece_path(@current_piece, "piece[file]" => file, "piece[rank]" => rank), method: :patch do %>

button_to 嵌套属性有效;在视图文件中:

<%= button_to piece_path(@current_piece), method: :patch, params: {piece: {file: file, rank: rank}} do %>

并在控制器中保持简单:

def piece_params
  params.require(:piece).permit(:rank, :file)
end