http://guides.rubyonrails.org/
$ rails _6.0.3.7_ new …
rails generate model Name field:type
rails generate scaffold Name field:type
id:integer
primary key column is added by default if this isn’t specifiedSuffixes
:uniq
- unique index:index
- non-unique indexWhether a create_table
migration is generated or written by hand, column modifiers can be added to the t.column
lines to further configure the column creation. The most common are:
Writing
def change
create_table :tablename do |t|
t.string :field, null: false, default: ''
t.references :user, null: false, foreign_key: true
t.timestamps
end
end
add_column :todos, :completed_at, :datetime, precision: 6
remove_column :ideas, :quote, :text
add_reference :todos, :category, type: :uuid, null: true, foreign_key: true
add_index :users, :email, unique: true
create_join_table :sources, :tags do |t|
t.index :source_id
t.index :tag_id
end
Running
rails db:setup
rails db:reset
rails db:migrate
rails db:rollback [STEP=N] [VERSION=0]
Outside of a create_table
migration, columns on existing tables can be added, removed, or changed.
change_column
change_column_null
change_column_default
add_foreign_key
remove_foreign_key
add_index
remove_index
belongs_to :model
has_many :models
validates :field, presence: true
Model.create(attributes) # Boolean
Model.create!(attributes) # raises
Model.find(id)
Model.find_by(field: value)
Model.where(field: value)
model.update(attributes) # Boolean
model.update!(attributes) # raises
resources :model
Nesting
Path and module
namespace :admin do
resources :articles # /admin/articles, Admin::ArticlesController
end
Path only
scope module: 'admin' do
resources :articles # /articles, Admin::ArticlesController
end
Module only
scope '/admin/' do
resources :articles # /admin/articles, ArticlesController
end
Path | Helper | HTTP Method | Controller Method |
---|---|---|---|
models | models_path | GET | #index |
POST | #create | ||
models/new | new_model_path | GET | #new |
models/:id | model_path(id) | GET | #show |
PUT/PATCH | #update | ||
DELETE | #destroy | ||
models/:id/edit | edit_model_path(id) | GET | #edit |
before_action :populate_model
def populate_model
@model = Model.find_by(slug: params[:model_slug])
end
params.require(:model).permit(:field, …)
redirect_to path, notice: string
skip_forgery_protection
render plain: "hello world"
render json: object.to_json, status: :something
head :no_content
<%= link_to label, path, method: :delete, data: { confirm: 'Are you sure?' } %>
<%= form_with model: @model, local: true do |f| %>
<%= f.label :field %>
<%= f.text_field :field %>
<% @model.errors.full_messages_for(:field).each do |message| %>
<p><%= message %>
<% end %>
<%= f.submit 'Create' %>
<% end %>
<%= yield :head %>
<% content_for :head do %>
<title>A simple page</title>
<% end %>
https://thoughtbot.com/blog/its-about-time-zones
ActiveSupport::TimeWithZone
supplements Time
so it is fancy
Application time zone configured in config/application.rb
In a Rails app, we have three different time zones:
Time.now
is system timeTime.parse
gives system timeDoing Time.zone
then calling methods on that gives application time instead:
Time.zone.now
Time.zone.parse
https://api.rubyonrails.org/classes/ActiveSupport/Testing/TimeHelpers.html
require 'active_support/testing/time_helpers'
RSpec.describe "whatev" do
include ActiveSupport::Testing::TimeHelpers
#freeze_time
(can take a block)#unfreeze_time
#travel_to
- stubs, so shouldn’t change as the test runsclass EnableUuids < ActiveRecord::Migration[6.0]
def change
enable_extension 'uuid-ossp'
enable_extension 'pgcrypto'
end
end
class CreateTodos < ActiveRecord::Migration[6.0]
def change
create_table :todos, id: :uuid do |t|
# ...
end
end
end
class AddCategoryToTodos < ActiveRecord::Migration[6.0]
def change
add_reference :todos, :category, type: :uuid, foreign_key: true
end
end
https://guides.rubyonrails.org/caching_with_rails.html
config.cache_store = :null_store
config.cache_store = :memory_store
config.cache_store = :file_store
config.cache_store = :redis_cache_store, { url: ENV['REDIS_URL'] } # not TLS
group :production do
gem 'hiredis'
gem 'redis'
end
Rails.cache.fetch('key', expires_in: 12.hours) do
# calculate the value
end
In config/application.rb
:
config.autoload_paths << Rails.root.join('lib')
get "/widgets/#{widget.id}", headers: headers
post '/categories', headers: {'Content-Type' => 'application/json'}, params: body_hash.to_json