This is my first app using Ruby on Rails. Excited to give it a try.
- Had to brew install Ruby to update to a new version that was compatible with Rails
- Had to change my ~/.zshrc to use the Homebrew version of Ruby and not the pre-installed version
- Started following the "Getting Started" tutorial from rubyonrails.org
- after creating a blog with
rails new blogI had to remove the .git directory from blog/- after cd'ing into blog
rm -rf blog/.git- used this stackoverflow as a guide
- for this, we need to create at minimum:
- a route
- maps a request to a controller action
- routes are "rules" written in a Ruby Domain-Specific Language
- a controller with an action
- performs the necessary work to handle the request AND prepares data for the view
- and a view
- displays data in a desired format
- a route
- add route to routes file
config/routes.rb - create
ArticlesControllerandindexactionbin/rails generate controller Articles index --skip-routesbin/railsis the configuration directorygenerate controlleris what generates the controllerArticlesis the name of the controller we madeindexis controller action--skip-routestells the generator to not generate routes as we've already done that ourselves
- the new controller we made is located in
app/controllers/articles_controller.rb- inside the controller is the
indexaction we defined- the
indexaction is empty by default - because it's empty, Rails automatically renders a view that matches the name of the controller and the action
- the
- inside the controller is the
- the new view created by the controller is in
app/views/articles/index.html.erb- any html we put in this file will be rendered at `localhost:3000/articles
- Now, we'll be displaying the same text from '/articles' to the root path
localhost:3000 - In
config/routes.rbwe added a new route:- `root "articles#index"
- This routes the
rootroute to ourindexaction of ourArticlesControllerroothandles the root route"articles#index"specifies theArticlesControllerand theindexaction. Changing either of these would route to a differentcontrolleror a differentaction
Our ArticlesController inherits from ApplicationController
class ArticlesController < ApplicationController- the class after the
<denotes inheritance We do not have to have something likerequire "application_controller"because Application Classes and Modules are available everywhere. We only needrequirecalls for two cases:
- the class after the
- To load files under the
lib/directory - To load gem dependencies that have
require: falsein theGemfile
- To create a model, we'll use a generator commnand again:
bin/rails generate model Article title:string body:textbin/railsis the configuration directorygenerate modelis what generates the modelArticleis the name of our modeltitle:stringtells our db migrations to create a db column calledtitlewith a typestringbody:texttells our db migrations to create a db column calledbodywith a typetext
- This command creates a "migration file" and a "model file"
- migration file:
db/migrate/<timestamp>_create_articles.rb - model file:
app/models/article.rb
- migration file:
class CreateArticles < ActiveRecord::Migration[7.0]
def change
create_table :articles do |t|
t.string :title
t.text :body
t.timestamps
end
end
end
- the call to
create_tablespecifies how thearticlestable should be constructed t.string :titlecreates a column of typestringnamed "title"t.text :bodycreates a column of typetextnamed "body"t.timestampsis created automatically and creates two additional columns:created_atandupdated_at- Rails will manage these columns by itself
Next, run the migration: bin/rails db:migrate
To create an instance of our model and interact with it, we need to use the Rails Console:
bin/rails consoleNow that we're in the console, we can create initialize a newArticleobject:article = Article.new(title: "Hello Rails", body: "I am on Rails!")articleis the variable we're assigning our newArticleobject toArticle.new(...)creates a new instance of theArticleobjecttitle: "Hello Rails"sets thetitlecolumn to the string"Hello Rails"body: "I am on Rails!"sets thebodycolumn to the text"I am on Rails!"IMPORTANT: All we did was initialized the object. At this point, it is only available within the console. We need to callsavein order for it to be saved to our db:article.saveNow, when we typearticlein our console, it will return the Article object we created and assigned to thearticlevariable. To fetch this Article from the db, we can callfindon the model and pass theidas an arguement:Article.find(1)And, when we want to fetch ALL Articles from the db, we can callallon the model:Article.all- This method returns an
ActiveRecord::Relationobject which we can think of as an superpoweredarray- These return objects look very similar when there's only one instance of the model, however the
ActiveRecord::Relationobject is surrounded by brackets[]to denote it's an array
- These return objects look very similar when there's only one instance of the model, however the
In our controller, we'll change our index action to fetch all Articles from our db:
- inside the
indexaction:@articles = Article.allNow, controller instance variables can be accessed by the view. So, we'll change ourviews/articles/indexto the following:
<h1>Articles</h1>
<ul>
<% @articles.each do |article| %>
<li>
<%= article.title %>
</li>
<% end %>
</ul>
This code is a combination of HTML and something called ERB. ERB stands for "Embedded Ruby". In here, are two ERB tags, <% %> and <%= %>
<% %>means "evaluate the enclosed Ruby code"<%= %>means "evaluate the enclosed Ruby code AND output the value it returns" Here's the logic that's happening:
- The browser makes a
GETrequest to our rootlocalhost:3000 - Our Rails appication receives that request
- The Rails router maps the root route to the index action of ArticlesController
- The index action uses the
Articlemodel to fetch all articles in the database - Rails automatically renders the
app/views/articles/index.html.erbview - The ERB code in the view is evaluated to output HTML
- The server sends a response containing the HTML back to the browser
- Create new route: `get "/articles/:id", to: "articles#show"
- Add
showaction to controller:
def show
@article = Article.find(params[:id])
end
- Create
showview:app/views/articles/show.html.erbwith contents:
<h1><%= @article.title %></h1>
<p><%= @article.body %></p>
- Link each article's title in
app/views/articles/index.html.erbto its detail page:
<h1>Articles</h1>
<ul>
<% @articles.each do |article| %>
<li>
<a href="/articles/<%= article.id %>">
<%= article.title %>
</a>
</li>
<% end %>
</ul>
test