Accessing POST params in routes.rb - ruby-on-rails

I have a system with a web UI that works as normal, and an API endpoint at /receiver_api. Users send emails which are parsed by Mailgun, who then submit a POST to this endpoint. There are a lot of possible actions that we may want to take, depending on the values of these params (create new post, create new reply, add subscription, delete subscription etc.), and when writing the handler it felt like we were doing a kind of routing again!
So we would like to choose the controller that we direct the request to based on what the POST params are. We are directing /receiver_api to a ReceiverApi#receiver controller/method at the moment, which inherits from ApplicationController. It currently effectively routes requests to other "fake" controllers that don't inherit from ApplicationController (since redirecting from one Rails controller to another wouldn't work). We would like to be ultimately routing to Rails controllers so we can use before_filter and all the other magic in them.
Anyway, one possibility that springs to mind is a method in routes.rb that accesses the POST params and returns the Rails controller/method that should be directed to. 2 questions:
Is this possible? Can you access POST params in routes.rb?
Is there a better way of doing this? We had thought about moving up a level into Rack, and will probably do this at some point, but would rather just get something out of the door if this will take a while.
Thanks!

Choosing a controller based on params is not a good thing to do.
A better alternative is to refactor your code (in those fake controllers) to methods in your model, and call model methods based on the params from your controller.
You cannot access params in your routes.rb, because it is run at initialization.
If you really want to call controllers based on params, there is a way of doing this, by redirecting to another controller. This is explained in http://www.railsonwave.com/2008/10/25/how-to-call-a-controller-s-action-from-a-different-controller/ [bad link], but do note that it is very much a hack.

Related

How should I be updating data with AJAX?

I am making a rails MVC style application.
When I am loading the pages, the controller gets the data from the model and forwards it to the view and the view renders itself.
However, I am wondering what the appropriate way is to interact between javascript and my database.
Say the user is playing a game and he has a bunch of clues on the screen. Clicking a clue will move it to his clue box and needs to update the UserClues model to add the clue.
The user also needs to be able to remove clues where the clue gets removed etc...
This needs to happen via AJAX.
I am wondering what the appropriate approach is.
Say he got his page from /Investigation which loaded the page using the InvestigationController.
Should the InvestigationController be the one calling the model to add/remove the clues, or should some sort of data controller do it.
For example:
/Investigation/AddClue
or another controller
/User/Clues/Add
The reason I am asking is I have a lot of data on my pages that is created/added/modified and I am wondering if my routes/controllers should be separate for data manipulation and pages, or if I should have a controller for each page and it also manages what the user can do on that page (like add / remove clues to and from a ClueBox)
Thanks
Ideally you will want to have a separate controller for each resource. Even though your current view is in the context of the Investigations, controller, dealing with clues should have its own resource. Otherwise things can get complex. If the clues are investigation specific, then you can scope them under the Investigation URL.
resources :investigations do
resources :clues
end
This will give you something like /investigations/1/clues/1, but this maybe not be necessary, and I would avoid nesting unless required.
The controller can then respond in the correct format. In this case Rails UJS provides you with the tools you need. You can render a create.js.erb or destroy.js.erb templates to handle user actions. The templates would have the required JavaScript and dynamic code to update the screen state.
If at all possible, try to use Rails' RESTful routes. In this case, that probably means line in your routes file that looks something like:
resources users do
resources clues
end
In your users/clues_controller.rb file, put in actions for the different AJAX requests, like create to add a clue to a user (via a POST request), destroy action to remove a clue from user (via a DELETE request, might need to simulate with POST + "_method=delete" parameter).

How to be RESTful in Ruby on Rails?

I have a decent amount of experience with rails, but I've always been a bit ad hoc with my development methods. I'm curious about how to be properly RESTful in rails. Here's an example of an app I'm working on now:
I have a few models, including a User, Pack, and Product model. The models each have a controller associated with them. If I want to create a new page called 'Dashboard', on which the User can create new records on the Pack model, as well as see their account information, how do I do this in a restful way? Do I create a new controller called Dashboard? Or do I add it to a controller that defines my 'Static Pages'? What's the best practice regarding pages that aren't exclusive to the actions on one model?
Thank you in advance!
Yes, basically you want one controller per resource. In this case the resource is a combination of things but since you've identified a singular meta-resource (a "dashboard") it makes sense. So, I'd create a DashboardsController and then have a route like:
resource :dashboard, only: :show
Then you can use dashboard_url for links to the dashboard.
NOTES: The singular resource in the routes file is important because it indicates you don't have a list of resources, just a single one. This means there won't be an index action and the show action will be the default -- thus dashboard_url doesn't require a resource to show to be passed to it. And, regardless, controllers are named in the plural -- thus DashboardsController.
I would create a DashboardsController despite not having Dashboard model. Then to maintain REST principles have a controller method :new and controller method :create. Simply disply the information on the dashboards/new.html.erb but have the form post to the :create controller action.
To supplement the answers already given, REST really exists to make an easily-consumable API. (Notably, Roy Fielding's work is in the area of APIs, and REST is built on top of HTTP methods that HTML doesn't allow.)
This has been a common stumbling block since RESTful routing debuted in Rails; people get the impression that every controller now needs to be RESTful and that the front end and API should never diverge. Frequently, though, the front end and API have different needs.
For resources you want to be accessible via an API—Products, Users, Packs—trying to be RESTful is ideal. For those sorts of uses, pdobb's advice to have one controller per resource is generally exactly what you're looking for. They make sense in the context of an API being consumed by a machine.
But what about the dashboard? Dashboards are generally an HTML view intended to be rendered in a browser and viewed by a human being.
Does a "dashboard" resource make sense in the context of an API? Would it make more sense to instead make that data available in other resources? Is that data available in other resources?
Even if a "meta-resource" aggregating data still makes sense, would it be more logical if the API version had another name, like AccountSummary?

