What's the difference between controllers and actions in ruby on rails? - 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.

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.

Am I thinking about MVC correctly?

I'm writing an application that details an applicant's status in our company through Salesforce; when one of our employees enters their Enquiry ID, it shows their status (cleared, not cleared) and, if not cleared, what the applicant needs to fix before they can proceed in their program.
I want to make sure that I am thinking about my application's different areas correctly. Here is what I have:
Model: The applicant class has a dynamic function, such as Application.find_by_Enquiry_Token__c_and_Account_dot_LastName_from_Opportunity, and when requested it returns the information from Salesforce
Controller: Parses the returned data from Salesforce and creates hashes with the information, such as #applicant[:general_information] = {:first_name = data[:Account].first[:FirstName], :last_name = data[:Account].first[:LastName]}.
View: Displays the information generated by the controller. However, it has it's own logic and checks, such as changing the color of a div depending on if they are clear (class="success"), if they are not clear (class="danger") or if they have some conditional information (class="warning").
I think I have this correct, except I'm a little worried about my view because I have a bit of Ruby code in there to perform checks based on the returned data, mainly to colorize but also to show certain errors. Is this okay/does this follow standards? Or should I try to refactor my application and push this up to the controller?
I would say having some ruby code like you do in the view is fine as long as you aren't performing long queries or setting instance variables in the view. Also another sign to start moving code from the view to the controller is if you feel the view is getting cluttered and hard to understand. From what you said, this seems like it is not a problem though.
One thing I would recommend changing is to make the method name on the model shorter. Shorter method names are much easier to understand and as you have it, the method name is very long and unwieldy. Other than that, I think you are doing everything well!
Displaying the correct classes in the view is fine and can't really be done anywhere else. If you feel like your views are getting messy, consider dividing them into partials or using Haml for views instead of ERB.
Model is where your application's business logic goes, including parsing data, and everything related to your domain.
Controllers handle interactions with the user. So, basically, in a webapp if a user goes to a URL what should your application do. This should not be doing anything other than handing off tasks to other classes and then rendering a view.
Views are just that. They should be super simple and straightforward as possible. You can extract logic from views into helpers or even presenters/decorators. Views handle what gets displayed to a user.
In your app I would have:
SalesforceApiGateway class which handles communications with Salesforce, I wouldn't be surprised if there was already a gem out there to handle this.
A model class for each Salesforce resource you are accessing. These would setup the proper call to the API gateway to pull the right data for the given resource.
This could get hairy quickly and may need to be extracted further: 1 class for interfacing with the gateway and a model class the resources as you would want to access them from your application.
Your controller should not be parsing any Salesforce data, but rather taking a user request and and wiring that up to the proper model.
The biggest thing to keep in mind is your classes should be doing one thing and one thing only. If you can't talk about your class without saying "and" then it is probably doing too much.
So you have a class that interfaces with the API. You have a class that parses the API. You have a class that brings an api's resource into your domain, etc.

Rails - Method in Model or Controller or somewhere else?

I'm practicing my Rails development skills by building an app that will have different types of exercises for users. Most probably things like multiple choice questions for different subject matters.
One way to check to see if the questions are answered correctly is to use validations on the model. However, I don't really need to save the results, and it might end up in me creating a lot of different models, as each question will have its own validation to check each answer.
Is an alternative to create a new Controller action for each subject area? Is
How else might I organize this?
http://www.enode.com/x/markup/tutorial/mvc.html
With the MVC pattern, Controllers are usually in control of manipulating data kept by Models.
It's good form to keep most of your logic in your Controller. I'm not sure what you mean about a new Controller action, but what you'll probably want to do is set up some sort of form in your View, (see form_for) and fire that off to the Controller. The Controller does validations or whatever you need it to do.
This should be helpful:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html
So for example, you might have a form in your View (a quiz for example), calculate a user's score in the Controller, and save that as a field for a user in your database.
The debate on where to put logic is as old as the involved patterns themselves. For MVC, I decided to ask myself:
Is the logic involved essential for the model?
Would the model (in itself) function well without the logic?
Is the model free of any requirements towards the controller?
If I'd re-use the model, would I want to take the involved business logic along or would it be in the way?
My general advice: Put business logic as "low" (bottom: db, then model, then controller, then view) as possible without violating any of the following constraints:
Authentication and authorization does not belong to view. It's either a property of the controller (handle things like sessions and general api access rules, etc) or of the model (authorization: who may access which content?)
UI/display/input-method related things do not get into model or db. Don't let your model/db decide if and how to render html, xml or json.
Data consistency and integrity not in controller/view. Ideally, your data model only accepts valid data, uses transaction safety and reports back failure or success to the controller. Ideally, consistency is handled at db level.
A model shall be reusable with other controller/views in new project (think of switching to another web api). Too heavy constraints may render it unusable in new situations.
there might be more...
And generally: If in doubt, put in into the controller. ;)

