【Rails】Modelの作成とルーティングと一覧表示まで

2018年4月5日

プログラミングスクールに通いながらお店の口コミサイトを鋭意製作中です。
今日は中核を担うお店のモデル(Shopsテーブル)を作る予定です。

予めお店をいくつかDBに保存しておき、それを一覧表示するところまで進めたいと思います。

ShopsテーブルのDB設計

shopsテーブルのDB設計は以下のように行いました。

【Shopsテーブル】

カラム 意味
id int ショップID
name str ショップ名
y_id str YahooAPIから取得したID
y_uid str YahooAPIから取得したID
y_ido str YahooAPIから取得した緯度
y_keido str YahooAPIから取得した経度
y_address str YahooAPIから取得した住所
y_leadimage str YahooAPIから取得した画像URL
close_flg boolean 店舗閉店情報

Shopsモデルの作成

Shopモデルをコンソールで作成、テーブルも作成します

$ rails g model Shop name:string y_id:string y_gid:string y_uid:string y_ido:string y_keido:string y_address:string y_leadimage:string close_flg:boolean
create db/migrate/20180403110350_create_shops.rb
create app/models/shop.rb

マイグレーションファイルを実行してテーブルを作成

$ rails db:migrate

テーブルが作成されているか確認

$ mysql -u root
mysql> show databases;
mysql> USE koluku_development;
mysql> show tables;
mysql> describe shops;

これで考えてたDB構成が作られてた。

close_flgはBoolean型なのでnilを受け付けないようにデフォルトをFalseにしようと思いました。

マイグレーションファイルを修正して、再度マイグレーションを実行‥

とやったら、おかしくなった。。

一度実行したマイグレーションファイルの再実行は駄目なんだそうです。

ここで1時間ほどつまづきました。