RESTful Actions Best Practices

I've got a RESTful User model working well in Rails 3. I'd like to add a new option to create a new user based on information queried out of a LDAP server.
What I'd like advice on is how best to do this. Here's what I've thought up so far, but I don't know if it matches Rails best practices:
Edit the resource path of User to accept both GET and POST to a new view called "import_ldap_user".
Import LDAP user then presents a form which uses AJAX (POSTing to import_ldap_user) to allow the visitor to search for a person in LDAP. The results are displayed on the page and if acceptable, the user clicks "Create", which then calls /user/create.
Part of why this seems bad to me is:
I need to post a proper #user to /user/create, but I'm not sure if my AJAX call can produce a proper #user.
I don't know if it's a bad practice to add a new verb to the RESTful Users route.
I don't know if using an AJAX POST to import_ldap_users is a proper separation of concerns.
Any ideas? Any Rails perfectionists have opinions about how this should work?
What gets posted to /user/create isn't an #user object but rather its attributes. A scaffolded create action will probably have something akin to #user.new(params[:user]), which just pulls the user attributes that were posted and creates a new object based on that.
Even if your AJAX call doesn't provide the attributes in a manner that can be processed by the new method, you can simply modify your create such that it manipulates the post data.
As for best practices, this is definitely something I've thought about in the past but I don't know if there's a "correct" answer. I think having a new view which posts to the create method is perfectly acceptable, you could also create a new controller if you want to strictly follow the CRUD pattern.
Definitely a good question and if anyone has a better answer I'd love to hear it.

Cons of using the generic routing in rails

What are the cons in using the generic route:
match ':controller(/:action(/:id(.:format)))'
I was told it is not recommended yet I do not see why. What problems can I get from using this?
Because it's easier to implement REST if you use the opposite ordering, ':controller(/:id(/:action))', and rails now has more convenient ways to get the proper HTTP verb using explicit resource routes.
Understanding the basic principles of REST will make it easier for you to expose an API, should you choose to go down that route, which embraces the principles of HTTP. It also tends to keep you from doing certain unclever things, like making it possible to delete records using a GET request. (The uncleverness might not be discovered until Google or your internal search bot decides to index all the links to :delete actions.)
The basic idea is that a GET /Url should imply fetching a resource. When you put the action first, the resource is semi-obscured, and you're accidentally opening the door to potential errors because all of the HTTP methods can be used to call destructive actions. Using an HTTP verb-centric approach, you can send an UPDATE request to the same URL as the SHOW request.
A specific answer to your question, which I understand to be understanding cons of the generic approach:
One significant risk is that you make every single controller action (non-protected) available to your users. It gives them the ability to access your entire 'tree' of controller actions, which may or may not be desirable depending on your situation.
In addition, you give users the ability to GET rather than POST, POST rather than GET, etc.
The comment above it that is generated explains it pretty nicely.
# Note: This route will make all actions in every controller accessible via GET requests.
This means that you could theoretically do a GET request on a route that is only supposed to be accessible via POST. ie. You could do add a route called /postable to a user object, which should only be POST'd to, but if you use the rule above you can also do a GET request on it (with empty parameters).
You don't really get problems, per se. Instead, you lose out on the advantages you gain from using resource routing:
A common pattern that helps simplify controller design
Free RESTlike handling of HTTP verbs (GET, PUT, POST, DELETE)
Peace, Love and Happiness*
You can find out more about resource routing by reading the Rails Routing Guide.
* Peace, Love and Happiness not available in all areas. Terms and conditions apply.

Should RoR urls look like /users/register or /user/register?

Should urls have pluralized words in them or singular?
I personally like:
/user/register
Is this against the 'convention'?
I think it depends on the way you think what it is.
From the perspective of syntax, it seems to me /user/register make more sense. While from the perspective of resources, the /users/register make sense.
Is there more than one User in your application?
If so, the standard /users/register would be the conventional REST url scheme for registering a new user - assuming this results in a user being created.
You might consider the more convention /users/new unless "register" really is a different action than creating a new user somehow.
Yes, that's against the RESTful convention of /users/new. However, I don't see much of an issue with using more user-friendly URLs, especially if you preserve the original REST URLs too. In all my applications, the first thing I do is setup routes to /signup, /login and /logout.
Plural form controllers are the convention, because it makes the most sense, it implies /users/ will be an index of users etc.
However, the only time I would consider using a singular form controller name here is if, for example: your application is a little more closed, and users cannot view/modify each other (no index), and you were using this controller only to allow users to register and view/update their own details. In that case the singular form can be a sensible option, but it's still a matter of preference.

Resources