I want to use angular resource to interact with my rails backend, the build-in $resource service is not fully compatible with rails API, like PUT is not support by default, I have to add custom action "update" with PUT method.
This problem with this approach is I have to add update action for every resource to make angular resource align with the rails API backend.
Is this the good approach to go?
I also found a angular resource wrapper angularjs-rails-resource, which provide a update method with PUT http verb, but it seems like the way how it handle parameters passing is a bit odd. for example, it wrap the parameter with a "undefined" key.
Parameters: {"undefined"=>{"username"=>"xxxx"}, "version"=>"1", "id"=>"88"}
So, the question is what is the best practice to use angular resource with rails API?
If you don't want the overhead of restangular and just want to add the update method to every resource, you can simply add a decorator to the $resource service.
Something like this:
.config(function ($provide) {
$provide.decorator('$resource', function ($delegate) {
//Store the delegate, so we can access it later
var resourceFactory = $delegate;
//Add the actions that you want added to each Resource here
var default_actions = {'update': {method: 'PUT'}};
return function (url, paramDefaults, actions) {
actions = angular.extend({}, default_actions, actions);
return resourceFactory(url, paramDefaults, actions);
};
});
})
Use angular-rails-resource. It is optimized for the Rails philosophy, which means that you don't have to juggle around with request/response format by yourself. And it supports a lot of other cool features, like nested resources, automatic name conversion, etc...
Take a look on restangular. It's really a nice solution for interacting with rest api.
Related
My question: When using AJAX within Rails, from a best practice standpoint, does the HTML verb that I use (e.g., get) to define a route matter? Is it OK to basically always use get?
Context: In my Rails App, I've built the following:
When a user selects an HTML checkbox, that triggers a JQuery listener that lives in a file inside of /app/assets/javascripts.
This .js file makes an AJAX call to a controller/action: foos#bar. My JS passes an ID into the action.
To route this request, I've added the following to routes.rb: get "/foos/bar" => "foos#bar". This tells my App which controller/action should process the AJAX call.
The controller/action handles this request just fine. The action grabs the ID as a URL parameter, updates the relevant model object, and finally returns back a 200 to the JS AJAX caller.
This all works great! No issues -- nothing to troubleshoot here.
My question is: In the example above, is it appropriate to define a get route within routes.rb to process this AJAX request? Or, is that bad practice? Should I instead be defining a put, since conceptually that is what I'm doing in this workflow (i.e., I'm updating an existing object)? I'm worried that, while this all works perfectly, I'm breaking some fundamental MVC routing standards.
If you are updating a resource it will most likely be a PATCH update, which means you aren't completely replacing the resource but are just updating it (this is why PATCH is the default HTTP method for updates in Rails, instead of PUT).
So, yes, you are violating RESTful conventions by using GET to update a resource. GET is only used to fetch a representation of a resource...without changing it in any way.
In my Rails application I have an url routed to an action in charged of showing or creating (if not existing) e resource. What is the appropriate http verb to use for this kind of request?
To be more precise, in my method I don't directly access the resource but I use a library which has that behavior: first search and then create the resource if not exiting. My method, in the end, always provide the resource returned by the library either a brand new one or an old one. Hence I cannot split into two requests.
According to this and considering my method always returns the same resource (idempotent) it seems that PUT should be the right one. I just wonder whether PUT can be used in case where e resource is actually just retrieved (get) and anything is not even updated
tnx
POST for creating, GET for showing is automatically used by rails. But I hope you can do all sorts of things with custom programming as data will be available to you in form of params[]
According to Ruby on Rails guides, you should use GET and POST verbs. More information here: http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions
You use GET to retrieve.
If resource found return 200 with resource.
If resource not found let it return 404 and check the error code and use POST and create the resource.
If you donot need any parameter while creating resource then you should use GET request Else if you need params while creating resource , then you should make separate action for creating(Post request with params) and showing(GET request) resource.
I'm playing around with angular in my rails app. This is not a single page app, i'm just using angular in a few places. I'm having a hard time getting route params from the uri to use in my resources.
For instance, say I'm on the page /users/1/posts/2. How do I get both user_id and id(for post)?
Thanks.
You could configure your angular app to pass the params to the controller your using for that page.
I would make a routes.js file doing something like:
App.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/your-route', {
controller: 'yourNGController',
resolve: {
params: ['$route', function($route){
params = {user_id: $route.current.params.user_id}
params.merge({post_id: $route.current.params.post_id})
return params
}]
}
})
}])
Then in your controller - "yourNGController' inject 'params' that you resolved in your route. That should get your the info you need into the controller.
If using newer versions of angular you may also need to include the angular-route.js as $routeProvider was removed from the core angular components.
I ended up just using ui-routes which makes this problem a whole lot easier.
I had a similair issue, and it is linked here: Passing Rails ID to Angular
I consider this solution a bit of a hack, so am interested in better approaches.
I want a /plan method to return a json object that's itself returned by another local (but belonging to another web app in java) URL (let's call it /plan2 for the sake of this question).
What I want is not a redirect but really to have /plan return the data as it is returned by /plan2, to which I'm appending a bunch of other keys. Since the request is local, would using Net::HTTP be overkill? What are my options, considering I'd also like to send an HTTP Accept header along.
Shooting in the dark here, but I am assuming that /plan belongs to public Rails app and the /plan2 is the url from another web app (maybe not even Rails) on the same server accessible by Rails app but not publicly available. If this is the case, then yes, you can get the response, but I would suggest rather OpenURI or Mechanize than Net::HTTP. If you put it in respond_to JSON format block then everything should be fine with Accept header also.
are you speaking of re-using functionality of another controller-method?
there is no standard way of doing this in rails. you could either put the common functionality into a module and include it this way, or use inheritance if the functionality is in another controller. if it's the same controller class, you could just call the method.
if it's a "private" url, how are you going to call it via http?!
I would suggest encapsulating whatever functionality /plan2 uses and simply re-use that in /plan1
But if you just want to get it to work...
class PlanController < ApplicationController
def plan1
plan2(extra_parameter_1: true, extra_parameter_2: 'hello')
end
def plan2(extra = {})
params.merge!(extra)
# Whatever your code was before...
end
end
I want to use ExtDirect for a 3rd party extjs user interface in Rails 3. So I have started to update the active-direct gem to work with Rails 3. Here is the updated version: https://github.com/stonegao/active-direct
At the moment my modified active direct plugin/gem works with models. I'm able to do this in JavaScript:
App.namespace.Project.all({params},callback_function);
That's great.
Now I want to use some special Rails 3 controllers (that act like a service).
In my Extdirect JS is this:
App.mynamespace.MyProject_Controller_V1_workspaceController.getStatus
This response also comes to my extjs router. No I want call this controller action and get the response.
I can't use #app.call(env) with a changed request_uri because I have no match in routes.rb
Is it possible to call this controller action
Specification of extdirect: http://tinyurl.com/4y3nc44
Thanks skeller1
yes, it is!
just do something like this:
status,headers,response=ProjectsController.action("index").call(#env)
so you can call the index method of the ProjectsController.
beware: ExtDirect accepts all types in the HTTP_ACCEPT http header field.
so you can do a
#env['HTTP_ACCEPT'] = "application/json"
before your request to an action to set your wanted response type.