before_action

毎回行う処理はまとめて記述できる

例えば、show,edit,update,destoryアクションで毎回同じ処理を書いていたとする。
このような場合はrailsのDRYの精神に基づいて無駄を省いていく。

before_action

これはアクションを実行する前に必ず実行してくれる関数。今回は以下のような処理が複数あったのでまとめてみた。

@project = Project.find(params[:id])

この処理をbefore_actionにかく。

before_action :set_project,only:[:show,:edit,:update,:destroy]

set_projectという関数を毎回実行する。onlyオプションをつけることで、指定したアクションの前に実行される。
set_projectはprivate関数として定義し、その関数内にまとめたい処理を書いておけばOK

印象的なモノクロ写真の作り方

befor

f:id:nm777taka:20140314162314j:plain

after

f:id:nm777taka:20140314162349p:plain

作り方

  • 白黒調整レイヤー作成(プリセットを暗く)
  • レベル補正調整レイヤー作成(コントラストなどをいい感じにいじる)
  • 新規レイヤー作成(shift+control+n)
  • 描画モードをスクリーン、50%の中間色で塗りつぶし
  • スマートオブジェクトに変換
  • ノイズフィルタ
  • ぼかし(ガウス)フィルタ
  • 今作ったレイヤーの不透明度を70くらいに
  • トーンカーブ調整レイヤー作成
  • レッドをちょっとあげて、ブルーを少し下げることでセピアっぽさを表現
  • 完成!
レイヤーはこんな感じ

f:id:nm777taka:20140314163151p:plain

Destroyアクション(削除)

モデルを削除する

とりあえず、indexにリンクをつくる。
<%=rink_to "[Delete]", project_path(project.id), method: :delete, data:{confirm:"are you sure?"} %>

いつもと違うのは、methodと確認用のアラートが追加されている。
methodにdeleteを設定することで、destroyアクションを行えるようになる。data:{confirm:""}は確認用アラートのおまじない。

Destroyアクション
def destory
  @project = Project.find(params[:id])
  @project.destroy
  redirect_to projects_path

削除対象のモデルを取得して、destoryすることで削除することができる。削除したらindexにリダイレクト。

以上でCRUDの全てのアクションを実装できた。

EditとUpdateアクション

編集(editアクション)

newで作ったモデルを編集するためには、editアクションを実行する。

edit用ページへのリンク(index.html.erb)
<%= link_to "[Edit]", edit_project_path(project.id) %>

編集対象のモデルのidを一緒に渡す必要がある。

editアクション
def edit
  @project = Project.find(params[:id]);
end
editのViewを作る

editのviewはnewと同様にフォームとボタンがある。railsのDRYに沿って、共通部分は共通化していく。

パーシャル

新たに_form.html.erbというファイルを作る。これがパーシャルというもので、ここにformのコードを書いておく。そうするとeditとnewのコードはこんな感じに。パーシャルとして使う場合のファイルの命名規則は_アンダーバーから始まること。

<%= render 'form' %>

更新(Update)

editの画面でsubmitを押した時の処理を書いていく。

updateアクション
def update
 @project = Project.find(params[:id])
 if @project.update(project_params)
    redirect_to projects_path
 else
    render 'edit'
 end 
end

編集したモデルを取得して、updateでモデルを更新する。その際に、newの時と同様にフィルタリングをやっておく。project_paramsでvalitation。saveの時と同様に、update時にvalitationされるっぽい。

これで、Create Read Updateまで完成。あとは削除

Newアクション(新規作成)

新規作成の流れ

newアクションとそれに対応するviewにフォームを設置。フォームからの入力をPOSTでprojectsが受け取り、createアクションを実行するという流れ。

コントローラー(newアクション)

def new
  @project = Project.new
end

フォームView(new.html.erb)

<h1>Add New</h1>
<%= form_for @project do |f| %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
フォームの作成

form_forでフォームの開始と終了タグを生成できる。

ラベル作成

f.label

テキストフィールド作成

f.text_field

サブミットボタン

f.submit

データの保存

projectsにpostしてcreateアクションを起こす流れ。submitボタンを押した段階でpostされる...?
保存する仕組みとvalidation

