Should rails ajax calls be bundled into their own separate controller? - ruby-on-rails

Should AJAX calls that are not RESTful be:
put in the controller that most suits their functionality/view, or
bundled together into their own separate 'Ajax' controller?
I've been doing 1, but I've just read this (2725 diggs) article
http://zygote.egg-co.com/10-dirty-little-web-development-tricks/ (see point 9)
and this chap opts for method 2. But he is a PHP developer though.
One benefit could be that 2 might clean up the routes by doing something like 'ajax/:action' instead of adding members to restful routes.
It seems like a 6.5 of one, half a baker's dozen of the other type thing.
Which option do you go for?

I prefer the first approach:
it's semantically consistent. if an Ajax action involves resource XXX, you (and other coders) will know where to find things in your application, thanks to Rails conventions.
if your application is heavy on Ajax (and nowadays most of them are), you will end up with a behemoth AjaxController that negates the whole RESTful thing. The rest of your controllers will be there just to provide gracefully degraded non-javascript CRUD actions.
Similarly, testing your Ajax controller will tend to be somewhat messy because you will have to set up scenarios --load fixtures, mocks, etc. for each and every "ajaxified" resource of your app.

Your "RESTful" controllers probably include new and edit actions, neither of which are actually RESTful, they just provide user interfaces for the create and update REST actions. new and edit don't get a separate NonRestUIController or something, they are kept in their associated resource's controller, keeping your controllers semantically consistent. Similarly, Ajax actions that relate to a certain set of functionality or a certain resource should stay in the associated controller.

Related

Rails: Handling permissions for individual tables and composite views concisely

I'm struggling to find/understand the Rails concept for handling table permissions and permissions for composite views (and composite updates).
Logically, Create, Read, Update and Destroy permissions for tables should be at table (model) level. If I know exactly which permissions a user has on a table, then it is possible to derive from that whether the user has the necessary permissions for any particular view (which just consists of data from one or more tables), and I should never have to repeat these permissions.
The 'Rails Way' would therefore seem to demand a controller for every table (model) that will be used by the application, in order to set permissions for that table in a precise way (using before_action or whatever to validate the user for the particular CRUD action). (Aside: I'm not even sure if there's a good reason for not moving the permissions logic into the model itself, which is actually what I did initially before trying to adhere to convention a little more.)
However, Rails (and possibly MVC in general?) seems to dictate that there should only be one action/view per request. So if I want to make a view consisting of three 'index' views, one for each of the models A, B and C, I need another action/view and a new validation rule for this action. This new validation rule, of course, shouldn't be necessary; the user is allowed to see this new composite view if they're allowed to see each of the individual 'index' views (or more precisely, the data underlying these views).
Also, any Create/Update/Destroy params received relating to a specific model should ideally be passed to that model's controllers for validation/execution (and there may be parameters for instances of multiple different models). I don't think this is typically how it is done, however, because it would require multiple actions being called.
Have I misunderstood the Rails methodology for handling this, or is it really expected that you effectively repeat yourself with regards to Create, Read, Update and Destroy permissions for composite views (and composite updates)?
First off the Rails framework does not ship with any provisions for authentication (well except has_secure_password) or authorization (permissions) and is totally unopinionated on the matter.
There is no "Rails way" to handle authentication or authorization.
What Rails is geared towards is the Rails flavor of REST which is focused on exposing resources through a structured API. Each controller handles a specific resource or just a specific representation of a resource.
Note that a resource is not equal to a table. Tables are an implementation detail while resources are the abstractions that your application provides as a public API.
Of course since the framework is not opinionated towards any form of authorization you can roll your own in any fashion you want such as RBAC, ABAC etc.
Of course there are several community gems such Pundit and CanCanCan that remove the need to reinvent the wheel.
(Aside: I'm not even sure if there's a good reason for not moving the
permissions logic into the model itself, which is actually what I did
initially before trying to adhere to convention a little more.)
There is a very simple reason why this is a bad idea. Models are not request aware and do not have the proper context for authorization.
A much better alternative is to use a component like Pundit that compliments the traditional MVC structure, but is its own separate entity - you could even call it MVCP.

What's the difference between controllers and actions in ruby on rails?