To get Analytics data and show on page what's the most popular items, should the code belong to Model, Controller, or View?

Suppose there is a call to get Analytics data from a third party or through our cache data on a server, for the "most popular items", and we show these items' names on all of our pages, should we put this code in Model, Controller, or View (Helper) component?
Maybe it is not strictly Model, because it is not directly in our data store.
Maybe it is Controller... should it be in the "general controller", such as in app/controller/application.rb to be sharable in all views? What if it is obtained in the controller code, but 1 month later, another person follow a new spec and remove the display of it on a view, then the code probably stay at the controller and nobody will remove it.
If it is in the helper... then what if in other part of the code, the controller need to get that data and store it in #popular? Also, aren't helpers suppose to help render data by putting repeated task in methods? So helpers shouldn't do so much data fetching logic.
Where is the code most properly placed?
Although I use .net mvc I think the same principles can apply.
So that being said here is what I usually have:
Controller > Service > Repository code.
So in this case you would have an Analytics service that handles the request and may make calls to third party or may call a repository layer (maybe both) that retrieves data from database. But this way all calls go through the same service. Plus removes any knowledge of how data is retrieved. In fact I had a similar situation one time where we were using a mail client and pulling in some of the analytics from their server and some from our database. All of that was hidden in the service layer so all that was returned was a model that could be used however it was seen fit.
Then all controllers who need it can share. In the view I would then have a helper that displays that data. Again anyone who wants can call the helper and pass the model data in required for that helper. This allows you to apply DRY principle.
Again this works for me. YMMV
I would like to suggest creating a google_api datasource. A quick google search should pop up a few of them that seem half finished to get a start with.
Use the GAPI class from google code from within the datasource to fetch data from google and format the results into something you can use.
Then you can setup a model for each metric you want to track. IE. class GoogleAnalyticsKeyword, GoogleAnalyticsAdWordCampaign etc. These models can be set to use your custom datasource. From the model you can do caching, validation etc on the data.
Then simply reference the models in the uses array in a controller. Either app_controller or dashboard_controller etc. Then just query the models from the controller you need the data to be available from.
http://code.google.com/p/gapi-google-analytics-php-interface/
http://github.com/msadouni/cakephp-plugin-google-analytics
(Disclaimer: this is coming from a Django background, my apologies if the terms or methodology don't directly translate into the MVC framework that you're using.)
My design process would basically go as follows:
I know that I wouldn't want to have to re-calculate the Analytics data for every page hit, so my choice is between just relying on a cache or using a cache in tandem with storing the temporary results in a database. I'd personally go for the latter method.
So I'd setup a Model to handle storing a subset of the Analytics data for the task at hand, saving the "most popular items" in your case. I would then create an automated task (say in cron, or in Django I would use Celery) to aggregate that data on a regular basis, perhaps at midnight every night.
Then I would just write some helpers to quickly query that aggregated data and display it in my template (the View in other frameworks).
In summary, I'd use a combination of the Model and View in the MVC paradigm. I don't see any reason to really involve the Controller in this process.
If you want to place it either Model, View or Controller, I would put it in a Model, because Models are responsible for CRUD actions, and retrieving a list of the most popular items is part of that.
I don't think it has to be in your data storage to count as a Model.
My 2 cents.

What is MVC in Ruby on Rails?

