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

时间:2017-10-30 13:17:05

标签: ruby-on-rails rspec addressable-gem

从View文件中我传递了url中的属性:

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

这会提供http://localhost:3030/pieces/%23?file=8&rank=8

等网址

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

在Controller I中尝试使用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时,我得到:#<Addressable::URI:0x3fa7f21cc01c URI:http://test.host/pieces/2> 没有跟踪网址的属性哈希。因此uri.query_values会返回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

我无法检查逻辑是否可以从localhost浏览器中运行(我此刻没有碎片对象,所以我遇到了错误)。还在努力。

我的问题是考试;但是,如果有建议以不同的方式从网址中提取属性我全都耳朵!

3 个答案:

答案 0 :(得分: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之外的其他方法发送请求。它通过附加一个创建表单的javascript处理程序并将其发送到HREF属性中的URI来实现。

然而,不像&#34;正常形式&#34;在rails中,params不是嵌套的:

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

将给出以下参数哈希:

{
  file: 1,
  rank: 2
}

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

如果你想要嵌套键,你必须提供params:

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

答案 1 :(得分:0)

如果您的网址为export function catcher<S, P, T extends new (... args:any[]) => React.Component<S, P>>(constructor:T) { class HOC extends constructor { } return HOC; } ,您应该可以:

http://localhost:3030/pieces/%23?file=8&rank=8

然后通过def piece_params params.require(:piece).permit(:rank, :file) end params[:rank]在您的操作中访问它们 在尝试分配值之前,我通常使用params[:file]来确保params在那里。这样的事情应该有效:

params[:file].present?

FWIW,您可能不应该使用URL字符串将params传递给p = {} if params[:rank].present? p[:rank] = params[:rank] end if params[:file].present? p[:file] = params[:file] end current_piece.update_attributes(p) 请求。您可以考虑通过表单或其他方式传递它们。

答案 2 :(得分: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