3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

初めてデプロイしたアプリに使用した技術

Posted at

初めまして。chihaと申します。
TECH::EXPERT短期にてRuby/Railsを中心に学習を開始して1ヶ月半ほど経ちました。
いい加減技術的アウトプットもしなければ、ということで初のQiita投稿です。

初めに

当記事は私(chiha)が初めて個人で開発したアプリケーションをデプロイしたので、用いた技術やコードについての記録を残すために書いています。

概要

アプリケーション名:FishingRecords
URL:https://fishing-records.herokuapp.com/
アプリ概要:ユーザー認証機能、投稿機能(釣果、釣り場)、投稿検索機能、詳細表示機能(googlemap付き)
アプリケーショントップページにて概要を表示しています。

使用ツール

  • Ruby on Rails 5.2.2
  • Ruby 2.5.1
  • jQuery
  • 開発・テスト MySQL
  • 本番 PostgreSQL
  • デプロイ heroku
  • 本番の画像アップロード Amazon S3

機能とツール、コード

苦労したコードや初めて使用した技術についての記録。

やったこと

  • 初期データの実装(スクレイピングをしてCSVへの書き出し、CSVからのcreate)
  • selectフォームの非同期通信による連動機能
  • herokuでのデプロイ

初期データ

http://yu0105teshi.hateblo.jp/entry/2016/08/03/180603
こちらを参照に、lib/tasks/seed.rakeを作成し、以下のコードを記述してseedコマンドでファイルを指定して走らせることができるように。

Dir.glob(File.join(Rails.root, 'db', 'seeds', '*.rb')).each do |file|
  desc "Load the seed data from db/seeds/#{File.basename(file)}."
  task "db:seed:#{File.basename(file).gsub(/\..+$/, '')}" => :environment do
    load(file)
  end
end

これで、db/seeds以下に配置した***.rbファイルに対して

$ rake db:seed:***

でファイルを指定しながらseedを叩けるようになりました。
スクレイピングをして初期データを作るのでnokogiriを導入
Gemfile

gem "nokogiri"

ターミナル

$ bundle install

https://qiita.com/kumamonmaster/items/9bb2aadde56c956fdc9f
https://qiita.com/mukoya/items/e975358ae8b86d64e5b2
この辺りを参考に、某百科事典サイトから魚の名前を取得し、csvに書き出す処理と、csvからseedデータを作成する処理を記述

/db/seeds/scraping.rbを作成し記述

require 'csv'
require "nokogiri"
require "open-uri"

# 取得元のURLを代入
url = "https://ja.wikipedia.org/wiki/%E9%AD%9A%E3%81%AE%E4%B8%80%E8%A6%A7"

contents = []
# スクレイピングでデータ取得
doc = (Nokogiri::HTML(open(url)))
# 開いたurlのhtml内で、tdタグの中のulタグの中のliタグの中のa要素という条件に一致するものに対して繰り返し処理
doc.css("td").css("ul").css("li").css("a").each do |link|
  #一致した要素の本文とhref属性の要素を取得して一つの配列化(csvへの書き出しの際、1つの配列が1つの行になるため)
  data = [link.content, link[:href]]
  contents << data
end

# db/seeds/csvにfish_names.csvを作成させて書き出し
CSV.open("db/seeds/csv/fish_names.csv","w") do |csv| 
  contents.each do |content|
    csv << content
  end  
end  

# CSVからseedデータをcreate
CSV.foreach("db/seeds/csv/fish_names.csv", encoding:"UTF-8") do |row|
  fish_name = row[0]
  fish_url = row[1]
  Fish.find_or_create_by(name: fish_name, url: ("https://ja.wikipedia.org" + fish_url))
end  

これで

$ bundle exec rake db:seed:scraping

を叩いて初期データを作ってもらえるように。
スクリーンショット 2019-09-05 20.08.58.png
こんな感じに魚の名前がズラーっと。
ついでに県と市のデータを作ってもらえるようにコードを書きました。

Prefectureテーブル

Column Type Options
name string null: false
has_many :cities

Cityテーブル

Column Type Options
name string null: false
prefecture_id references foreign_key: true
belongs_to :prefecture

こんな感じの2つのテーブルにまとめてデータを作ってもらいます。

