How well does AngularJS works with ROR

angular ror

The main purpose of integrating Angular.js and ROR is making sure that everything fits together well in your app. Building an API along with you application is also much easier to meet when combining both framework. Rails comes with cross-site request forgery protection in the form of a token embedded in the head section of each page to make forms work with AngularJS you need to use that token in all API request.

AngularJS can be used to make a web app respond faster, in the sense that in response to a user interaction something happens on the web page without reloading and rendering the whole page. Also helps to build a rich client side app where you write a lot of JavaScript code that runs on client machine which is interactive to the user. It communicate with the server-side backend that is Rails app. AngularJs provides ROR web app with a no of nice client-side features such as, two-way data binding, form validations, easy to use UI widgets, etc. But, we chose to use Rails for routing the entire site. Therefore, the angular app is embedded within rendered rails view.

Few things those are helpful to building AngularJS on Rails apps:

Skinny controllers in Angular

–> In the Rails world, “Fat models, skinny controllers” has been some of the most often quoted design advice for many years. In angular.js, this also turns out to be solid advice. Getting logic out of your controllers makes it easier to reuse and also helps improve the design of your codebase e.g. Single Responsibility Principle. Here are a couple of the ways to put your angular.js controllers on a diet.

Services

–> The most common way you’ll run across to move code out of your controller is to move into a service created by a factory and then inject it where you need it. Moving this controller method out into a service is really easy. We just define a service and then let angular inject it into our service.

–> This is a great way to share code between multiple controllers or anything else in your app. Angular services are singletons, it’s worth pointing out, so not the best place to put logic that’s belongs to something you want multiple instances of.

Angular models as Coffeescript classes

–> In a client side framework the model layer doesn’t tend to end up with as much code as server side models do. There are certain concerns such as, authorization, certain kinds of validation that are always going to need to happen on the server side. But that doesn’t mean that your models have to be totally anemic either. There are definitely cases where defining functions on your models is totally the right place for code to live.

–> In Angular, to have our models easily persist to our RESTful Rails backend, we really like a gem called angular-rails-resource. It’s got some nice improvements over ng-resource when integrating with Rails. Like ng-resource, you define your models as Angular factories.

–> The end result of all this is “class” you can use to create new instances. However, it wasn’t at all obvious to us initially where to put methods. It turns out to be easier than we thought. We can make a Coffeescript class that extends from the class function that rails resource factory creates. Since we then have a plain ole Coffeescript class, we can add methods to it just like any other class. Our factory just returns the Coffeescript class.

Putting your templates on the asset pipeline

–> When you first start out with angular, you may not need to put templates in separate files at all. But as soon as you start using the router or building custom directives you’ll end up needing them. The canonical way to load templates is to use the template url attribute. This works fine, and you can put html files in your rails app in assets or templates and rails will serve them up no problem.

–> It’s worth pointing out that you can write your templates in haml as well, but you need do just a little extra work to make this happen. This lets you write your template in haml, you’ll need to name it foo.html.haml in this case. This works fine, but there’s another undocumented way you can give templates to angular, you can use let the asset pipeline precompiled templates using a client side template library and put them on the global JST variable.

–> It may seem like a strange thing to do, but it solved a specific problem that didn’t seem to have an immediately obvious solution: loading directive templates in our unit tests. You can use haml to write your views in rails to do client side views. So it works pretty well to move your templates underneath app/assets/javascripts and rename them to *.jst.hamlc.

To deform or not to deform (This only works for Rails 4 apps.)

–> There are two different syntaxes for telling angular what dependencies you need injected. In order to be consistently inconsistent, we can use both. One is to define an array where the first arguments are the names of the dependencies and the last is the function. The other, more concise syntax is to define your function with parameter names that map to services or factories and tell angular essentially, “figure it out for me wouldya.”

–> But this breaks down if you use a javascript minifier that mangles or renames your variables. This is the default for Rails in production environments, but it’s easy to turn off. And voila, at the cost of a few more characters in your minified javascript, you can use the more concise syntax.

AngularJs allows you to access rails params and instance variables within their own Angular control code this question is solved by bellow four approaches:

Parse the URL via $location:

Angular controller can be injected with the $location service. From there, it is possible to simply parse the current URL to get the id of the resource

Hidden divs containing HTML5 custom data attributes:

In this technique, you can create a div that contains the custom attributes within your ng-controller scope. And controller calls getElementByID() and getAttribute() to set the $scope variables but, this approach doesn’t take any particular angular feature.

Use ng-init to evaluate an initialization method:

You can define initialization method using ng-init in the same element as our controller.

Use an Angular service to provide the data and inject it:

Taking advantage of an Angular service defined within your app allows to selectively inject it into the controllers that need it. The angular controllers can then be injected with the service to get the Rails data. Angular also supports implicit dependency injection if the names of parameters in the controller function definition match the name of the services.

Of the four services injection approach feels most idiomatic to Angular. We create the service once, the code for the controller can be separated out into its own file in the form of rails partial, and it takes advantages of the angular services dependency injection mechanism.