ruby-on-railsrspecaddressable-gem

Passing attributes in test url - Rspec / Addressable gem


From a View file I pass attributes in a url:

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

this gives urls like http://localhost:3030/pieces/%23?file=8&rank=8

I need to extract the value of file and rank from this url, to update the database fields (coordinates of a chess piece after a move).

In Controller I'm trying to use the 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

When I inspect uri I get: #<Addressable::URI:0x3fa7f21cc01c URI:http://test.host/pieces/2> There is no hash of attributes trailing the url. Thus uri.query_values returns nil. I don't know how to mirror such thing in the test.

The error message:

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

In 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

I can't check if the logic works from the localhost browser (I don't have pieces objects at the moment so I run into errors). Also working on that.

My question regards the test; however if there are suggestions to extract the attributes from the url in different ways I'm all ears!


Solution

  • button_to with nested attributes works; in the view file:

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

    And keep it simple in the controller:

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