読者です 読者をやめる 読者になる 読者になる

railstutorial.jp 7章メモ

rails
  • テーマ
    • フォーム

paramsでデバッグ

<%= debug(params) if Rails.env.development? %>
  • 環境
    • test
    • development
    • production (Herokuは常にコレ)

パラメータを指定して起動

$ rails console test
$ rails server --environment production
$ rake db:migrate RAILS_ENV=production

Herokuのリモートコンソール

$ heroku run console

RESTfulなリソースの設定 config/routes.rb

resources :users

params[:id]に/users/1の1が入ってくる
params[:id]は文字列だが、findに渡すと数値に変換される

  def show
    @user = User.find(params[:id])
  end

factorygirlのインストール。test環境のみ。

group :test do
  gem 'factory_girl_rails'
end
$ bundle install

spec/factories.rb

FactoryGirl.define do
  factory :user do
    name     "Michael Hartl"
    email    "michael@example.com"
    password "foobar"
    password_confirmation "foobar"
  end
end

テストの中で、上で定義した:userが使用できるようになる

let(:user) { FactoryGirl.create(:user) }

genarateもできた
specやtest配下は自動的にロードされるのかな?

$ rails generate factory_girl:model User
      create  test/factories/users.rb

specやtest配下は自動的にロードされるのかな?

config/environments/test.rbにtestの環境変数が設定できる
ここではtestの実行速度を速くしたいのでbcryptのコスト関数を下げる

  ActiveModel::SecurePassword.min_cost = true

Gravatarの利用
GravatarのURL(https://secure.gravatar.com/avatar/ID)はMD5ハッシュを用いてユーザーのメールアドレスをハッシュ化している

Digest::MD5::hexdigest(email.downcase)

モデルのupdate_attributesメソッドで一部データの更新

rails c
user = User.first
user.update_attributes(name: "Example User",
  email: "example@railstutorial.org",
  password: "foobar",
  password_confirmation: "foobar")

dbの変更を全てリセットしてやり直す

rake db:reset

Capybaraの文法

visit signup_path
fill_in "Name",         with: "Example User"
fill_in "Email",        with: "user@example.com"
fill_in "Password",     with: "foobar"
fill_in "Confirmation", with: "foobar"
click_button "Create my account"

件数の取得

User.count

Rspecメソッド - expectへのブロックを渡し - to/not_to - change

expect { click_button "Create my account" }.not_to change(User, :count)

これは次と同じ

initial = User.count
click_button "Create my account"
final = User.count
expect(initial).to eq final

フォームの作成 form_forヘルパーメソッド

# @userはUserオブジェクト
<%= form_for(@user) do |f| %>

  <%= f.label :name %>
  <%= f.text_field :name %>

  <%= f.label :email %>
  <%= f.text_field :email %>

  <%= f.label :password %>
  <%= f.password_field :password %>

  <%= f.label :password_confirmation, "Confirmation" %>
  <%= f.password_field :password_confirmation %>

  <%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
<% end %>

rspecでdescriptionに対応するテストを実行する
ネストしたdescribeの引数文字列は連結するっぽい

$ rspec spec/requests/user_pages_spec.rb -e "signup page"

signup_pathがないというエラーが出る。。。

Failures:

  1) User pages signup page
     Failure/Error: before { visit signup_path }
     NameError:
       undefined local variable or method `signup_path' for #<RSpec::ExampleGroups::UserPages::SignupPage:0x007ffbd0fdac18>
     # ./spec/requests/user_pages_spec.rb:32:in `block (3 levels) in <top (required)>'

  2) User pages signup page
     Failure/Error: before { visit signup_path }
     NameError:
       undefined local variable or method `signup_path' for #<RSpec::ExampleGroups::UserPages::SignupPage:0x007ffbd0f94a60>
     # ./spec/requests/user_pages_spec.rb:32:in `block (3 levels) in <top (required)>'

spec/requests/user_pages_spec.rbに以下書いたら動いた。

require 'rails_helper'
include ApplicationHelper

フォームの値はparamsとしてControllerに渡る
user[name] や user[email] -> params[:user]

strong parameters機能
このままPOSTするとActiveModel::ForbiddenAttributesError in UsersController#create となる

マスアサインメントの脆弱性

@user = User.new(params[:user])

は以前のRailsで動いた。user[admin]='1'とかを強制的に渡されると危険。
Rails4からは、paramsをそのまま渡すとエラー

Controllerでstrong parametersの利用を推奨

params.require(:user).permit(:name, :email, :password, :password_confirmation)

コントローラ間で共通のパーシャル
app/views/shared/に置く

user.errors.count
user.errors.empty?
user.errors.any?

pluralizeメソッドでいい感じに単数形/複数形にする

include ActionView::Helpers::TextHelper
pluralize(5, "error")

redirect_to でリダイレクト

# user_urlへリダイレクトすることと同様
redirect_to @user

エラーでrspecが通らない。謎。

Failure/Error: let(:user) { FactoryGirl.create(:user) }
ActiveRecord::RecordInvalid:
  Validation failed: Email has already been taken

test:prepareしなさいと言われたのでやってみたがないらいしい。

$ rake test:prepare
rake aborted!
Don't know how to build task 'test:prepare'

(See full trace by running task with --trace)

db:test:prepareもRails4.1からdeprecatedらしい。

$ rake db:test:prepare
WARNING: db:test:prepare is deprecated. The Rails test helper now maintains your test schema automatically, see the release notes for details.

以下でやっとテストが通った

$ rake db:create db:migrate RAILS_ENV=test
$ rake spec

特殊な変数flash

flash[:success] = "Welcome to the Sample App!"

Railsでは自動的にシンボルを文字列に変換してテンプレートに渡すようになっている

本番でSSLをつかう config/environments/production.rb

config.force_ssl = true