使ったコマンド
$ rails new プロジェクト名
$ rails generate scaffold テーブル名 カラム:データ型
$ rake db:migrate
$ rails console #または rails c
$ rails server #または rails
$ rails -h #railsコマンドのヘルプ
$ rails generate -h #rails generateコマンドのヘルプ
$ rails generate scaffold -h #rails generate scaffoldコマンドのヘルプ
$ rake -T #rakeで実行できるタスクの一覧
$ rake routes
例えば、リレーションがこんな風だとします。(同じキャラクターが他のアニメにも出てることは考えないでおきます。)
アニメ 1
: 多
キャラクター
URLはこんな風にします。
http://example.com/animes/1/characters
animes/1の”1”の部分は、Animeテーブル内での通し番号 = idです。
(もし、URLのidの部分を”TIGER & BUNNY”とか名前にしたいという方には、こちらのgemをどうぞ。 つ gem friendly_id)
これを実現するためには、リレーション(データベースに関する設定)とURLの設定が、それぞれ個々に必要です。
それをこれからお話します。
config/routes.rbを編集します。
例)http://example.com/animes/1/characters
resources :characters
resources :animes do #編集
resources :characters #追記
end #追記
animesの後ろにつながる部分をdo~endの中に書きます。元々あったresources :charactersは後で使うので残しておきます。
そうして、rake routesコマンドでURLの出来を確認してみてください。
$ rake routes
Prefix Verb URI Pattern Controller#Action
characters GET /characters(.:format) characters#index
POST /characters(.:format) characters#create
new_character GET /characters/new(.:format) characters#new
edit_character GET /characters/:id/edit(.:format) characters#edit
character GET /characters/:id(.:format) characters#show
PATCH /characters/:id(.:format) characters#update
PUT /characters/:id(.:format) characters#update
DELETE /characters/:id(.:format) characters#destroy
anime_characters GET /animes/:anime_id/characters(.:format) characters#index
POST /animes/:anime_id/characters(.:format) characters#create
new_anime_character GET /animes/:anime_id/characters/new(.:format) characters#new
edit_anime_character GET /animes/:anime_id/characters/:id/edit(.:format) characters#edit
anime_character GET /animes/:anime_id/characters/:id(.:format) characters#show
PATCH /animes/:anime_id/characters/:id(.:format) characters#update
PUT /animes/:anime_id/characters/:id(.:format) characters#update
DELETE /animes/:anime_id/characters/:id(.:format) characters#destroy
animes GET /animes(.:format) animes#index
POST /animes(.:format) animes#create
new_anime GET /animes/new(.:format) animes#new
edit_anime GET /animes/:id/edit(.:format) animes#edit
anime GET /animes/:id(.:format) animes#show
PATCH /animes/:id(.:format) animes#update
PUT /animes/:id(.:format) animes#update
DELETE /animes/:id(.:format) animes#destroy
どうですか?animesの後ろにcharactersが付いたURLがありますね。do~endで囲ったものが後ろに付いてくれます。また、do~endで囲ったほうのanimes単体のURLも作ってくれます。resources :charactersのように1行だけだと、そのテーブル単体のURLができます。
このように、URLをつなげるときは理論上do~endでどんどん中に囲んでいけばOKですが、あまり長いURLはお行儀がわるいのでテーブル名2つ分ぐらいまでにしておきましょう。
app/models以下のファイルを編集します。
例)アニメ 1
: 多
キャラクター
anime.rb
class Anime < ActiveRecord::Base
has_many :characters #追記
end
character.rb
class Character < ActiveRecord::Base
belongs_to :anime #追記
end
英語のように読めばわかりやすいと思います。
(複数形)
をたくさんもっている。(単数形)
に属している。DBにデータがない状態では特に確認する方法がないので、このまま次に進みます。
ここまでできたら、リレーションがあるリンクをページ上に作っていきましょう。
まずは、リンクの設定手順の確認です。
new_anime GET /animes/new(.:format) animes#new
“/animes/new”が、出来上がりのURL。”new_anime”が、html.erbに書くpath。
app/views/animes/index.html.erb
<%= link_to 'New Anime', new_anime_path %>
link_toの記述に”new_anime”を”_path”につなげて書くだけ。
ここまでいいですか?
では、例題です。
例)とあるアニメ詳細ページ /animes/:id に、キャラクター登録ページ /animes/:anime_id/characters/new へのリンクを貼る
rake routesで確認します。
new_anime_character GET /animes/:anime_id/characters/new(.:format) characters#new
また、URLとhtml.erbとの関係は以下のようになります。
URI Pattern Controller#Action views
/characters(.:format) characters#index app/views/characters/index.html.erb
/characters(.:format) characters#create -
/characters/new(.:format) characters#new app/views/characters/new.html.erb, _form.html.erb
/characters/:id/edit(.:format) characters#edit app/views/characters/edit.html.erb, _form.html.erb
/characters/:id(.:format) characters#show app/views/characters/show.html.erb
/characters/:id(.:format) characters#update -
/characters/:id(.:format) characters#update -
/characters/:id(.:format) characters#destroy -
アニメ詳細ページに該当するhtml.erbは、app/views/animes/show.html.erbです。ここに以下のリンクを追加します。
<%= link_to 'New Character', new_anime_character_path(@anime) %>
“_path”の後ろに、URLの:anime_idのネタとなる@animeを渡してください。
この@animeは、アニメ詳細ページを呼び出すapp/controllers/animes_controller.rbから来ています。rake routesコマンドで表示されたController#Actionの部分で、どこがどう呼ばれるのか確認してみてください。
animes_controller.rb
class AnimesController < ApplicationController
before_action :set_anime, only: [:show, :edit, :update, :destroy]
・・・
# GET /animes/1
# GET /animes/1.json
def show
end
・・・
private
# Use callbacks to share common setup or constraints between actions.
def set_anime
@anime = Anime.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def anime_params
params.require(:anime).permit(:name)
end
end
Rubyぽくなってきましたが、焦らなくても大丈夫です。すべては設定だと思ってください。
def~endで囲まれたところがそれぞれ、controllerのactionと呼ばれる部分です。
今回該当するdef show~endの中には何もありません。でも、2行目にbecore_action(というコールバック)で:set_anime(メソッド)を実行します。いつ実行するのか、only: [:show …]のactionのときです。
そうすると、privateの下にあるdef set_anime~endの中には@animeというのがあって、def show~endのとき、この@animeが呼ばれるというわけです。
@animeには、:idを持つanimeの情報がすべて入っています。なので、リンクの”_path”にそのまま渡せばRailsがよしなにしてくれるという訳です。
データを登録するとき、リレーション情報も一緒に登録してしまいましょう。
方法その1:URLからリレーションのidをもらう
例)とあるアニメ詳細ページ /animes/:anime_id からキャラクター登録ページ /animes/:anime_id/characters/new へ移動して登録する
rake routesで/animes/:anime_id/charactors/newがあることを確認しましょう。
そして、以下の編集をします。
app/controllers/characters_controller.rb
def new
@anime = Anime.find(params[:anime_id]) #追記
@character = @anime.characters.new #編集
・・・
end
def create
@anime = Anime.find(params[:anime_id]) #追記
@character = @anime.characters.new(character_params) #編集
・・・
end
controller内でparams[:anime_id]
と書くと、URLの/:anime_idを勝手に参照してくれます。また、@characterに@animeからつないだカタチで値を入れると、@animeとcharacterのリレーション情報を勝手に引き継いでくれます。
便利!
こうすると、キャラクター登録ページでanime情報を表示できるようになり、登録するときにcharacterとの関係も保存されます。
app/views/characters/_form.html.erb
<%= form_for([@anime, @character]) do |f| %> <!--編集(create用URLの作成)-->
・・・
<div class="field">
<%= f.label :anime_id %><br />
<%= @anime.name %> <!--編集(anime情報の表示)-->
</div>
・・・
<% end %>
方法その2:登録フォームのセレクトボックスでリレーションのidをもらう
例)キャラクター登録ページ /characters/new でガンガン登録する
まず、viewでセレクトボックスを用意して、controllerに情報が渡せるようにします。
app/views/characters/_form.html.erb
<%= form_for(@character) do |f| %>
・・・
<div class="field">
<%= f.label :anime_id %><br />
<%= f.select :anime_id, @animes.map{|a| [a.name, a.id]} %> <!--編集(セレクトボックスに変更)-->
</div>
・・・
<% end %>
ちょっとRubyとhtmlなお話。
次に、rake routesで/charactors/newがあることを確認しましょう。そして、以下の編集をします。
app/controllers/characters_controller.rb
def new
@character = Character.new
@animes = Anime.all #追記
・・・
end
def create
@character = Character.new(character_params)
@character.anime_id = params[:character][:anime_id] #追記
・・・
end
params[:character][:anime_id]
と書くと、viewから送られて来た配列をうまい具合に拾ってくれて、データが登録されるというわけです。
便利!
これだけは駆使してできると思います。がんばってください!
$ rails generate model テーブル名 カラム:データ型
$ rake db:migrate
$ rails generate controller コントローラー名s #コントローラー名は複数形で書くこと!
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 License
produced by Minami.rb