今回はdb/seeds/csv配下に郵便局の郵便番号一覧(https://www.post.japanpost.jp/zipcode/download.html )のcsvファイルを配置しています。

https://qiita.com/ultrasevenstar/items/bcf1601e2269e46e1e9b
こちらのcsv読み込み以降のコードを参考にしました。

/db/seeds/prefecture.rbを作成して以下を記述

require 'csv'
require "open-uri"

# csvを開くが文字コードが違うので指定してあげる
CSV.foreach("db/seeds/csv/KEN_ALL.CSV", encoding: "Shift_JIS:UTF-8") do |row|
  prefName = row[6]
  cityName = row[7]
  #県のデータを作る
  pref = Prefecture.find_or_create_by(name: prefName)
  #市のデータを作る
  City.find_or_create_by(name: cityName, prefecture_id: pref.id)
end

これで

$ bundle exec rake db:seed:prefecture

を叩いて県と市のデータを作ってくれます。
初期データ関連は以上になります。

selectフォームの非同期通信による連動機能

具体的に言うと、県を選ぶと市のフォームの内容が入れ替わる機能です。
3e310576fc41bffd835933b4b6d5739c.gif
こういうやつ。

http://kawahiro.hatenablog.jp/entry/2013/10/26/233051
こちらのコードを参考に。
テーブルとアソシエーションは先述の通りです。

materialize導入、hamlでの記載をしています
/views/posts/new.html.haml

= form_for @post do |f|
  //…中略
  .pref-choice-form
    .pref-choice-form__left
      = f.label :prefecture_id ,"都道府県"
      = f.select :prefecture_id, @pref_choices, class: "select_form",include_blank: true
  .city-choice-form
    .city-choice-form__left
       = f.label :city_id ,"市区町村"
       = render partial:"cities", locals: {city_choices: @city_choices}

/views/posts/_cities.html.haml

.input-field.col.s12.search_cities
  = select :post,:city_id,city_choices,include_blank: true

routes.rb

# 今回はpostsの中で使用するのでposts/cities_selectにしています
resources :posts do
  collection do
    get :cities_select
  end
end

posts_controller.rb

# ルーティングで作ったcities_selectという処理を書く
def cities_select
  if request.xhr?
    #飛んできたリクエストとパラメータで表示データ生成
    @cities = City.where(prefecture_id: params[:prefecture_id])
    #selectフォームに出す個別の選択肢用の処理([フォームに表示するテキスト,フォームで飛ばしたいID]という形を作らせる
    @city_choices = @cities.map{|city| [city.name, city.id]}
    #作った配列データをcityのselectフォーム部分に飛ばす
    render partial: 'cities', locals: {city_choices: @city_choices}
  end
end

jsフレームワークのjQueryを使用しています

$(window).load(function(){
  $("#post_prefecture_id").on("change",function(){
    $.ajax({
      type: "get"
      url: "/posts/cities_select",
      data: {
        prefecture_id: $(this).val()
      }
    })
    .done(function(data){
      $(".search_cities").html(data);
      //Materializeのformを使用している場合、これ書かないと処理後のフォームが表示されない
      $("#post_city_id").formSelect();
    })
  });
});

これで完成!
Materializeのselectフォームでは、

$(document).ready(function(){
  $('select').formSelect();
});
//https://materializecss.com/select.htmlのinitialization参照

という処理を最初にかけないと表示されないので、ajax処理後に追加したフォームに対して$("#post_city_id").formSelect();みたいにしてあげないと選択肢入れ替え後のフォームが表示されませんでした。
こんな感じで連動selectを実装しました。

herokuでのデプロイ

https://qiita.com/kazukimatsumoto/items/a0daa7281a3948701c39
こちらの記事そのままです。ありがとうございました。
自分のローカル環境がMySQLだったので曖昧検索のコードが上手く走らなかったので合わせて修正しました(以下の記事と同じ書き方をしていました)
https://qiita.com/smizuka/items/a80bb84191e015b34e40

Post.where("name LIKE(?) AND city_id LIKE(?)","%#{pamrams[:name]}%","#{params[:city_id]}")

こんな感じで書いてたのですがPostgreSQLでは型チェックがより厳密なのでエラーになる(そもそも型を意識しないコーディングが悪い)。

Post.where("name LIKE(?) AND city_id::text LIKE(?)","%#{pamrams[:name]}%","#{params[:city_id]}")

これで本番のPostgreSQLでは動くものの、今度はローカルでエラー。
最終的に

Post.where("name LIKE(?)","#{params[:name]}").where(city_id: params[:city_id])

whereを重ねて書いたら全部解決しました。知識不足。

最後に

長くなるので今回の記事ではこの辺りにします。あくまで導入した新しい技術についての記録を残す感じにしました。
検索機能など、自分で書いたコードについてはおいおい書きます。忘れないようにします。
まだまだ学習2ヶ月ほどのド初心者ですので、より良いコード、間違った点などがあればご教授頂けると幸いです。

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?