From 32f02a4d2f587ed7bf1c828308ce88186dc73dbc Mon Sep 17 00:00:00 2001 From: Jamison Ordway Date: Mon, 17 Jun 2024 13:52:46 -0600 Subject: [PATCH] Add updated Intro to MVC to index --- .../images/lessons/intro_to_mvc/mvc_rails.png | Bin 0 -> 31988 bytes module2/lessons/index.md | 1 + module2/lessons/intro_to_mvc.md | 134 ++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 assets/images/lessons/intro_to_mvc/mvc_rails.png create mode 100644 module2/lessons/intro_to_mvc.md diff --git a/assets/images/lessons/intro_to_mvc/mvc_rails.png b/assets/images/lessons/intro_to_mvc/mvc_rails.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca304607650ebc0a984f4c7526e95d4f1facdcd GIT binary patch literal 31988 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 D867gM literal 0 HcmV?d00001 diff --git a/module2/lessons/index.md b/module2/lessons/index.md index a469db7b..dbd5b491 100644 --- a/module2/lessons/index.md +++ b/module2/lessons/index.md @@ -5,6 +5,7 @@ title: Module 2 - Lessons ## Introduction To Rails * [Beginner Rails Workshop](./beginner_rails_workshop) +* [Introduction to MVC](./intro_to_mvc) ## Professional Development * [Overview](./pd_overview) diff --git a/module2/lessons/intro_to_mvc.md b/module2/lessons/intro_to_mvc.md new file mode 100644 index 00000000..0f20659d --- /dev/null +++ b/module2/lessons/intro_to_mvc.md @@ -0,0 +1,134 @@ +--- +layout: page +title: Introduction to MVC +--- + +## Learning Goals + +- Identify the elements of the MVC design pattern +- Describe the single responsibility of each of the Model, View, and Controller +- Describe how data is passed through the MVC pattern + +## Vocabulary + +- MVC +- Model +- View +- Controller +- DSL (Domain Specific Language) + +## Warmup + +- Open the Task Manager app you completed earlier in the inning. If you need a fresh copy of that application for any reason, a complete version can be found [here](https://github.com/turingschool-examples/task-manager-7-complete). +- In your own words, what are the primary responsibilities of the models, views, and controllers in Task Manager? + +## Overview + +- **Models** - Interact with the database. Holds other methods related to a particular resource (e.g. a `task`) +- **Views** - Templates for pages that we will display to our user. Frequently contain placeholders for data, making them dynamic. +- **Controllers** - Coordinate the response to an HTTP request. In Task Manager, we just had one, but it is common to have multiple controllers. + +## Controller + +Look at your Task Manager `routes.rb`. + +- Routes in Rails are defined as part of its DSL (Domain Specific Language). +- The first keyword, a predefined method, of these routes corresponds with the **HTTP verb** the request is making to the route. +- The argument this method takes is a string version of the **path** the request is being made to. +- The second argument specifies which controller action should handle the request. The DSL syntax is `#` + +Look at your `tasks_controller.rb`: + +- Each route maps to a controller **action** +- A controller **action** is a **method** defined in a Controller class +- Controller **methods** and **actions** are synonymous +- Controllers send commands to models to perform database interactions + - ex: the `index` action retrieves all the tasks + - ex: the `create` action saves a new task +- Controllers pass data to views via instance variables + +## Model + +Look at your Task model. + +- Nothing! So where do we get the ability to call methods like `Task.all` and `Task.find`? +- Every controller within the controllers directory will have access to EVERY model in the database. +- The file naming conventions for models is singular. +- A model that inherits from `ApplicationRecord` should have a corresponding table in the Database. + +## View + +Look at a view from Task Manager. + +- By default, Rails looks for our views in a `/views` directory. +- Use ERB (embedded ruby) to describe how data should be used to create HTML + - `<%= %>` renders the return value of the enclosed statement. Use this when you need something to be a part of the HTML document sent to the User. + - ex: `

<%= task.description %>

`**This piece of code will be extremely useful for assigning** `id` **attributes dynamically, which is important for testing. Bookmark this piece of code!** + - ex: `
` does not render the return value. Use this when you don't want the return value to become part of the HTML. Typically, these are used for Ruby statements that control other statements. + - ex: `<% tasks.each do |task| %>` ... `<% end %>` + - ex: `<% if @tasks %>` ... `<% end %>` + + +## Putting it All Together + +- Someone sends a request to your application. That request includes: + - An HTTP verb (GET, POST, etc.) + - A URI path (`/tasks`, `/`, `/tasks/2`) +- Rails inspects the verb/path combo and determines what controller action to call based on what routes you've defined in `routes.rb` +- Within that controller action, we: + 1. Perform any data manipulation we need using our model + 2. Collect any data we need to use in our view (using a model as a go-between) + 3. Render a view or redirect + +Let's draw a diagram to represent this process. + +

+

+ Rails MVC Diagram +
+

+ +### Logic "Responsibilities" + +The MVC Design Pattern describes the primary responsibility of each portion of code that we'll describe a little bit deeper here. + +### Models -- Data Logic + +We saw earlier that the Model is responsible for interaction with the database. In MVC, we say that the Model is responsible for "data logic". *Calculations, filtering of data, or other manipulation of data should happen at the Model level.* When fetching data from a Model, the Model should only return raw data in an appropriate data structure -- usually an array, but can also be a hash. + +A Model generally does not alter data. For example, it would be appropriate for the Model to calculate the average age of all students, but it should NOT 'round' that data to, say, two decimal places. It can force the result to be a floating point number with `.to_f`, but it should return raw data as much as possible. + +### Views -- Presentation Logic + +Views have very little logic in them, generally just if/else statements and perhaps doing some basic iteration over a dataset. *The primary goal of a View is to manipulate raw data given to it by a Controller to present that data* in a way that is useful to our users. + +If a View has access to an instance variable, or a collection of instances in an array that it is iterating over, it's appropriate for the View to call "instance methods" from the Model class if needed. A View should not call *class* methods except in extremely rare cases where a data builder requires it, such as a drop-down select in a form for example. + +
+### MVC and Forms + +In MVC applications, we can get and manipulate data on an html page in multiple ways. You've collected data from a user with JavaScript eventListeners as part of the Hang In There project, and now we are using erb to get data from our view to our controller, as well as from our controller to our view. +
+ +### Controllers -- Business Logic, or Application Logic + +Our Controllers are the "traffic cop" between our Models and our Views. Based on the incoming request, each controller method knows precisely which Model(s) it needs to utilize to fetch or write data, and will generally hand that data off to a View for presentation. + +Controllers should limit their database actions to very simple lookups, or creation of a resource. A controller should not do very much data manipulation, that "data logic" is the role of the Model. Likewise, the controller should pre-fetch as much data as possible so the View does not call Class methods from the Models. + +### Experiment + +- Add a new route and view so that the user can successfully visit `localhost:3000/easteregg` and see a new view of your choice. +- Add a new route so that the user can go to `localhost:3000/showmethetasks` and be redirected to all of the tasks. + +NOTE: For task 2, You should not have to create a new view. + +**Let’s also quickly talk about why the 2nd path isn’t a good idea.** + +### Recap + +- What does MVC stand for? +- What are the "logic responsibilities" for each part of the MVC pattern? +- How is data passed through the MVC pattern? +- What is the difference between `<%= %>` and `<% %>`?