実は既にレッスンで習ったことを忘れてて、何故か既に実行済のマイグレーションファイルをいじりはじめてしまったのです‥(汗

テックアカデミーの講師によると

`rails db:rollback` で前に反映したものを未反映( `rails db:migrate:status` で down 表示になる状態)にしてから再度 `rails db:migrate`で反映して下さい

とのことなので。いったんロールバックしてから、マイグレーションファイルを以下のように編集して、再度マイグレーションを実施。

マイグレーションファイル修正

class CreateShops < ActiveRecord::Migration[5.0]
  def change
    create_table :shops do |t|
      t.string :name
      t.string :y_id
      t.string :y_gid
      t.string :y_uid
      t.string :y_ido
      t.string :y_keido
      t.string :y_address
      t.string :y_leadimage
      t.boolean :close_flg, default: false, null: false

      t.timestamps
    end
  end
end

デフォルト値の指定は以下のような書き方となります。同時にnullの場合はfalseにするように指定しています。

t.boolean :close_flg, default: false, null: false

あと基本的に(特に本番環境で)反映済のマイグレーションファイルを直接いじってはいけませんのでご注意下さい。

運営開始してから間違ってDB作り直しとかすると、(バックアップ取ってなければ)会員情報とか投稿してもらった情報とか全部飛びます。

また複数人で開発しているとDB周りに差分が出来たりするとバグるので気をつける必要があります。

うーん。DBは最初に設計をしっかりやっておかないと大変なことになりそうだな。。プログラミング初心者には難しいぜ!

モデルを作ったらルーターを作成

Railsの一般的なプログラミングの流れに従って、モデル→ルーター→コントローラーという順で作っていきます。

config/routes.rbを次のように編集。

Rails.application.routes.draw do
  root to: 'toppages#index'

  resources :shops
end

$rails routesでルーティングが作成されてるか確認。

Prefix Verb URI Pattern Controller#Action
root GET / toppages#index
shops GET /shops(.:format) shops#index
POST /shops(.:format) shops#create
new_shop GET /shops/new(.:format) shops#new
edit_shop GET /shops/:id/edit(.:format) shops#edit
shop GET /shops/:id(.:format) shops#show
PATCH /shops/:id(.:format) shops#update
PUT /shops/:id(.:format) shops#update
DELETE /shops/:id(.:format) shops#destroy

このようになりました。
それぞれ以下のように考えています。(これが後のレビューで修正になるとは‥)

①ショップの一覧を表示する
shops GET /shops(.:format) shops#index

②ショップのDB保存
POST /shops(.:format) shops#create

③口コミ投稿画面
new_shop GET /shops/new(.:format) shops#new

④2回目以降の口コミ投稿画面
edit_shop GET /shops/:id/edit(.:format) shops#edit

⑤店舗口コミ詳細画面
shop GET /shops/:id(.:format) shops#show

この3つはよくわからないので取り敢えず保留(汗
PATCH /shops/:id(.:format) shops#update
PUT /shops/:id(.:format) shops#update
DELETE /shops/:id(.:format) shops#destroy

ルーターを作ったらコントローラーを作成

コンソールで生成コマンド

$ rails g controller Shops –no-helper –no-assets
create app/controllers/shops_controller.rb
create app/views/shops

shopのコントローラーを実装

shops_controller.rbに7つのメソッドを書いて枠だけ作っておく。随時それぞれのメソッドを実装していく形にしています。

class ShopsController < ApplicationController
  def index
  end

  def show
  end

  def new
  end

  def create
  end

  def edit
  end

  def update
  end

  def destroy
  end
end

コントローラーの次はVIEWの作成

コントローラーを作ったらビューを作る、というのもRailsの標準的な開発の流れです。

cd app/views/shops/ で移動して以下ファイルを作成。

index.html.erb
show.html.erb
new.html.erb
edit.html.erb

ショップ一覧画面を作成する

index.html.erbでショップ一覧を表示させるので、以下のように記述。

<% content_for :cover do %>
  <div class="cover">
    <div class="cover-inner">
      <div class="cover-contents">
        <h1>店舗一覧</h1>
      </div>
    </div>
  </div>
<% end %>

<p>テスト</p>

テストのところにDBから取ってきたShopの一覧を表示させたいと思います。

手動で予めデータを入れておく

さて、このタイミングでショップ情報を手動でDBに入れておきました。

1店舗目 2店舗目 3店舗目
name リンガーハット 柏駅東口店 くるまやラーメン柏大津ケ丘店 ラーメン街道一番星イオンモール柏店
y_id gaa8016 21230394045 21230491007
y_gid 04qKqvYnAxQ Xia079FuO76 eCFwuWgnTQY
y_uid 72bca3dad8bc642f747c89d711c59abcfbbf9575 413abfcd6868c41940aa9710d6b9950c51161b72 8f5d9f624a787e074c1bed888332018e4d97b232
y_ido 35.86060775 35.841221666667 35.851761666667
y_keido 139.97321684 140.0029475
y_address 千葉県柏市柏1-5-16 千葉県柏市大津ケ丘1丁目49−3 千葉県柏市豊町2丁目5−25

rails cコンソールを使って手動でデータ作成。

> rails c

> shop = Shop.new(name: ‘リンガーハット 柏駅東口店’, y_id: ‘gaa8016′, y_gid: ’04qKqvYnAxQ’, y_uid: ’72bca3dad8bc642f747c89d711c59abcfbbf9575′, y_ido: ‘35.86060775’, y_keido: ‘139.97321684’, y_address: ‘千葉県柏市柏1-5-16’)

> shop.save

> shop2 = Shop.new(name: ‘くるまやラーメン柏大津ケ丘店’, y_id: ‘21230394045’, y_gid: ‘Xia079FuO76’, y_uid: ‘413abfcd6868c41940aa9710d6b9950c51161b72’, y_ido: ‘35.841221666667’, y_keido: ‘140.0029475’, y_address: ‘千葉県柏市大津ケ丘1丁目49−3’)

> shop2.save

> shop3 = Shop.new(name: ‘ラーメン街道一番星イオンモール柏店’, y_id: ‘21230491007’, y_gid: ‘eCFwuWgnTQY’, y_uid: ‘8f5d9f624a787e074c1bed888332018e4d97b232’, y_ido: ‘35.851761666667’, y_keido: ‘139.961476388889’, y_address: ‘千葉県柏市豊町2丁目5−25’)

> shop3.save

mysqlで確認。

$ mysql -u root
mysql> show databases;
mysql> USE koluku_development;
mysql> select * from shops;

shop#indexアクションを実装

先程作成したshop_controller.rbの、indexメソッドを実装していきます。

取り敢えず、すべてのshopを取得して@がついた変数に代入します。これでVIEW側でもこの変数が使えるようになる。

class ShopsController < ApplicationController
  def index
    @shops = Shop.all
  end

VIEW(index.html.erb)の実装

上のindexアクションから送られてきた@shopsを用いて一覧表示を行います。

<p><%= @shops.length %>件ヒットしました。</p>

<div class="shoplist">

  <% @shops.each do |shop| %>
  
    <article class="shoplist-item">
  
      <p class="shoplist-title"><%= shop.name %></p>
      
      <div class="shoplist-thumb">
        <img src="<%= root_url %>images/icon/icon-no-image.png">
      </div>
  
      <div class="shoplist-cont">
        <p><%= shop.y_address %></p>
        <p>緯度:<%= shop.y_ido %> 経度:<%= shop.y_keido %></p>
      </div>
  
    </article>
  <% end %>

</div>

each文でショップの数だけループさせ、その中でshop.nameで店舗名を表示、また画像はまだ無いので仮のNo Image画像を出して、ショップの住所と緯度・経度だけを表示させます。

これでここまで出来ました。

データベースに後からカラムを追加(汗

ここまで実装を進めてきたのですが、途中でカラムを追加したくなりました(汗)あれほど言われてるのに。

設計の時に先を見越してちゃんとしたDBを構築できていれば良かったのですが、テックアカデミーの講師の方とのレビューもまだなので、かつ自分で試行錯誤したかったのでこのようになってしまいました。

shopsテーブルに追加したカラムは

osusume(boolean) → 店主が◯◯をおすすめしてるかどうか
y_moyorieki(str) → 最寄り駅と徒歩◯分

の2つです。

作成済みDBに後からカラムを追加する方法

コンソールで以下のように実行。

Addカラム名Toテーブル名 カラム名:型
とやります。

osusumeカラム追加

$ rails g migration AddOsusumeToShops osusume:boolean
create db/migrate/20180404003658_add_osusume_to_shopss.rb

マイグレーションファイルが作成されます。

y_moyoriekiカラム追加

$ rails g migration AddY_moyoriekiToShops y_moyorieki:string
create db/migrate/20180404004635_add_y_moyorieki_to_shops.rb
$ rails db:migrate

マイグレーションも実行しました。テーブルに本当にカラムが追加されているか確認します。

$ mysql -u root
mysql> show databases;
mysql> USE koluku_development;
mysql> show tables;
mysql> describe shops;

これでOKですね。

画面表示はこのようになりました。

ボタンも作成したのですが、うまく枠内にはまりません。

ショップ一覧画面を一旦完成させる

Bootstrapを使って画面をデザインして結果的にindex.html.erbは以下のようにしました。

<% content_for :cover do %>
  <div class="cover">
    <div class="cover-inner">
      <div class="cover-contents">
        <h1>店舗一覧</h1>
      </div>
    </div>
  </div>
<% end %>

<p><%= @shops.length %>件ヒットしました。</p>


<div class="shoplist">

  <% @shops.each do |shop| %>
  
    <article class="shoplist-item">
  
      <div class="raw">

        <div class="col-xs-4"> 
          <div class="shoplist-thumb">
            <img class="mw100" src="<%= root_url %>images/icon/icon-no-image.png">
          </div>
        </div>
    
        <div class="col-xs-8"> 
          <div class="shoplist-cont">

            <p class="shoplist-title orange b"><%= shop.name %></p>
            <p><%= shop.y_address %><br><%= shop.y_moyorieki %></p>
            <p>緯度:<%= shop.y_ido %> 経度:<%= shop.y_keido %></p>


<p>あああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ</p>
<p>いいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいい</p>
<p>ううううううううううううううううううううううううううううううううううううううううううううううううううううううううううううううううううううううううううううううう</p>

            <div class="raw">
              <div class="col-xs-6"><a class="btn btn-danger" href="new_kuchikomi_path"><span>店情報の投稿に協力する</span></a></div>
              <div class="col-xs-6"><%= link_to shop, class: "btn btn-warning" do %><span>店内写真や口コミを見る</span><% end %></div>
            </div>


          </div>
        </div>
      </div>

    </article>
  <% end %>

</div>

画面表示が以下のようになったところで、ひとまずショップ一覧画面は完成として次に進みたいと思います。

次は、口コミModelの作成に入ります!