Search code examples
ruby-on-railsember.jsember-cligrape-api

How to update records (PUT) in ember


I have tried everything I can to get my ember app to update my rails api with zero success. My current code looks like: edit route

import Ember from 'ember';

export default Ember.Route.extend({ 

  actions: {
        submit: function(){
          var model = this.controller.get('model');
          model.save();
          this.transitionTo('movies.show', model);
     }
   }
});

edit.hbs

<form>
  <div class="form-group col-sm-4">
    <label for="title" class="col-sm-2 control-label">Title</label>
    <div class="col-sm-10">
        {{input value=title id=title class="movie-title"}}
    </div>
  </div>

  <div class="form-group col-sm-4">
    <label class="col-sm-2 control-label" for="director">Director</label>
    <div class="col-sm-10">
        {{input value=director id="director" class="movie-director"}}
    </div>
  </div>

  <div class="form-group col-sm-4">
    <label class="col-sm-2" for="rating">Rating</label>
    <div class="col-sm-10">
        {{input value=rating id="rating" class="movie-rating"}}
    </div>
  </div>
  <button type="submit" class="btn btn-primary btn-block commit-movie-change" {{action 'submit'}}>Add</button>
</form>

router.js

import Ember from 'ember';
import config from './config/environment';

var Router = Ember.Router.extend({
  location: config.locationType
});

Router.map(function() {
  this.resource('movies', function(){
    this.route('show', {path: ':movie_id'});
    this.route('edit', {path: ':movie_id/edit'});
    this.route('create', {path: 'create'});
  });
});

export default Router;

my model looks like

import DS from 'ember-data';

export default DS.Model.extend({
  title: DS.attr('string'),
  director: DS.attr('string'),
  rating: DS.attr('string')
});

This actually works to update locally and start a PUT to the server but it does not send any of the properties/ params to the api. and when i look at the server log it shows

Started PUT "/api/v1/movies/10" for 127.0.0.1 at 2015-01-16 01:00:50 -0500
Movie Load (0.7ms)  SELECT  "movies".* FROM "movies"  WHERE "movies"."id" = 10 LIMIT 1
 (0.4ms)  BEGIN
 (0.6ms)  COMMIT

I am at a loss with this. I have tried to write updateRecord() method within the route but that does not seem to work. Any help would be hugely appreciated. If you need to see any other code let me know.


Solution

  • Your back-end is incorrectly parsing the parameters to update the model. In rails/app/controllers/api/v1/movies.rb, you have this for a PUT:

    Movie.find_by_id(params[:id]).update_attributes(declared(params[:movie], {include_missing: false}))
    

    When I ran both your Ember and Rails applications, I saw that Ember was properly sending attributes to the API, so I added a binding.pry in your put code to look more closely. There I found that the call to declared was filtering out all the attributes. If you change it to this instead, it works:

    Movie.find_by_id(params[:id]).update_attributes(declared(params, {include_missing: false})[:movie])
    

    I’ve never used Grape so I don’t know if this is idiomatic, but it works.

    Incidentally, you can just use Movie.find(params[:id]); find_by_id is unnecessarily verbose.