LoginSignup
4
4

More than 3 years have passed since last update.

府中産農産物直売所検索ページをとおしてかんたんなrailsアプリつくってみよう

Last updated at Posted at 2019-03-10

概要

  • 府中市が公開しているオープンデータを検索する事を事例にして、railsのアプリを作成する方法を丁寧に解説します。

作れるモノ

github

環境

  • ruby (rbenv) 2.6.1
  • rails 6.0.0 rc 1
  • mac

使っているGem

手順

以下の手順で説明します
1. rails new ! (空のアプリを作ろう)
2. migration ! (テーブル作ろう)
3. import ! (データをインポートしよう)
4. view ! (データを表示しよう)
4. search ! (データを検索できるようにしよう)
5. deploy ! (herokuにアップしてみんなで使えるようにしよう)

rails new ! (空のアプリを作ろう)

> bundle init
Writing new Gemfile to /Users/junara/IdeaProjects/opendata/Gemfile
> ls
Gemfile      Gemfile.lock 

railsをインストールするために gem "rails" のコメントをアウトを外します。

# frozen_string_literal: true

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

gem "rails", '~> 6.0.0.rc1'
bundle install
# 省略

今いる場所にrailsを作成します。

pwd
# 今の場所がわかる
rails new .

ここでいちど起動を確認しましょう

rails s

http://localhost:3000 にアクセスします。下記の画面が出たら成功です。
image.png

migration ! (テーブル作ろう)

今回対象となるデータを見ます。 府中産農産物直売所マップ(平成30年11月現在) (CSV:11KB)

インポートするデータを府中市のHPからダウンロードして中身を見ます。
府中産農産物直売所マップ(平成30年11月現在) (CSV:11KB)

エディタによっては、へんな文字が羅列されているかもしれません。
これは、文字コードをうまく認識できていないことが問題です。
文字コードは複数種類ありますが、今だったらshift-jisとutf-8どちらかを試せば解決することが多いです。(エディタによってやり方が違うのでそちらは各自しらべてください。)
今回はshift-jisを選ぶと文字がキチンと日本語で表示されます。

db/30chokubaijo_map.csv
№,名 前,直売所住所,電話番号,営業時間,販売期間,休業日,販売品目,コメント
# 省略

取り込むmodelを作成します。model名とカラム名を考えましょう
今回は、お店のデータなのでテーブル名は Store とします。

 rails g model store                                                                                                     ?[HEAD]
Running via Spring preloader in process 84006
      invoke  active_record
      create    db/migrate/20190310103813_create_stores.rb
      create    app/models/store.rb
      invoke    test_unit
      create      test/models/store_test.rb
      create      test/fixtures/stores.yml

次にカラム名です。カラム名は、取り込みたいデータのないようで決めます。
取り込みたいデータとは、前記のCSVをみて考えます。
もちろん、全部のデータを取り込むこともできます。ただ、無駄なデータを取り込むのはデータベースを肥大化させるだけなので、まずは必要なデータ、使用する列だけを取り込みます。
とりあえず、今回必要とするのは 名 前販売品目 列とします。
これにあわせてmigrationを作成しましょう

db/migrate/20190310103813_create_stores.rb
class CreateStores < ActiveRecord::Migration[6.0]
  def change
    create_table :stores do |t|
      t.string :name, comment: '名 前'
      t.string :description, comment: '販売品目'
      t.timestamps
    end
  end
end

migrationファイルが作られたら、migrationを実行して、tableを作成しましょう。

rails db:migrate                                                                                                        ?[HEAD]
== 20190310103813 CreateStores: migrating =====================================
-- create_table(:stores)
   -> 0.0113s
== 20190310103813 CreateStores: migrated (0.0113s) ============================

これで、必要なmodel, tableの作成が終了しました。

import ! (データをインポートしよう)

下記のgemを入れます。importするときの定番。

gem 'activerecord-import'
bundle install
# 省略

取り込むためのメソッドをStoreモデルに書きます。

require 'csv'
class Store < ApplicationRecord
  def self.import_csv(file)
    list = []
    CSV.foreach(file, encoding: 'cp932', headers: true) do |row|
      list << self.new(store_params(row))
    end
    import list
  end

  def self.store_params(row)
    {
        name: row['名 前'],
        description: row['販売品目']
    }
  end
end

先ほど db/30chokubaijo_map.csv に保存したcsvをインポートします。

rails c
irb > Store.import_csv('db/30chokubaijo_map.csv')
   (0.2ms)  SELECT sqlite_version(*)
   (0.1ms)  begin transaction
   (0.1ms)  SAVEPOINT active_record_1