Could someone please explain MVC to me in Ruby on Rails, in layman terms. I am especially interested in understanding the Model in MVC (can't get my head around the model).
Some background, MVC is a (compound) design pattern and was developed in 1979 by Trygve Reenskaug (Smalltalk).
True MVC was primarily planned for use in n-tier (non web) systems and it splits a system into 3 distinct parts, a Model, View and Controller
The Model
Contains data for the application (often linked to a database)
Contains state of the application (e.g. what orders a customer has)
Contains all business logic
Notifies the View of state changes (** not true of ROR, see below)
No knowledge of user interfaces, so it can be reused
The View
Generates the user interface which presents data to the user
Passive, i.e. doesn’t do any processing
Views work is done once the data is displayed to the user.
Many views can access the same model for different reasons
The Controller
Receive events from the outside world (usually through views)
Interact with the model
Displays the appropriate view to the user
** Classic MVC is not suited to web applications, as the model cannot send all changes to the view in an observer fashion (the view is a web page). The Model2 was introduced to overcome the changing infrastructure by JSP team in 90s . MVC Web frameworks are really not MVC, but Model2 (this is true of Ruby on Rails).
Here is a description of GUI patterns including MVC from the master, Martin Fowler
GUI Architectures
The best book I have found so far is Agile Web Development with Rails. It begins by assuming no knowledge, and is quite comprehensive.
Hope this helps to shed some light for you!
MVC basically indicates Model-View-Controller. And MVC used by many languages like PHP, Perl, Python etc. Generally MVC works like this:
Request first comes to the controller, controller finds and appropriate view and interacts with model, model interacts with your database and send the response to controller then controller based on the response give the output parameter to view.
Your Model is the data structure that your program uses.
The View is the part that interacts with the screen or the next level up.
The Controller generally processes data between the model and view
MVC structures are often nested, so a "Model" or "View" may contain its own MVC (Think of a component on the screen. You may just fill it with a string, but behind the scenes the code of the component draws its own little view, has it's own little model (the string you pass in) and has a little controller drawing the data onto the view.
In Rails, the roles of the model, view and controller are well-defined by the framework, any tutorial will point out the three components as it walks you through the files it created.
In other systems, those pieces may be harder to identify. Also, MVC is not "Perfect", just keep in mind that there are valid alternatives, but it's a good way to start organizing.
The Model View Controller principle divides the work of an application into 3 separate but closely cooperative subsystems.
Model (ActiveRecord ):
It maintains the relationship between the objects and the database and handles validation, association, transactions, and more.
This subsystem is implemented in ActiveRecord library, which provides an interface and binding between the tables in a relational database and the Ruby program code that manipulates database records. Ruby method names are automatically generated from the field names of database tables.
View ( ActionView ):
It is a presentation of data in a particular format, triggered by a controller's decision to present the data. They are script-based template systems like JSP, ASP, PHP, and very easy to integrate with AJAX technology.
This subsystem is implemented in ActionView library, which is an Embedded Ruby (ERb) based system for defining presentation templates for data presentation. Every Web connection to a Rails application results in the displaying of a view.
Controller ( ActionController ):
The facility within the application that directs traffic, on the one hand, querying the models for specific data, and on the other hand, organizing that data (searching, sorting, messaging it) into a form that fits the needs of a given view.
This subsystem is implemented in ActionController, which is a data broker sitting between ActiveRecord (the database interface) and ActionView (the presentation engine).
Check the links below for clear understanding of mvc in rails:
http://www.bogotobogo.com/RubyOnRails/RubyOnRails_Model_View_Controller_MVC.php
https://betterexplained.com/articles/intermediate-rails-understanding-models-views-and-controllers/
I think the best way to wrap your head around MVC is by example. Try coding up a simple Rails app using MVC. There are many tutorials online, such as the blog example at "Getting Started with Rails".
If chose to learn by coding an example, check out the answers to Where can I find clear examples of MVC?
MVC isn't specifically just for Ruby on Rails. It was actually created awhile before Ruby on Rails ever came around. It's mainly just a way of organizing your code so that you have some code that's responsible for your models (the Class version of a database table), some code that's responsible for your views (what's visually being displayed to the user) and code that's responsible for your controllers (what ties the views to the models and performs the bulk of your logic.
That's the non-framework-specific description. Each framework that uses MVC has a different way of implementing it. For Ruby on Rails each model represents a database table as a class that can communicate directly in code with other objects without needing to write any SQL. All the SQL is being taken care of in the background and you just have to think of it as though it were a normal class (well almost, it's not seamless yet). The view is mostly HTML and represents what will be sent to the browser. The controller is just the code that communicates the models and views together.
All in all, MVC isn't specific just to Ruby on Rails...that's just the most popular.
Ruby on Rails does not implement the MVC design pattern. Ruby on Rails has folders called controllers, models, and views. The views folder has HTML files. The controllers and models folder have ruby files. The controllers map to a URL and a method in the controller gets executed upon requesting that URL, the associated view (HTML file) gets loaded and the model (data structure) for it is used to populate the view. Thats the extent of it's likeness to the MVC design pattern. It's a shame that people say it's MVC because it's caused a generation of confusion and misunderstanding of the MVC design pattern.
In Rails, the model is a data structure.
Here's a brief overview at a high level on how the MVC Pattern works:
Controller:
Listens on some kind of interaction/event stream.
Controller can send the model that type of interaction/event.
Controller can also communicate with the the view.
Model:
Models will listen in on the interaction/event from the controller.
Is an abstraction of a data source.
Handles data logic and manipulation.
After it is done with logic, it then sends to controller which will then communicate with the view.
View:
View can communicate with the controller.
Knows how to render data from the Model to the browser visually.
The Controller tells to View to do something with something from the
Model.
A couple of things to note is that models can't communicate with views directly and vise versa. Only the controller can communicate with the view and model, so the controller acts as the delegator for the interaction/event retrieved from users interaction on the browser.
check this link for more clear understanding
one more link to get clear

Resources