0

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

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

这给出了类似的网址http://localhost:3030/pieces/%23?file=8&rank=8

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

在控制器中,我正在尝试使用 Addressable 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我得到:url 后面没有属性#<Addressable::URI:0x3fa7f21cc01c URI:http://test.host/pieces/2> 散列。从而返回。我不知道如何在测试中反映这样的事情uri.query_valuesnil

错误信息:

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

我无法从 localhost 浏览器检查逻辑是否有效(我目前没有碎片对象,所以我遇到了错误)。也在为此努力。

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

4

3 回答 3

1

您无需手动解析请求 URI 即可在 Rails 中获取查询参数。

Rails 构建在 Rack CGI 接口之上,该接口解析请求 URI 和请求正文,并提供参数作为 params 哈希。

例如,如果您有:

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 中的“正常形式”不同,params 不是嵌套的:

<%= 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 %>
于 2017-10-30T14:51:19.617 回答
0

如果您的网址是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请求。您可能会考虑通过表格或其他方式传递它们。

于 2017-10-30T14:09:40.527 回答
0

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
于 2017-11-01T10:46:43.550 回答