Can anybody tell me the difference between controllers and actions in ruby on rails?
I fetched this definition from the official rails guide:
A controller's purpose is to receive specific requests for the application. Routing decides
which controller receives which requests. Often, there is more than one route to each
controller, and different routes can be served by different actions. Each action's purpose is
to collect information to provide it to a view.
I am confused.
Please, make it as simple as possible since I am newbie!
Thanks!
Controllers are just Ruby Class files which have a series of instance methods inside
Basic Explanation
Rails controllers are basically files where actions (methods) are kept
Each time you access a Rails app, you're sending a request to the system. The various technologies inside Rails route that request to a certain action, where your code can use the passed data to perform some sort of action (hence the name). The actions are kept inside controllers to give the application structure
So if you access http://yourapp.com/users/new, it tells Rails to load the new method in the users controller. You can have as many actions in the controllers as you want, but you have to tell the Rails routes system they are there, otherwise they won't be accessible
Proper Explanation
Rails Controllers are just Ruby Classes, storing a series of actions
The "actions" (instance methods) work on passed data (params) to create objects that can either be passed to the model, or used inside other methods
Whenever you send a request to Rails (access a URL), it first uses the ActionDispatch middleware to send your request to the correct Class (controller) instance method (action), and then your code does something with that data
Your job as a dev is to connect the right controllers with the right models, presenting the right data the user at the right time
DISCLAIMER: I don't write code in Rails (never did). I write Sinatra modular applications and use the MVC model.
You first need to clarify the MVC model. The MVC is an approach to programming web applications (in RoR) or user interfaces in general. So MVC stands for Model-View-Controller. I will try to explain a bit, but in order to understand this, you need to practice and play with it.
The Model: If you remove the layers of abstraction, it's your database scheme. The way your application interconnects in order to retrieve information.
The View: The way these informations are retrieved elaborated and served. Essentially is what you, or the client, see in the browser.
The Controller: The controller is what interacts with the program to produce a requested view or to alter a model. You request a view when you access a chart with statistical information, and you alter the model when you input DATA on it. In Rails ecosystem, ActionController is a class with a set of predefined methods to help you perform easier and quicker standard Controller actions like update a form, etc.
So the Action Controller allows you to alter data to your models (the db), or request a route to view your data, etc.
Action is not separated from controllers, it's basically what controllers do :-). Everything else is static.
If you feel that these concepts are still hard to grasp, try building a very basic modular application in Sinatra, and you will have a ground level view of how things work.
Explanation by Analogy (simple explanation without getting too technical)
I work in a busy office. I bark out orders (i.e. 'requests') to my staff to get em to do stuff.
e.g.
Sometimes I want a document so I can read it.
“Ngozi, pass me the ABC.ASX EOFY results please?”
Yes sir!
Sometimes I ask my staff to edit an existing document:
“Sunita, can you edit that report on the state of the union address?”
“Sure!” is the response.
I organise my staff based on the type of work they do
But I have a little problem.....I have 10,000s of different types of documents. Sometimes I want to get: (I) sports results and other times I want: (ii) the evening news, while still at other times I want: (iii) a collection of Donald Trump's latest 4 am Tweets.
So I created a new system. I have a staff member directly responsible for each type of thing.
Ngozi handles ASX (Australian Stock Exchange) Financial Results. And when I want Ngozi to do something (i.e. perform some type of action) then I tell him what to do.
Sunita works mainly on politics. Sometimes I”ll ask her to something (e.g. write up a report – this is one type of 'action', or I'll ask her to bring me a certain document – another type of action - and she'll do it. I like to get Sunita to work on politics and Ngozi to work on financial results. It's best to keep their responsibilities separated.).
And Freddie works on anything pertaining to Queen.
Etc. etc.
The meaning of the analogy?
In this case, the controller would be the person – who's responsible for handling certain types of requests. And the “action” would be the particular specific thing that I want done:
e.g.
getting a document or
edit something or even
creating a new document.
Hope that clears things up.

How to use the same model with Rails for different controllers while staying RESTful

I need to have two separate pages on the site I'm planning to build that are very similar that I don't need to introduce new DB tables or models. I would also like to stay RESTful.
If I'm to use the same controller/model I will need to have new methods other than standard index, new, edit...etc which makes it non-restful or I will have to have a variable on page that identifies it and then inside each method I will render different view accordingly.
Another idea I got was to have separate controller and model but use the same DB tables and enforce the model to use the table although it doesn't match the convention.
I'm guessing there might be cleaner way to do this. Do you know any? if not which way do you suggest?
Thanks,
Tam
I'm not afraid of the restafarian police! Sometimes your controllers need more than the 7 actions (where's the get to confirm a delete, eh?), sometimes they will need less. That's just the way it is when you start to create real world software.
If the actions you're adding are not coherent with the actions that exist (for example off by just a little bit but still off in most actions), then we're talking about a new controller IMO - otherwise adding a few actions where you need to is ok in my book.

