How are Model, View and Controller connected? - ruby-on-rails

I understand the different roles the Model, View and Controller play in an application but how are they linked to each other, for example a simple comparison is when linking a JavaScript file with an HTML file a tag is required with a 'src' reference.
Since learning Rails I have been told they are linked, but not how.
How are the Model, View and Controller actually linked and why is a 'src' or something similar not required with MVC and specifically Rails?

Basically it's all linked through routes controllers and actions.
The routes file (routes.rb file in your_app_root/config) effectively intercepts an incoming url and maps that url to a controller/action (actually that's done by a web server like Nginx which then passes the request on to your rails app via something like Unicorn but that's another question entirely).
So for a standard HTML site set up you might have a folder called home and in that folder you might have an index.html
So when you navigate to some_url/home/index then you will get the contents of the index.html file rendered in the browser.
In RoR for this to work you will need a route defining a get request for a collection (plural or no params passed in)
It could look something like this
YourApp::Application.routes.draw do
get 'home', to: 'home#index', as: :home
# etc...
That route would connect your browser to the index action on the home controller if you navigate to some_url/home
The index action in the home controller can just be an empty action
class HomeController < ApplicationController
def index
end
end
And providing you have an index.html.erb in the app/views/home folder then you will get that file rendered automatically as ActionController translates whatever you have told it to render in to HTML, css and javascript or json or XML if you are using resource routes and the request it receives is an XML or JSON request, and sends the resulting data back to the browser
If you wanted to get some data displayed from your database then the controller action has the responsibility of obtaining that data and stuffing it into an object (an instance variable which is denoted by an # symbol) that your view can use in an erb tag
e.g.
class HomeController < ApplicationController
def index
#some_records = SomeModel.all
end
end
This can then be used in the index.html.erb file like so
<ul>
<% #some_records.each do |rec| %>
<li> A record: <%=rec.some_method%> </li>
<% end %>
</ul>
Because you have a route you can use the routes name as a path for links and buttons to post data from the browser back to the server where the whole process starts all over again.
That's not a strict description of exactly how it all hangs together but it shou close enough to give you an idea of how it all happens

Model–view–controller is a software design pattern that organizes Rails applications. From the viewpoint of a software architect, it is an abstraction that simply provides a way to organize code. You can see the MVC design pattern in the hierarchy of classes in the Rails API, notably ActionController (controller), ActionView (view), and ActiveRecord (model), which are objects that can be subclassed to be used as components of your web application. You can also see the MVC design pattern reflected in the file structure of a Rails application, where you will find folders for models, controllers, and views. You won't see the actual code that wires together models, controllers, and views unless you dig deep into the Rails source code.
For a deeply technical introduction to the Rack middleware that ties together models, controllers, and views, you can read the RailsGuide: Rails on Rack which describes the Action Dispatcher.
The Action Dispatcher does the work of integrating the model, controller, and view objects. When you follow the Rails convention of organizing code according to the MVC design pattern, Rails does all the work of "linking" the code for you. You never actually see the code that "links" the MVC pieces together.
For a more complete explanation of MVC (and everything else that is Rails), see my in-depth article:
What is Ruby on Rails?
To understand Rails, you need to look at it from several perspectives, including software architecture.

Related

What is the proper workflow for storing data without multiple instances of database models?

I'm relatively new to web development. I am using ruby on rails.
If I had a website with blog posts, I would have a Post model inside my DB and would CRUD instances of it. What if I had an "about" page (where users can read about the blog) and wanted to edit a block of text on the "about" page? How would I go about updating the text displayed on that page?
It doesn't sound like it would make sense to store the data in a DB model as I would only have one instance of such model (since there is only a single "about" page).
What would be the appropriate workflow for storing and editing this data if I will only have one instance of it?
Static pages do not have any dynamic data - thus can be just plain HTML files or .html.erb in basic rails views.
All you need to do is create something like:
Have a route to yourpage.com/about.html inside your routes.rb file
get "/about", to: "static_pages#readme"
Have a controller to serve this route
class StaticPagesController < ApplicationController
def about; end
end
Notice there's no dynamic data on the about page so we do not have to set any variables inside a controller. (like you would set #posts in your PostsController)
Have a view template with the data you need to be displayed on /about page
app/views/static_pages/about.html.erb
PS. If you'd like to bypass rails all the way you can drop about.html inside public/ folder and check yourpage.com/about or localhost:3000/about.html in dev environment. (Look for 404.html page for reference), but I'd keep with the rails way.

what determines controller action ruby rails

at https://www.codecademy.com/en/courses/learn-rails/lessons/start/exercises/start-views, the controll action is described as 'pages#home':
Well done! Now when a user visits http://localhost:8000/welcome, the route
get 'welcome' => 'pages#home'
will tell Rails to send this request to the Pages controller's home action.
but when I made the controller I did rails generate controller Pages which is uppercase.
pages_controller.rb:
class PagesController < ApplicationController
def home
end
end
Is the pages part of pages#home determined by the first part of pages_controller.rb, ignoring the _controller.rb end?
What happens if I change pages_controller.rb to renamedpages_controller.rb but leave the class name as PagesController?
thank you
Action Controller is the C in MVC. After routing has determined which controller to use for a request, your controller is responsible for making sense of the request and producing the appropriate output. Luckily, Action Controller does most of the groundwork for you and uses smart conventions to make this as straightforward as possible.
Controller Naming Convention
The naming convention of controllers in Rails favors pluralization of the last word in the controller's name, although it is not strictly required (e.g. ApplicationController). For example, ClientsController is preferable to ClientController, SiteAdminsController is preferable to SiteAdminController or SitesAdminsController, and so on.
Following this convention will allow you to use the default route generators (e.g. resources, etc) without needing to qualify each :path or :controller, and keeps URL and path helpers' usage consistent throughout your application. See Rails Guides.
When a request is made like: http://localhost:8000/welcome, it matches a route in the routes.rb file where the route is mapped to a controller and an action.
In your routes file, you have:
get 'welcome' => 'pages#home'
get 'welcome' part matches with the url .../welcome and map this request to pages#home where pages is the controller name and home is an action (a method defined in pages_controller). This is Rails convention to name the controllers like this: ControllerName_controller.rb. So, basically pages is your controller's name and the last _controllers is common to each and every controller in your Rails application.
What happens next is, this action of the controller do some work and talk to the model/database and build the required variables/data that will be passed to a view. According to Rails convention, there has to be a matching view file like: home.html.erb which will render the response to the browser.
There are other ways to render different partials and views in different ways, but if you follow the Rails convention, then it becomes very easy to understand and work with different Models, Views and Controllers in Rails. This is called: Convention Over Configuration.
When you follow the Rails convention for naming things, Rails does a lot of work and configuration for you for free to make your life easier.
When you have get 'welcome' => 'pages#home' in your routes file, then when a request: /welcome comes, it maps to pages_controller and it will look for the pages_controller.rb file under the app/controller/. If you rename this to something else, then the program will not find it as it expected and will throw you an error and your request will not be completed.
Your controller's name has to match with the class name of that controller, This is also a Rails convention. If you change any one of them, then you will get an error and your request will fail.
Yes. and #home is the "action" in PagesController
You get a uninitialized constant PagesController error
So, your controllers should always be in the form NameController defined in name_controller.rb, and actions as public methods in NameController.

What is the "_path" method in ruby on rails?

I'm learning RoR, and I'm getting very confused by the "_path" method as it's used in Controllers and Routes. To be more specific, I'm referring to the many different calls that take the syntax "(something)_path". So far as I know, they all seem to either encode or manipulate a URL or link. I'm having a hard time mastering the use of this type of method because I can't figure out what it's core functionality is supposed to be.
For example, I could use the following code to redirect an old URL structure to a page of listed Tweet instances in my config/routes.rb file:
get '/all' => 'tweets#index', as: 'all_tweets'
Only now can I use the following in an .erb file. Notice the "_path" code at the end of the line.
<%= link_to "All Tweets", all_tweets_path %>
I could also use the following code to create a link to an edit page (and another action) in a different .erb file:
<p><%= link_to tweet.user.name, edit_tweet_path(#tweet) %></p>
I've tried reading through my study materials as well as the RoR documentation, but I always end up more lost than when I began. Does anybody know the low-level definition of this "_path" method?
Helper
It's called a route helper, which means that Rails will generate them to help provide you with resource-based routing structures. I'll explain more in a second
--
To explain properly - Rails is just a framework.
Like all software, it is a series of files loaded in a particular order. As such, Rails creates a series of helper methods in the booting process. These "helper" methods can then be used throughout your application to call functionality / information as you require:
The Rails framework provides a large number of helpers for working
with assets, dates, forms, numbers and model objects, to name a few.
These helpers are available to all templates by default.
In addition to using the standard template helpers provided, creating
custom helpers to extract complicated logic or reusable functionality
is strongly encouraged. By default, each controller will include all
helpers. These helpers are only accessible on the controller through
.helpers
The route helpers (which are generated from your config/routes.rb file give you the ability to call routes which are resourceful. These might seem strange to begin with, but once you understand them, will help you inexorably.
--
Resourceful
To give you more clarity - Rails routes are known as resourceful
This means they are constructed around resources. To give you a brief definition of this, you need to appreciate that the resources of your application are the pools of data you can add to, and pull
from.
To explain further, because Rails is object orientated. If you're new, this won't mean very much, but keep it in mind, as when you progress through the language / work, you'll begin to see why this is important.
Object orientated programming puts OBJECTS at the center of the flow. Typically, you'd put logic at the center, but with OOP, it's the objects. This is very important for us, as it means that everything you do in Rails is based around the objects you can create.
As per the MVC principle (which, again, is what Rails is built on), you'll create / invoke your objects from your Models:
This means that if you want to create a series of routes to "CRUD" (Create Read Update Destroy) your objects, Rails is able to create the routes necessary to do that. This is where the resources directives come from inside the routes file:
Hope this helps!
Actually, these paths are generated based on your routes.rb. If you run this command at your project, you would be able to see all available on your app
rake routes
For example, if I declare my resources in routes.rb like this
resources :posts
then I would automatically have following available paths
posts_path
post_path
new_post_path
edit_post_path
If you use some strange abc_path which has not been declared in routes.rb, then you will get errors.
Hope this is helpful, you will definitely need to work more with Rails and then eventually you will understand all of these things :)
you could find definition for these methods in rails repository:
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/route_set.rb#L127

Rails. How to put few controllers on one page

I am working on Todo app now and I have troubles. After sign in, I am on persons profile(first controller), on it I have button for new project(projects controller-2d controller) and after pressing it, appears button for new tasks(task controller-3d controller). How I can put all of this 3 controller's views on one page. Here an example of what I mean(approximately):http://todo.kzotov.ru/
You can put anything you want in the view. You could eager load the projects and tasks and put it all on the profile page. You also don't have to map controllers and views to models, so if the PersonsController or whatever is not what you're looking for, maybe do something more specific like ProfilesController and host all this functionality there.
MVC
You'll be best reading up on the MVC programming pattern -
The bottom line is that if you send a request to your application, it will only hit one controller#action. Your multiple "controllers" should not be something to consider - you should only look at the single controller action you're accessing at that specific time.
To be more specific about this, let me detail how it all works...
OOP
Ruby (on top of which Rails is a framework), is object orientated.
This is not just a fancy phrase - it's a real pattern of programming, which allows you to focus the flow of your application around the data / objects you want to create. The objects in Rails are derived from your Models - collating & organizing the respective data for your controllers
In order to understand how Rails works - you need to appreciate that everything you do is based on objects. Your routes, actions & data all work together to provide the end-user experience we know from Rails. How that happens is down to you.
Specifically, you want to look what what you're accessing
You don't want to load multiple controllers - you want to build several models and show those. This gives you the ability to show the HTML elements / files you want:
Recommendation
I would make sure you can put all your activity on your single view, which will then mean you have to determine your controller's data in order to provide you with the data you need to show:
#app/controllers/profiles_controller.rb
class ProfilesController < ApplicationController
def index
#your index
end
end
#app/views/profile/index.html.erb
<%= link_to "task", task_path %>
What you'll probably want to do is create a separate route / method to give them the ability to pull back ajax data when the initial button was clicked. I can detail this if you need it, but what I've given you should be ample food for thought

what are the sequence of events that happen when you get a page

Im trying to get my head around the sequence of events that happen between when rails receives a get/post command and the page is served. I was just trying to map out the sequence myself and i realised i dont fully understand myself which scripts is even ran first so I'd like to clear it up in my head.
many thanks
jon
The request goes into the route matcher which parses the URL, parses the config/routes.rb and if the URL matches a route, it looks for a controller file whose name matches the controller part of the URL, (e.g. http://localhost/categories will look for a CategoriesController)
Then, one of two things happen:
If you're using a Rails restful route, the route matcher applies heuristics to figure out which of the 7 actions to call: a GET on a plural last part is mapped to index; a GET mapped to an ID-looking part after the plural is mapped to show (e.g. categories/1 or categories/something or categories/1-something); a POST to a plural last part is mapped to create; a PUT to an ID-looking part after the plural is mapped to update; a DELETE to the same URL is mapped to destroy; new and edit are mapped to GETs for categories/new & categories/edit.
If you have a custom action, you must have a method in your controller object of the same name.
The chosen action is executed and then Rails either renders the template/file/action specified in the render call within the action or it looks for a view file of the same name as the action and that ends with .html.erb (by default) in the app/views/ directory.
Simple.
Rails does quite a lot of things, a good way to get a decent overview is to read the "Action Controller Overview" document at rails guides: http://guides.rubyonrails.org/action_controller_overview.html
The basic structure is:
rack middleware
routing
filters
controller code
rendering
filters
But rails also does many things by itself to the request. It automatically determines what kind of response you want based on your accept headers, and/or if you manually specify which type of response you want with a file ending like /blog/1.xml. Rails also magically creates a nicely formatted params hash, parsing params like user[name]=foo to {:user => {:name => "foo"}}. Rails also has built-in exception handling and some nice stuff to prevent cross site request forgery and much more, so check out the Controller Overview for the lowdown on that.

Resources