# 省略
   (0.1ms)  RELEASE SAVEPOINT active_record_1
   (0.8ms)  commit transaction
=> #<struct ActiveRecord::Import::Result failed_instances=[], num_inserts=1, ids=[], results=[]>

保存されているか確認します。

irb > Store.first.description
  Store Load (0.2ms)  SELECT "stores".* FROM "stores" ORDER BY "stores"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> "トマト、きゅうり、おくら、いんげん、キャベツ、さつまいも、ブロッコリー、ねぎ、なす、モロヘイヤ、ピーマン、紫イモ、カリフラワー、じゃがいも、里いも、大根、ほうれん草、水菜 ほか"
irb(main):009:0>  Store.count
   (0.2ms)  SELECT COUNT(*) FROM "stores"
=> 46

view ! (データを表示しよう)

ルートを追加します。

config/routes.rb
Rails.application.routes.draw do
  root to: 'home#index'
end

上記で追加したhomeのアクションを行うコントローラーを新規で追加します。

app/controllers/home_controller.rb
class HomeController < ApplicationController
  def index
    @stores = Store.all
  end
end
app/views/home/index.html.erb
<h2>
  府中産農産物直売所一覧
</h2>
<% @stores.each do |store| %>
  <div>
    <h3>
      <%= store.name %>
    </h3>
    <div>
      <%= store.description %>
    </div>
  </div>
<% end %>

ここで確認します。
http://localhost:3000/

image.png

search ! (データを検索できるようにしよう)

Activerecordでやるのは面倒なので、定番の検索のgem ransackを入れます。

gem 'ransack'

で、インストール

bundle install

検索するために、indexアクションを修正します。
ransackの使い方は公式をどうぞ。

app/controllers/home_controller.rb
class HomeController < ApplicationController
  def index
    @stores = Store.ransack(description_cont: params[:keyword]).result
  end
end

検索フォームをviewについかします。

<h2>
  府中産農産物直売所一覧
</h2>

<div>
  <%= form_with url: root_path, method: :get, local: true do |f| %>
    <%= f.text_field :keyword, value: params[:keyword], autocomplete: 'off' %>
    <%= f.submit '検索' %>
  <% end %>
</div>
<% @stores.each do |store| %>
  <div>
    <h3>
      <%= store.name %>
    </h3>
    <div>
      <%= store.description %>
    </div>
  </div>
<% end %>

ためします。
入力ボックスに 乳酸菌飲料 と入力すると下記のようになれば成功です。

image.png

deploy ! (herokuにアップして世界のみんなに使ってもらおう)

developmentとtest環境ではsqlite3, productionではpgをインストールします。

group :development, :test do
  gem 'sqlite3'
end

group :production do
  gem 'pg'
end

herokuへpushと同時に migrationが走るようにしましょう

release: bundle exec rake db:migrate

herokuのアプリを作ります。

heroku create fuchu-nosanbutsu

現行のmasterをherokuへpushします。

git push heroku master

うまくdeployされたかみましょう

heroku open

こういう表示なら成功です。

image.png

次にデータをインポートします。herokuでrails cをします。

heroku run rails c

既にやったようにインポートをします。

Store.import_csv('db/30chokubaijo_map.csv')
Store.count # -> 46

終わったらexit

exit

herokuのページを再度リロードすると前述と同様に、一覧が表示され、検索も可能なことが確認できます。

image.png

完成です!!!これで、世界の人に府中市の農産物をアピールできました!

さらに発展させるには?

作ったのは、とてーもシンプルなアプリです。更に発展させるともっと使いやすいアプリになります。ご自身の興味にしたがって色々やってみましょう。
下記は、拡張例です!
是非挑戦しましょう!

かんたんめ

  • インポート対象を追加する:元のCSVには、住所などの列もあります。そちらもインポート対象にしましょう。
  • インポートした列を表示に追加しましょう。
  • 検索結果にページネーションを加えましょう
  • 検索キーワード結果の文章にマッチしたキーワードをハイライトさせましょう。
  • 複数のカラムを対象に検索できるようにしましょう
  • bootstrapを導入して、装飾しましょう
  • bulmaを導入して装飾しましょう
  • 住所を押した時、google mapに遷移させましょう
  • データを追加、編集できるフォームを追加しましょう
  • herokuにdeployしましょう

そこそこ

  • インポート時、重複列がある場合はupdateにしましょう
  • 空白スペースで区切った場合はand検索になるようにしましょう
  • 検索をページ遷移せずajaxで行いましょう
  • 地図(google map)を表示させましょう

むずかしめ

  • インクリメンタルサーチを入れましょう
  • vue or reactでフロントを書きましょう

enjoy !

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4