在测试中传递属性 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
我从视图文件中传递属性 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