2017-10-30 13 views
0

を表示ファイルから私は、URLに属性を渡す:テストURLに属性を渡す - RSPEC /アドレス可能な宝石

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

これは私がファイルの値を抽出する必要がhttp://localhost:3030/pieces/%23?file=8&rank=8

のようなURLを提供しますこのURLからランク付けして、データベースフィールド(移動後のチェスの座標)を更新します。

私はアドレス可能な宝石を使用しようとしているコントローラで

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_valuesnilを返します。私は知らないどのようにテストでそのようなものをミラーする

エラーメッセージ:Controller_specで

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 

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 

ロジックは、現時点では(私が作品を持っていないローカルホストブラウザから作品のオブジェクトかどうかは確認することができないので、私はエラーに遭遇する)。それにも取り組んでいます。

私の質問はテストに関するものです。しかし、URLからさまざまな方法で属性を抽出する提案がある場合、私はすべての耳です!

+0

あなたは@current_piece」「あなたはリテラル文字列を '渡すと、@のcurrent_piece''」'周りの引用符を削除する必要があります' - インスタンス変数の値ではありません。 – max

+0

いいキャッチ!実際に私は実際のビューファイルに引用符をつけていませんが、これを間違ったものから貼り付けています(これをプレースホルダとして使用して、オブジェクトを持たないためルーティングエラーをなくします)。 –

+0

私の質問を修正しました。 this –

答えて

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 
0

あなたの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があることを確認する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、あなたはおそらくPATCH/PUT要求にのparamsを渡すURL文字列を使用しないでください。あなたはフォームや何かを介してそれらを渡すことを検討するかもしれません。

+0

これは、より単純な 'piece_params'定義でこれを行うことができるはずであることを知っていただきありがとうございます。私はそれらのパラメータをURLとは異なる方法で渡すことができることを確認しました。私がセキュリティに取り組んでいるプロジェクトの目的は問題ではありませんが、確かにそれについて知る価値があります! –

1

Railsでクエリのパラメータを取得するためにリクエストURIを手動で解析する必要はありません。

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あなたがGET以外の方法でリクエストを送信する<a>要素を使用できるようにするjQueryのUJSを使用しています。これは、フォームを作成し、それをHREF属性のURIに送信するjavascriptハンドラをアタッチすることで行います。あなたがしたい場合

{ 
    file: 1, 
    rank: 2 
} 

ない

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

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

はのparams以下のハッシュを与える:しかしparamsをネストされていないレールで "正規形" とは異なり

ネストされたキーを使用すると、パラメータを次のように指定する必要があります。

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

また、 'button_to'を使って、リンクではなく離散的なフォーム要素を作成することもできます。これにより、クエリ文字列の代わりにリクエスト本体にパラメータを渡すことができます。 – max

+0

これは、私がリクエストボディの仕組みを理解するのに役立ちました。最後に 'button_to'が私のために働くので、私は今解決策を投稿します。 –