arrow_backward Back to blog

Angular with Rails, Part III

 

angular-ruby-on-rails-logo
In Part 2 of Angular with Rails series, we covered creating a Rails API with tests in RSpec and setting up an AngularJS app that reads from the API.

In Part 3 we will cover:

  • Adding CSS
  • Adding editing functionality
  • Creating a custom filter
  • Setting up JavaScript tests

Setup Bootstrap Sass

In order to support editing functionality we’ll add some CSS to the UI. Following the README at bootstrap-sass, we’ll add to our Gemfile:

Add to our app/assets/javascripts/application.js:

Rename app/assets/stylesheets/application.css to application.css.sass (if you prefer sass over scss) and add:

Then we’ll add some classes to our employee index in app/views/employees/index.html.erb:

Add the Edit API

Next, we’ll update our Rails API to support editing of employee records. Let’s start by adding some tests for the update method in spec/controllers/api/employees_controller_spec.rb:

At this point, these tests will fail. We need to create an update method in our API controller, but first we must specify what params are allowed on update (Rails’ strong parameters) at app/controllers/api/employees_controller.rb:

Now, our update action is simple. The code will try to update the employee object and render the errors if there’s a problem.

Next run the tests to make sure they pass. For a more complex application there would be more tests, but in our example these will suffice.

Add the Edit Front End

For our employee edit functionality we’ll define a modal dialog containing a form and a submit button. The Angular-bootstrap package contains a modal dialog tool. We’ll add the angular-bootstrap package to our bower.json:

And bundle exec rake bower:install

Next, require angular-bootstrap in app/assets/javascripts/application.js:

Finally, we’ll add it as a dependency to our angular app in app/assets/javascripts/angular-app/modules/employee.js.coffee.erb:

Now, we need to add a modal controller to our AngularJS app. This controller will handle popping up a modal editable form and submitting it to our Rails API. In app/assets/javascripts/angular-app/controllers/employee/EmployeeListCtrl.js.coffee:

Next, we’ll create the modal controller at app/assets/javascripts/angular-app/controllers/employee/EmployeeEditModalCtrl.js.coffee:

In the above code we’re defining a modal controller that receives the employee object we passed in the prior controller, along with function stubs for the save / cancel buttons in the dialog. Next, we need to define the edit form template in app/assets/javascripts/angular-app/templates/employee/edit.html.erb:

Finally, if you run the code now you’ll get an error loading the template. We need to tell our angular-rails-templates gem what the base path for our templates is. This is necessary because we are using the rails asset pipeline to combine our javascript files. In config/application.rb:

Next, we can return to our employees index and provide an ng-click attribute to launch the edit form. We’ll add this link on the employee name cell in the table in app/views/employees/index.html.erb:

Now, clicking an employee’s name will launch a modal form with fields containing that employee’s data. However, we still need to hook up the Save Changes button to our Rails API. In app/assets/javascripts/angular-app/controllers/employee/EmployeeEditModalCtrl.js.coffee:

We can simply say put() above because we are using Restangular to manage that object.

One problem with the above code is that while the server is applying validation to the object, the client side AngularJS portion is not. One downside of using client-side MVC is the fact that validation from the server must often be duplicated on the client. The subject of AngularJS form validation could be a blog post on its own. I’ll leave that as an exercise for the reader.

Secure the UI

Though the editing functionality now works, notice the page still shows each employee’s social security number. In order to mask the SSN and only reveal it in edit form, we can create an AngularJS filter. In app/assets/javascripts/angular-app/filters/employee/empMaskNumber.js.coffee

It’s recommended that you name filters with an app prefix to avoid colliding with AngularJS’s built-in filters. Let’s edit our employee table to make use of the filter in app/views/employees/index.html.erb:

Viewing the employee table again you should see the SSN field being masked with asterisks except the last 4 digits. While this filter is simple and apparently works, when building more complex filters we will need javascript tests.

Setup JavaScript Tests

Next, we’ll setup jasmine-rails. Add jasmine-rails to the Gemfile:

And add angular-mocks to the bower.json:

Then run:

Next, we need to setup our spec_helper. In app/assets/javascripts/spec_helper.coffee:

Note the beforeEach line above. As your application grows and more angular apps are added, they must also be added here to be available for testing. The above spec helper also requires SinonJS. Download the file and place it at vendor/assets/javascripts/sinon.js .

Now you should be able to run an empty test suite:

Which should return 0 specs and 0 failures. We are now ready to write our test for our filter defined above. In spec/javascripts/filters/emp_mask_number_spec.js.coffee:

In a real application expect to have more specs than just the above. At this point though, you have everything you need to continue building your application and expanding. You can find the code for this example on Github.

Need to catch up on the Angular with Rails series? Check these out:

Resources:

arrow_backBack

New Project Request