Ruby on rails is one of the best full stack web framework, laravel took a lot of inspiration from it. This is my note when i learn rails, hopefully it will be useful for you if you want to learn rails too.
I learn it from this YouTube: https://www.youtube.com/watch?v=B3Fbujmgo60
Rails Command Line
Create new rails application
rails new foodlogGenerate rails CRUD Scaffolding
rails generate scaffold Entry field:type[string,integer,etc] Active record types
:binary
:boolean
:date
:datetime
:decimal
:float
:integer
:primary_key
:string
:text
:time
:timestampOr you can see from rails command line rails generate model -h
Delete generated controller
rails delete controller archivesDon't use
- Do not use
<%=when working with loop use<%instead
Syntax for render partials
Make sure to use <%= when working with one line erb
<%= render "shared/header" %>Working with variable in erb
<% if notice.present? %>
<p class="notification is-link is-light"><%= notice %></p>
<% end %>Link in View
<%= link_to "View all entries", archives_index_path, class: "button is-link is-outlined is-centered" %>Add customization on initialize rails app
You can add custom helper inside folder /config/initializers example time_format.rb
Time::DATE_FORMATS[:nice_date] = "%B %e, %Y"Then we can use it in view like this
<%= DateTime.now.to_s(:nice_date) %>Useful time helper in ruby
Make date more readable for human
<%= time_ago_in_words(model.created_at) %> ago // Logged 3 hour agoDebugging Params in rails
<%= params %>Example value would be like this
{"controller"=>"entries", "action"=>"show", "id"=>"1"}Use do when wrapping link with child elements
<%= link_to entry_path(entry) do %> ...<% end %>Grouping Model Collection
Setup the model first
class Entry < ApplicationRecord
def day
self.created_at.strftime("%b %e, %Y")
end
endQuery on controller
@entries = Entry.all.group_by(&:day)Consume it on the view
<% @entries.each do |day, entries| %>
<% entries.each do | entry | %>
...
<% end %>
<% end %>Model Validation
Define attributes to validate in the model
class Entry < ApplicationRecord
validates :calories, :proteins, :carbohydrates, :fats, :meal_type, presence: true
endDisplay error validation in the form
<%= form_with(model: entry) do |form| %>
<% if entry.errors.any? %>
<div class="message is-danger">
<div class="message-header">
<h2><%= pluralize(entry.errors.count, "error") %> prohibited this entry from being saved:</h2>
</div>
<div class="message-body">
<ul>
<% entry.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
</div>
<% end %>
...
<%end>Updating Data from CLI
Run console
rails consoleGet last entry
entry = Entry.lastUpdate the date to yesterday
entry.created_at = Date.yesterdaySave entry
entry.saveRails Tests
Mock database done in fixtures it create in yaml file.
# tests/fixtures/entries.yml
breakfast:
meal_type: "Breakfast"
calories: 12
proteins: 142
carbohydrates: 101
fats: 11
lunch:
meal_type: "Lunch"
calories: 21
proteins: 311
carbohydrates: 27
fats: 95Run db migration for test
bin/rails db:migrate RAILS_ENV=testThen run the test
rails test test/controllers/entries_controller_test.rbIf you found error ActionView::Template::Error: Permission denied
Go to test/test_helper.rb comment out this line
# parallelize(workers: :number_of_processors, with: :threads)Example test create entry
test "should create entry" do
assert_difference('Entry.count') do
post entries_url, params: { entry: { calories: @entry.calories, carbohydrates: @entry.carbohydrates, fats: @entry.fats, meal_type: @entry.meal_type, proteins: @entry.proteins } }
end
assert_redirected_to entry_url(Entry.last)
endExplanation
postis POST request there is alsoget,patchanddeletemethod requestentries_urlis url pathparamsis request bodyassert_difference('Entry.count')assert to make sure data is inserted to database if delete the assert would beassert_difference('Entry.count', -1)
Run test specific line
rails test test/models/entry_test.rb:4