createアクション
def create
 @project = Project.new(project_params)
 if @project.save
   redirect_to projects_path
 else
   render 'new'
 end 
end

private
 def project_params
   params[:project].permit(:title)
 end
end
フィルタリング

project_paramsというプライベートメソッドでフィルタリングをする。newアクションで渡ってきたprojectのtitleだけを許可するみたいな感じ。昔はこんなことしなかったみたいだけど、最近はセキュリティーを高めるために必要とのこと。お決まりの書き方。

Validation

フォームからなにも入力しなくても新しいモデルが作れてしまう。なので、適切な形でデータを保存できるようにvalidateというものをする。

project.rb(モデル)を編集
class Project < ActiveRecord::Base
validates :title, presence: true
end

対象はtitle、ルールはそれがあるかどうかを判定するpresenceを指定する。
@~.saveを実行した段階でvalidationが実行されるので、if文をsave部分に追加する。
そして、エラー入力があった場合は画面遷移させたくないので、falseだった場合にrenderでnewを指定することで、画面遷移せず同じ画面にとどまる。

エラーメッセージの表示(newのviewをいじる)
<% if @project.errors.any? %>
<%= @project.errors.inspect %>

@project.errorsにエラーが格納されているので、if文でerrorがあるかどうか判定する。あった場合に、errosに格納されている内容をメッセージとして表示する。inspectはエラーメッセージをそのまま表示する。一旦、inspectでどんな内容か確かめ、必要な部分だけを抽出してあげるという流れ。f:id:nm777taka:20140311110926p:plain
内容を見ると、titleがキーで、メッセージ配列の0番目にデフォルトメッセージが入っているので、これを表示してあげる。

<%= @project.errors.messages[:title][0] %>
メッセージを変える

model.rbでpresenceを設定したが、いくつでもルールを追加できるし、メッセージも自由に作ることができる。

validates :title, 
	presence: {message: "入力してください"},
	length: {minimum:3,message:"3文字以上!"}

新たにlengthという文字数指定を追加した。
因にmessage:""はシンボルをキーとして使う表記法みたい。ハッシュの書き方なのかなーrubyやってないからよく分からん。

とまあ、このな感じでフォーム作成→検証→保存の流れを作成した。

Showアクション(詳細表示)

Modelの詳細を表示する

Modelにはtitle属性をつけ、index_viewで一覧表示させた。そのmodelの各要素の詳細を表示するアクションShowを作っていく。

indexからのリンクをはる(index.html.erb)

<%= link_to @projects.title , project_path(project.id) %>

rake routesで全体像を見てみると、projectはパラメータを必要とし、showアクションを実行することが分かる。idはmigrateした段階で勝手に作られるものの一つ(あとはタイムスタンプとか)。テーブルでいうどこの列かを示すものだと思う。

showアクション

def show
  @project = Project.find(params[:id])

find関数を使って、指定したid(列)の要素をとってくる。
URLで渡ってきた数字はparamsに格納される。:idはシンボルでURIで指定されているもの。

show のためのviewを作る

<h1><%= @project.title %></h1>

idで指定した要素のtitleを表示する。

共通テンプレート

共通のテンプレートを編集する

場所:view/layout

<!DOCTYPE html>
<html>
<head>
  <title>Mebuy</title>
  <%= stylesheet_link_tag    "application", media: "all", "data-turbolinks-track" => true %>
  <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
  <%= csrf_meta_tags %>
</head>
<body>

<%= image_tag "logo.png" %>
<%= yield %>
<%= link_to "HOME",projects_path %>

</body>
</html>

yieldの部分に各view独自の構造が挿入される形。

画像を表示
  • イメージタグヘルパーと使うと楽(rails)
<%= image_tag "logo.png" %>

このタグはassets/imagesフォルダにある画像を参照してくれるので、必要な画像はこのフォルダに突っ込んどく。イメージタグ書くより遥かに楽ちん♩

リンク

これもヘルパーが用意されている。

<%= link_to "HOME", projects_path %>

カンマより右側はファイルのパスを表している。rake routesで表示されるあれ!
f:id:nm777taka:20140311012550p:plain
左側に書いてある名前_pathで真ん中に表示されているURIに変換してくれる!便利!