Architectural best practices - where to put non-REST actions?

I'm making my first real Rails app, and am learning about REST architecture and how it fits into Rails apps. My controllers don't really seem to map logically to an individual resource, so it's tough for me to implement strict REST. For instance, I have a "catalog", "checkout" and "admin" controller, not a "products", "categories", "orders" and "users" controller, although those are the main resources being used in those controllers. Each of the controllers does more than just REST actions on a resource however, all of them pull from multiple models and service multiple views.
Am I missing a design/architectural practice that would make REST work better here? Namespaced controllers perhaps, with non-REST actions in the top-level controller only, and REST actions in the sub-controllers? Seems like I would run into some DRY violations there...
If this is the way you want to structure your app, forget about REST and just map the routes you need. If you don't actually want to manage resources why bother?
REST is great for resources. It's really painful to map a checkout procedure as a restful resource and not worth the effort, personally, I just have 4/5 actions in my checkout controller and that seems to do the job.
If you want the helpers, you can map named routes
checkout_delivery_path
map.checkout_delivery '/checkout/delivery', :controller => "checkout", :action => "delivery"
If you look at the HTTP spec here
you will see that one thing that POST can be used for is:
Providing a block of data, such as the result of submitting a
form, to a data-handling process;
So, you can create a controller that is a "data-handling process" and do a POST to it without violating any REST constraints. If you name the resource with a noun you can make URL feel a bit more RESTful, but it really is not not necessary. e.g.
POST /MyStore/CheckoutGirl
As for your Catalog, I don't see why that doesn't map easily.
GET /MyStore/Catalog/Item/2324
GET /MyStore/Catalog/SaleItems
The admin usually maps to users, roles, etc. There is nothing new there.
Stop trying to shoehorn every aspect of REST into every application. REST is an architecture, and it's not suitable for all purposes. If what you need is some RPC action, then use some other form of RPC, not the resource-centric principles of REST.
Also, the URL naming schemes are totally irrelevant to whether your application is RESTful or not. That's not what REST is about. They're nice to have, but just do what makes sense for your application.

Rails: How do I keep a complex app RESTful?

I always try to make my applications as RESTful as possible but I've recently begun working on a complex project that requires multiple additional methods in my controller.
I normally achieve this by adding another :collection to the route but it seems like a workaround and in on scenario I have 5.
Are there any best practices for handling the extra methods in a controller? They are generally simple forms that updates a model.
The other solution, which is what I do, is every time you find yourself creating an action that doesn't fit into the RESTful actions, eg Search, so you might find yourself making a search action on an Article controller, what you could do instead of creating this action is create a Search controller instead, and use RESTful actions inside of that instead. There is no rule saying you need to use all the actions, you might only need one or two, but it keeps your API RESTful and your code organised.
This is not a hard and fast rule, but I have certainly found it helpful when I try to decide where to put stuff.
I think there's a bit of confusion in the Rails community about how and where to use the word "RESTful". Strictly speaking, the only thing that can be RESTful is your web API (as railsninja already mentioned). That the code of an application that conforms to the REST conventions (the application with REST API) can usually be organized into a set of controllers (that match the resources) and methods in these controllers (that match the four verbs of the HTTP protocol) is nothing but a hint of how to keep your application clean and organized.
If we want to talk about a RESTful Rails application, we can't just talk about RESTful controllers - there's nothing RESTful about just controllers themselves. It's possible to have a complex web application with only one controller (and myriad of methods) that represents many resources and is perfectly RESTful.
That said, it's pretty OK to add more methods to your controller. Sometimes, it's good to extract some of these extra methods and create a completely new controller - make this any time you feel good about it (rule of a thumb: create new controller anytime you are able to identify it with some self-sufficient resource, ie. a resource which could exist just by itself). Sometimes though, it'd be silly to extract some resource to a different controller. Say you have a resource which has a status attribute. It makes sense to perceive this status attribute as a resource by itself and perform at least one action on it (update), but it won't make any good to extract it to a different controller.
There is a Railscast about this topic, adding custom actions to an otherwise RESTful controller.
Edit: I see that you've mentioned the method in the Railscast as a workaround already. :-) I believe the only other "pure" way to handle it would be to add additional controllers as required to support the actions you want.
"I normally achieve this by adding another :collection to the route but it seems like a workaround and in on scenario I have 5. "
This sounds perfectly fine to me. REST is not about the crud operations and your concern seems to stem from the fact that you are doing more than the basic crud operations but there's nothing wrong with that.

Resources