Search code examples
ruby-on-rails-3activerecordrestful-architecture

Datatype not being passed in correctly for Rails 3.1 web service


I have a Rails RESTful web service application that accepts a value from a client to increment the value in the database. The database value is an integer, but when using rspec to test the code, the value being passed in is interpreted as a string.

I'm using Rails 3.1 and Ruby 1.9.2.

Here's the rspec snippet:

...
it "should find Points and return object" do
  put :update, :username => "tester", :newpoints => [10, 15, 0], :format => :xml
end
...

Here's the controller code:

...
respond_to do |format|
  if points.update_attributes([xp + :newpoints[0]][sp + :newpoints[1]][cash +        :newpoints[2]])
    format.json { head :ok }
    format.xml { head :ok }
...

xp, sp and cash are values from the database and have been validated as Fixnum datatype. The error I am getting is:

TypeError: String can't be coerced into Fixnum

How do I write my test to ensure that the parameters being passed are passed as the proper datatype?

I can include more of the code if needed. Thanks in advance!


Solution

  • It took me a bit of head banging, but I found out that I was passing everything in wrong. The solution I've come up with is definitely not the best solution and could probably be re-written, but it works and for now, that's sufficient.

    The change to the rspec snippet was to create hash represented by symbol :newpoints

    it "should find Points and return object" do
      put :update, :username => "tester", :newpoints => {"experience_points" => 10, "shame_points" => 15, "gold" => 0}, :format => :xml
    end
    

    The handling of this request in the controller required a bit of tweaking, but here's the pertinent pieces:

    class PointsController < ApplicationController
      #before_filter :authenticate, :only => :update
      before_filter :must_specify_user
      before_filter :fix_params
      before_filter :clean_up
      respond_to :html, :xml, :json
    
      def fix_params
        if params[:points]
          params[:points][:user_id] = @user.id if @user
        end
      end
    
     def clean_up
       @newpoints = params[:newpoints]
       @experience = @newpoints["experience_points"]
       @shame = @newpoints["shame_points"]
       @gold = @newpoints["gold"]
       @xp = @experience.to_i
       @sp = @shame.to_i
       @cash = @gold.to_i
    end
    
    def update
      points = Points.find_by_user_id(@user.id, params[:id])
      xp = points.experience_points
      sp = points.shame_points
      cash = points.gold
      final_experience = xp += @xp
      final_shame = sp += @sp
      final_gold = cash += @cash
      final_points = {:experience_points => final_experience, :shame_points => final_shame, :gold => final_gold}
      if_found points do
        respond_to do |format|
          if points.update_attributes!(params[final_points])
            format.json { head :ok }
            format.xml { head :ok }
          else
            format.json { render :nothing => true, :status => "401 Not Authorized"}
            format.xml { render :nothing => true, :status => "401 Not Authorized"}
          end
        end
      end
    end
    end
    

    Obviously, much can be done to make this follow DRY and what not, so any suggestions are still welcome. Thanks in advance!