$ rvm list
- show currently installed Rubies
$ rvm install 2.3.1
$ rvm use --default 2.3.1
- use most recent
Install the Rails gem if you haven't done so before
$ gem install rails
Generate a new Rails app w/ Postgres support
$ bin/rails new my_app --database=postgresql
Initialize the database
$ bin/rails db:create
Start the Rails server
$ bin/rails s
Add this to any view to enable a Rails console in the browser:
<% console %>
Use the interactive Rails console in your terminal application to run Rails code, inspect your database etc.
$ bin/rails console
E.g. try out the pluralize helper:
> helper.pluralize(3, 'mouse')
> helper.number_to_currency(1.50)
> helper.truncate("Iron Man", length: 7)
All Rails Helpers available here
Open the DB Console, from which you can interact with your database using your database's regular commands:
$ bin/rails dbconsole
Show environment variables:
$ env
Create a route that maps a URL to the controller action
# config/routes.rb
get 'welcome' => 'pages#home'
Shorthand for connecting a route to a controller/action
# config/routes.rb
get 'photos/show'
# The above is the same as:
get 'photos/show', :to 'photos#show'
get 'photos/show' => 'photos#show'
Automagically create all the routes for a RESTful resource
# config/routes.rb
resources :photos
HTTP Verb | Path | Controller#Action | Used for |
---|---|---|---|
GET | /photos | photos#index | display a list of all photos |
GET | /photos_new | photos#new | return an HTML form for creating a new photo |
POST | /photos | photos#create | create a new photo |
GET | /photos/:id | photos#show | display a specific photo |
GET | /photos/:id/edit | photos#edit | return an HTML form for editing a photo |
PATCH/PUT | /photos/:id | photos#update | update a specific photo |
DELETE | /photos/:id | photos#destroy | delete a specific photo |
Create resources for only certain actions
# config/routes.rb
resources :photos, :only => [:index]
# On the flip side, you can create a resource with exceptions
resources :photos, :except => [:new, :create, :edit, :update, :show, :destroy]
Create a route to a static view, without an action in the controller
# config/routes.rb
# If there's a file called 'about.html.erb' in 'app/views/photos', this file will be
# automatically rendered when you call localhost:3000/photos/about
get 'photos/about', to: 'photos#about'
Reference: http://guides.rubyonrails.org/routing.html
Generate a new controller
Note: Name controllers in Pascal case and pluralize
$ bin/rails g controller Photos
Generate a new controller with default actions, routes and views
$ bin/rails g controller Photos index show
Rails code | Returns |
---|---|
User.all | [array of all users] |
User.find(1) | User with primary key of 1 |
User.find([1, 10]) | Users 1 and 10 |
Reference: http://guides.rubyonrails.org/action_controller_overview.html
Generate a model and create a migration for the table
Note: Name models in Pascal case and singular
$ rails g model Photo
Generate a model and create a migration with table columns
$ rails g model Photo path:string caption:text
The migration automatically created for the above command:
class CreatePhotos < ActiveRecord::Migration
def change
create_table :photos do |t|
t.string :path
t.text :caption
t.timestamps null: false
end
end
end
Reference: http://guides.rubyonrails.org/active_model_basics.html
Migration Data Types
:boolean
:date
:datetime
:decimal
:float
:integer
:primary_key
:references
:string
:text
:time
:timestamp
When the name of the migration follows the format AddXXXToYYY
followed by a list of columns, it will add those columns to the existing table
$ rails g migration AddDateTakenToPhotos date_taken:datetime
The above creates the following migration:
class AddDateTakenToPhotos < ActiveRecord::Migration[5.0]
def change
add_column :photos, :date_taken, :datetime
end
end
You can also add a new column to a table with an index
$ rails g migration AddDateTakenToPhotos date_taken:datetime:index
The above command generates the following migration:
class AddDateTakenToPhotos < ActiveRecord::Migration[5.0]
def change
add_column :photos, :date_taken, :datetime
add_index :photos, :date_taken
end
end
The opposite goes for migration names following the format: RemoveXXXFromYYY
$ rails g migration RemoveDateTakenFromPhotos date_taken:datetime
The above generates the following migration:
class RemoveDateTakenFromPhotos < ActiveRecord::Migration[5.0]
def change
remove_column :photos, :date_taken, :datetime
end
end
Scaffolding is great for prototypes but don't rely too heavily on it: http://stackoverflow.com/a/25140503
$ rails g scaffold Photo path:string caption:text
$ rake db:migrate
One book belongs to an author. An author has many books.
belongs_to
creates an author_id
column in the table.
# Models:
class Author < ApplicationRecord
has_many :books, dependent: :destroy
end
class Book < ApplicationRecord
belongs_to :author
end
The corresponding migration might look like this:
class CreateBooks < ActiveRecord::Migration[5.0]
def change
create_table :authors do |t|
t.string :name
t.timestamps
end
create_table :books do |t|
t.belongs_to :author, index: true
t.datetime :published_at
t.timestamps
end
end
end
One CEO has one company. There is no need to declare that the company belongs_to the Ceo - this is obvious.
In this case, has_one creates a foreign key of ceo_id on on the company model (as though the company has been declared to belong_to
a Ceo)
# Model
class Ceo < ApplicationRecord
has_one :company
end
# Migration
class CreateCeo < ActiveRecord::Migration[5.0]
def change
create_table :ceos do |t|
t.string :name
t.timestamps
end
create_table :company do |t|
t.belongs_to :ceo, index: true
t.string :name
t.timestamps
end
end
end
Seeding can be done in seed.rb
or on the Rails console.
Delete record to avoid duplication:
Gallery.delete_all
Creating records that have relationships:
area_show = Gallery.create(title: 'Area Show, May 2016')
Images belong to a gallery:
area_show.images << Image.new(path: "gallery_photos/pic1.jpg")
e.g.
$ bin/rails db:create
from jacopretorius.net
-
db:create Creates the database for the current RAILS_ENV environment. If RAILS_ENV is not specified it defaults to the development and test databases.
-
db:create:all Creates the database for all environments.
-
db:drop Drops the database for the current RAILS_ENV environment. If RAILS_ENV is not specified it defaults to the development and test databases.
-
db:drop:all Drops the database for all environments.
-
db:migrate Runs migrations for the current environment that have not run yet. By default it will run migrations only in the development environment.
-
db:migrate:redo Runs db:migrate:down and db:migrate:up or db:migrate:rollback and db:migrate:migrate depending on the specified migration. I usually run this after creating and running a new migration to ensure the migration is reversable.
-
db:migrate:up Runs the up for the given migration VERSION.
-
db:migrate:down Runs the down for the given migration VERSION.
-
db:migrate:status Displays the current migration status.
-
db:migrate:rollback Rolls back the last migration.
-
db:version Prints the current schema version.
-
db:forward Pushes the schema to the next version.
-
db:seed Runs the db/seeds.rb file.
-
db:schema:load Loads the schema into the current environment’s database.
-
db:schema:dump Dumps the current environment’s schema to db/schema.rb.
-
db:setup Runs db:create, db:schema:load and db:seed.
-
db:reset Runs db:drop and db:setup.
-
db:migrate:reset Runs db:drop, db:create and db:migrate.
-
db:test:prepare Check for pending migrations and load the test schema. (If you run rake without any arguments it will do this by default.)
-
db:test:clone Recreate the test database from the current environment’s database schema.
-
db:test:clone_structure Similar to db:test:clone, but it will ensure that your test database has the same structure, including charsets and collations, as your current environment’s database.
Creating a path helper for a route
# Creating a path helper for a route
get '/photos/:id', to: 'photos#show', as: 'photo'
# app/controllers/photos_controller.rb
@photo = Photo.find(17)
# View for the action
<%= link_to 'Photo Record', photo_path(@photo) %>
Path helpers are automatically created when specifying a resource in config/routes.rb
# config/routes.rb
resources :photos
HTTP Verb | Path | Controller#Action | Named Helper |
---|---|---|---|
GET | /photos | photos#index | photos_path |
GET | /photos/new | photos#new | new_photo_path |
POST | /photos | photos#create | photos_path |
GET | /photos/:id | photos#show | photo_path(:id) |
GET | /photos/:id/edit | photos#edit | edit_photo_path(:id) |
PATCH/PUT | /photos/:id | photos#update | photo_path(:id) |
DELETE | /photos/:id | photos#destroy | photo_path(:id) |
Access images in the app/assets/images
directory like this:
<%= image_tag "rails.png" %>
Access images stored in the public folder: (e.e. public/gallery_photos/haf1.jpg)
<%= image_tag("/gallery_photos/haf1.jpg") %>
Within views, link to JavaScript and CSS assets
<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag "application" %>
<!-- Filenames are fingerprinted for cache busting -->
<link href="/assets/application-4dd5b109ee3439da54f5bdfd78a80473.css" media="screen"
rel="stylesheet" />
<script src="/assets/application-908e25f4bf641868d8683022a5b62f54.js"></script>
Reference: http://guides.rubyonrails.org/asset_pipeline.html
Bind a form to a model for creating/updating a resource
Use this method if you're using strong params to protect against mass assignment
# app/controllers/photos_controller.rb
def new
@photo = Photo.new
end
# ERB view
<%= form_for @photo, url: {action: "create"}, html: {class: "nifty_form"} do |f| %>
<%= f.text_field :path %>
<%= f.text_area :caption, size: "60x12" %>
<%= f.submit "Create" %>
<% end %>
<!-- HTML output -->
<form accept-charset="UTF-8" action="/photos/create" method="post" class="nifty_form">
<input id="photos_path" name="photo[path]" type="text" />
<textarea id="photos_caption" name="photo[caption]" cols="60" rows="12"></textarea>
<input name="commit" type="submit" value="Create" />
</form>
Create a form with a custom action and method
<%= form_tag("/search", method: "get") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Search") %>
<% end %>
<form accept-charset="UTF-8" action="/search" method="get">
<input name="utf8" type="hidden" value="✓" />
<label for="q">Search for:</label>
<input id="q" name="q" type="text" />
<input name="commit" type="submit" value="Search" />
</form>
#### Translate Ruby data to a JavaScript variable for use in a script:
<script> var chartData = <%= raw @chart_data.to_json %>; </script>
Show the console:
<% console %>