Question

I'm using Backbone.js to create a pure JS front-end for my rails app using a JSON api.

The backbone.js model URL looks like this:

window.MedicationCollection = Backbone.Collection.extend({
  model: Medication,
    url: 'http://localhost:3000/medication_options'
});

CRUD works fine with this. It's sending requests to my server with an "application/JSON" content type.

But I needed to add authentication for the API and my rails app is using Authlogic so I added this:

  before_filter :require_user

     def require_http_auth_user
        return true if current_user
        authenticate_or_request_with_http_basic do |email, password|
          email = email.gsub("_at_", "@") if email.include?("_at_")
          if @current_user = User.find_by_email(email)
            @current_user.valid_password?(password)
          else
            false
          end
        end
      end

And a typical CRUD method in rails looks like this:

  def update
    @medication_option = MedicationOption.find(params[:id])
    if @medication_option.update_attributes(params[:medication_option])
      flash[:notice] = "Successfully updated medication."
    end
    respond_with @medication_option
  end

So in my Backbone.js model I added "username:password" to the url:

window.MedicationCollection = Backbone.Collection.extend({
  model: Medication,
    url: 'http://username:password@localhost:3000/medication_options'
});

The authentication works fine with the appropriate credentials, but for some reason all of the Backbone.js requests are interpreted by the Rails server as HTML instead of JSON.

For some reason during an Basic HTTP authentication, the JSON header gets lost in the mix.

So if I explicitly add ".json" to the end of the URL like this:

window.MedicationCollection = Backbone.Collection.extend({
  model: Medication,
    url: 'http://username:password@localhost:3000/medication_options.json'
});

I can get basic GET requests to work.

But when I do CRUD it doesn't work because it appends the ID to the end of the URL, so it errors:

ActionController::RoutingError (No route matches "/medication_options.json/41516")

So I'm not sure where to go from here.

Was it helpful?

Solution

Your .json should always be at the end of the url to be interpreted as json:

/medication_options/41516.json

You can edit the Model url as well as the collection URL if needed to put the json at the right place.

The root problem is why it doesn't get processed as json in the first place. If you are using rails 3 do you have:

respond_to :js 

or

respond_to :json

to match your respond_with and make sure your controller accepts this kind of format (otherwise rails would return 406 error by default)?

OTHER TIPS

I've never used Document.js, but in looking through the docs it seems you can override url and return the result of a function instead of giving it a literal string value. Could you add the .json to the end of the url string that way?

Try something like this:

 _.extend(Medication, 
    {extension:'.json',
     url:function() {
          var base = getUrl(this.collection);
          if (this.isNew()) return base + this.extension;
          return (base + (base.charAt(base.length - 1) == '/' ? '' : '/')
                  + this.id + this.extension);
        }
    });
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top