bundle initしてGemfileを作成する。
作成されたGemfileのgem railsをアンコメントする。
最終的に作成されるGemfileは以下のようになります。
source "https://rubygems.org"
git_source ( :github ) { |repo_name | "https://github.com/#{ repo_name } " }
gem "rails"
それでは、Railsプロジェクトを作成します。
bundle exec rails new . -d postgresql
# Gemfile がコンフィリクトを起こすので、エンターキーで上書きを許可する
rails g scaffold <モデル名> <項目名>:<型> ..
rails g controller <コントロール名> <アクション名> ..
rails g model <モデル名> <項目名>:<型> ..
rails g integration_test <インテグレーションテスト名>
rails g migration <マイグレーション名> ..
rails g migration <マイグレーション名> <属性名>:<型>
マイグレーション名をmigration_name_to_model_nameとするとadd_column行が追加され、モデル(model_name)とカラムが追加される
rails d scaffold <モデル名>
rails d controller <コントロール名> <アクション名> ..
rails d model <モデル名>
rails d integration_test <インテグレーションテスト名>
rails d migration <マイグレーション名>
root '<コントローラ名>#<アクション名>'
どノーマル
get static_page/help -> static_page_help_url -> static_page#help
名前付きルート
get /help, to: 'static_page#help' -> help_path -> static_page#help
名前付きルートの別名
get /help, to: 'static_page#help', as: 'helf' -> helf_path -> static_page#help
HTTPリクエスト
URL
アクション
名前付きルート
用途
GET
/users
index
users_path
すべてのユーザーを一覧するページ
GET
/users/1
show
user_path(user)
特定のユーザーを表示するページ
GET
/users/new
new
new_user_path
ユーザーを新規作成するページ (ユーザー登録)
POST
/users
create
users_path
ユーザーを作成するアクション
GET
/users/1/edit
edit
edit_user_path(user)
id=1のユーザーを編集するページ
PATCH
/users/1
update
user_path(user)
ユーザーを更新するアクション
DELETE
/users/1
destroy
user_path(user)
ユーザーを削除するアクション
assert: 結果がtrueになることを主張する
assert_not: 結果がfalseになることを主張する
assert_response: 特定のステータスコードを持っていることを主張する
assert_response :success -> 200-299
assert_response :redirect -> 300-399
assert_response :missing -> 404
assert_response :error -> 500-599
assert_response 402 -> 402
assert_select: タグの検証
assert_template: 特定のテンプレートファイルが返されることを主張する
assert_template 'static_page/home'
assert_equal: 期待される値と実際の値を比較する
assert_equal <期待される値> <実際の値>
assert_no_difference <更新対象> <更新処理ブロック>: 更新対象が変更されないことを主張する
assert_no_difference User.count { post users_path, params: { user: { name: "", email: "", password: "bar", password_confirmation: "foo" } } }
assert_difference <更新対象> <更新件数> <更新対象ブロック>: 更新対象が変更されることを主張する、更新件数はオプションだが、更新後に影響を受ける件数を表す。createやdestroyのテストに用いる
assert_redirected_to: リダイレクト先が正しいかをチェックする。follow_redirect!の前に呼び出す
assert_empty: 空かどうかを検証
assert_not_empty: 空以外かどうかを検証
assert_nil: nilを検証
rails test: 全てテスト
rails test:models: モデルのテストのみ
rails test:controllers: コントローラテストのみ
rails test:integration: インテグレーションテストのみ
テスト内部でassignsメソッドを使用することでインスタンス変数にアクセスすることができる。
assigns ( :user ) . remember_token
マイグレーション
元に戻したい
最初の状態に戻したい
rails db:migrate VERSION=0
add_index :<models>, :<attr>, <属性>: インデックス追加
before_saveコールバック: オブジェクトが保存される直前、オブジェクトの作成時や更新時に呼び出される
before_createコールバック: オブジェクトが作成される時に呼び出される
presence: 必須入力を検証する(presence: true)
format: フォーマットを検証する
format { with: <正規表現> }: フォーマットを正規表現で検証
uniqueness <bool>: 一意性を検証する
uniqueness: { case_sensitive: <bool> }: 大文字を区別するかどうか(false:区別しない)
allow_nil: 引数にtrueを設定するとnilの検証はスキップする(新規作成時は別途検証を行い、更新時は検証を行わないという用途に用いる)
View に render を追加すると引数のファイルの内容をそ部分に追加します。
ファイル名の前にはアンダースコア(_)を入れる必要があります。
以下の例では、app/view/layouts/_shim.html.erbが読み込まれます。
< head >
< %= render 'layouts/shim' %>
</ head >
app/assets: 現在のアプリケーション固有のアセット
lib/assets: あなたの開発チームによって作成されたライブラリ用のアセット
vendor/assets: サードパーティのアセット
次の行はapp/assets/stylesheets ディレクトリ中の全てのCSSファイルがアプリケーションCSSのように扱われる。
また、次の行はCSSの読み込みシーケンスの中で、application.css自身もその対象に含める。
プリプロセッサエンジンは繋げて実行することができる。
例えば、foobar.js.erb.coffeeであれば、CoffeeScriptが実行されたのちERbが実行されます(コードは右から左へ実行される)。
obj.valid?: オブジェクトを検証後正常かを返す
obj.save: オブジェクトを永続化する
Recode.create([Hash]): Hashからオブジェクト作成と永続化する
obj.destroy: オブジェクトをDBから削除する
nRecode.find(Number): idで検索
Recode.find_by([Hash]): 属性で検索する
Recode.find_by_プロパティ名(String): 属性で検索する
Recode.all: モデルの全ての永続化オブジェクトを取得する。オブジェクトはRelationクラスで返ります
Recode.first: 最初のオブジェクトを取得する。
obj.reload: オブジェクトを変更し、保存を行わずにreloadすると、変更が取り消される
obj.update_attributes([Hash]): 属性をHashでオブジェクトを更新する、validationを行う
obj.update_attribute([Hash]): 属性をHashでオブジェクトを更新する、validationを行わない
obj.errors: ActiveModel::Errorsのインスタンスを返す。
obj.errors.full_messages: エラーが発生した属性とメッセージを連結した文字列を返す
Array.empty?: 配列が空であるかを返す
String.empty?: 文字列が空であるかを返す
Array.any?: 配列に要素があるかを返す
redirect_to: 特定のURLにリダイレクトする
redirect_to @user は redirect_to user_url(@user) と等価
render: 引数のビューを描画する
follow_redirect!: 直前のpost内の処理で行われた、リダイレクトで、指定されたリダイレクト先に移動するメソッド(テスト用)
content_tag <タグ名>, <コンテンツ>, <属性>: タグを追加する。文字列エスケープが鬱陶しくなったら使う
cookies: セクション情報をブラウザが閉じても保存され続ける
sesstion: セッション情報を保持する ブラウザが閉じると消える
model.toggle!(:<属性>): boolean型を反転する
Time.zone.now: イムゾーンに元ずいた現在の日時を取得する
provideを用いることで実現できる
個別のView
<% provide ( :title , "Home" ) %>
<h1 >Home </h1 >
レイアウトView
<html >
<head >
<title ><%= yield ( :title ) %></title>
</head >
</html >
"#{ :success } " #> "success"
( 1 ..10 ) . to_a
=> [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ]
( 1 ...10 ) . to_a
=> [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
Gem
Clearance
Authlogic
Devise
CanCan
API
データベースへの変更をコンソール終了時に全てロールバックする。
$ rails console --sandbox
Modelに以下の行を追加する
class User < ApplicationRecord
has_secure_password
end
上記のメソッドを実装すると以下のことができるようになる
セキュアにハッシュ化したパスワードを、データベース内のpassword_digestという属性に保存できるようになる。
2つのペアの仮想的な属性 (passwordとpassword_confirmation) が使えるようになる。また、存在性と値が一致するかどうかのバリデーションも追加される。
authenticateメソッドが使えるようになる (引数の文字列がパスワードと一致するとUserオブジェクトを、間違っているとfalseを返すメソッド) 。
ただし、DBに自動で属性が追加される訳ではないので、自分でpassword_digest属性を追加する要がある。
$ rails generate migration add_password_digest_to_users password_digest:string
また、バリデーションが追加されているので、オブジェクト作成時に値をセットする必要がある。
以下のように、passwordとpassword_confirmationに値をセットする。
@user = User . new ( name : "example name" , email : "[email protected] " ,
password : "foobar" , password_confirmation : "foobar" )
def show
@user = User . find ( params [ :id ] )
debugger # <-
end
Dockerでデバッグするにはattachする(composeのコンソール(docker-compose up)からはサーバーが止まってしまう)
$ docker-compose attach < コンテナ名>
flash[:danger] = "error"とするとフラッシュメッセージを表示できるが、別ページに遷移してもメッセージが表示されたままになる。
flash.now[:danger] = "error"とする必要がある。
SecureRandom.urlsafe_base64はA-Z, a-z, 0-9, "-", "_"のいずれかの文字(64種類)の長さ22のランダムな文字列を返す
ActiveModel::SecurePassword.min_costの部分はテスト時はハッシュ化のコストを高くする必要がないので、最小の値を設定しています。
本番環境では最適なコストが用いられます。
def self . digest ( string )
cost = ActiveModel ::SecurePassword . min_cost ? BCrypt ::Engine ::MIN_COST :
BCrypt ::Engine . cost
BCrypt ::Password . create ( string , cost : cost )
end
以下のコードは生でcookiesに保存される
cookies [ :user_id ] = user . id
以下のコードは署名付きでcookiesに保存される
cookies . signed [ :user_id ] = user . id
以下のコードは署名した後、永続化するしてcookiesに保存される
実際は、20年後に削除される
cookies . permanent . signed [ :user_id ] = user . id
トークンとダイジェストが一致していることを確認する
BCrypt ::Password . new ( password_digest ) . is_password? ( password_token )
$ rails db:fixtures:load
$ rails c
> michael = User.find ActiveRecord::FixtureSet.identify(' michael' )
_model.html.erbというパーシャルから<%= render @models %>とすれば@modelsの中身を順に開いて、_model.html.erbに渡されます。
以下を次のようにリファクタリングすることができる
<% @users.each do |user| %>
<%= link_to user.name, user %>
<% end %>
< li >
<%= link_to user . name , user %>
</ li >
<% @users.each do |user| %>
<%= render user %>
<% end %>
bcrypt: ハッシュ関数を使用するために使う。パスワードのハッシュ化に用いる
guard: ファイルの変更を検出してタスクを自動実行する
guard-minitest: guardとminitestの親和性をとる
faker: 実際に存在しそうなテストデータを作ることができる。ユーザー名やメールアドレスなどを得ることができる
will_paginate: ページネーションを提供する。Bootstrapを使用している場合はbootstrap-will_paginateも合わせて用いる
ページリンクを配置したい場所に<%= will_paginate %>を入れる。
will_paginateでページネーションするためにはpaginateの戻り値をviewに渡す必要があります。
コントローラーでModel.paginate(page: params[:page])とすれば、実現できます。
:pageはwill_paginateが自動で渡します。
brew install heroku
heroku login
heroku key:add
Heroku は sqlite に対応していない。今回はプロジェクトを作成する際に、PostgreSQLを使用するように指定して作成する。
rails new < appname> -d postgresql
git init
rails test
git add -A
git commit -m < commit message>
heroku create # この時点で git remote -v に追加される
git push -u heroku master
heroku rake assets:precompile # アセットをコンパイル
アプリケーションを更新する
DB更新を伴う場合は、メンテナンスモードにしてから更新したほうがいい
rails test
git add -A
git commit -m < commit message>
git push
heroku maintenance:on
git push heroku
heroku run rails db:migrate
heroku maintenance:off
!注意!
本番データベースをクリアするにはpg:resetを行う
rails test
git push heroku
heroku pg:reset DATABASE
heroku run rails db:migrate
heroku run rails db:seed
heroku restart
config/puma.rbの中身
workers Integer ( ENV [ 'WEB_CONCURRENCY' ] || 2 )
threads_count = Integer ( ENV [ 'RAILS_MAX_THREADS' ] || 5 )
threads threads_count , threads_count
preload_app!
rackup DefaultRackup
port ENV [ 'PORT' ] || 3000
environment ENV [ 'RACK_ENV' ] || 'development'
on_worker_boot do
# Worker specific setup for Rails 4.1+
# See: https://devcenter.heroku.com/articles/
# deploying-rails-applications-with-the-puma-web-server#on-worker-boot
ActiveRecord ::Base . establish_connection
end
./Procfile の中身、Herokuが内容使用してPumaを起動する
web: bundle exec puma -C config/puma.rb
# 開発環境時にproductionのgemをインストールしない
bundle install --path vendor/bundle --without production
上記のコマンドを実行すると.bundle/configにいかが追加されます。
BUNDLE_WITHOUT : " production"
test環境でApplicationヘルパーのテストを行う
test/test_helper.rbへ以下の行を追加する。
ENV [ 'RAILS_ENV' ] ||= 'test'
..
class ActiveSupport ::TestCase
fixtures :all
include ApplicationHelper
..
end
使用例
pluralize ( @user . errors . count , "error" )
pluralize(1, "error") #> "1 error"
pluralize(2, "error") #> "2 errors"
以下のコードをapplication.html.erbに追加する。
< %= debug(params) if Rails.env.development? %>
puts user . attributes . to_yaml
Heroku アップロード直後に The page you were looking for doesn't exist. が表示される
以下のコマンドを実行する
SCSS でできること
ネスト
a:hoverのように内方するエンティティの継承 -> &:hover
変数($val)
ミックスイン(mixin), @includeを用いる
footer {
..
a {
..
& : hover {
..
}
}
}
上記のSASSは次のようにプリコンパイルされます。
footer {
..
}
footer a {
..
}
footer a : hover {
..
}
ミックスイン機能
@mixin box_size {
box-sizing : border-box;
}
.debug_dump {
width : 100% ;
@include box_size;
}
変数の呼び出し
.field_with_errors {
@extend .has-error ;
.form-control {
color : $state-danger- text; / / extendした.has-error 内の $state-danger- text 使用できる
}
}
flash ようには、4つのスタイルがある(success, info, warning, danger)