- 投稿日:2020-07-25T23:07:00+09:00
Google Chartがモーダルで上手く表示できない時
簡単にグラフが作れて人気なGoogle Chart。その中の「GeoChart」は都道府県別の日本地図を作成できます。以下のように都道府県別で色分でき、カーソルを当てるとパラメータを表示してくれます。
やりたいこと
今回は既にあるオリジナルサービス内に、ユーザー詳細ページにあるリンクをクリックするとモーダルでユーザーのデータが反映されたMAPを表示する機能を実装します。
ということでファイルを作成。
(データを入れる処理は人それぞれなので割愛)users/_map.html.erb<div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <div class="modal-header"> <h4 class="modal-title" id="myModalLabel"><%= "#{@user.name}がイベントで訪れた都道府県" %></h4> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> </div> <div id="regions_div"></div> <script src="https://www.gstatic.com/charts/loader.js"></script> <script type="text/javascript"> google.charts.load('current', {'packages':['geochart']}); google.charts.setOnLoadCallback(drawRegionsMap); function drawRegionsMap() { var data = google.visualization.arrayToDataTable(gon.map_data); var options = { region: 'JP', resolution: 'provinces', width: '100%', height: 500 }; var chart = new google.visualization.GeoChart(document.getElementById('regions_div')); chart.draw(data, options); } </script> </div> </div>users/map.js.erb$("#map-modal").html("<%= escape_javascript(render 'map') %>") $("#map-modal").modal("show")users/show.html.erb-略- <%= link_to map_user_path(user), remote: true do %> <%= image_tag "/images/japan.png" %> <% end %> -略- <div class="modal fade" id="map-modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"></div> <div class="modal fade" id="recommend-modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"></div>users_controller.rbdef show gon.map_data = @user.prefecture_data endprefecture_dataメソッドはmodels/user.rb内に作ったメソッドで、都道府県に行ったデータを取得していると思ってください。
問題
さあ準備ができたので、実際にブラウザでリンクをクリックしてみましょう。
あ、あれ!!??(・_・;
上手く表示されていません…
モーダルタイトルの「ゲストユーザーがイベントで訪れた都道府県」は表示されていますが肝心な日本地図は表示されませんでした。解決
どうやらmodalが完全に表示する前に、地図を描画させてしまっている事が原因のようです。
今回はmap.js.erbにjQueryで以下のように書いてみました。map.js.erb$("#map-modal").html("<%= escape_javascript(render 'map') %>") $("#map-modal").modal("show") #以下を追記 $("#map-modal").on("shown.bs.modal", function () { google.charts.load('current', {'packages':['geochart']}); google.charts.setOnLoadCallback(drawRegionsMap); var data = google.visualization.arrayToDataTable(gon.map_data); var options = { region: 'JP', resolution: 'provinces', width: '100%', height: 600 }; var chart = new google.visualization.GeoChart(document.getElementById('regions_div')); chart.draw(data, options); });shown.bs.modal(モーダル・ダイアログを開くshowメソッドを呼び出した時のイベント)を使っています。
無事成功しました!
参考
- 投稿日:2020-07-25T23:01:58+09:00
[Rails][IRB][Pry]SourceAnnotationExtractor is deprecated 解決法
起こったこと
Rails6
でbinding.pry
などIRB
でTab
補完しようとすると以下のようなエラーが出る。
(Warining だけど見づらい。)[WARN ] DEPRECATION WARNING: SourceAnnotationExtractor is deprecated! Use Rails::SourceAnnotationExtractor instead. (called from new_card at /home/user/dev/rails/test-proj/app/controllers/app_controller.rb:36)解決法
とりあえず
以下のパッチをconfig/initializers
に置く。config/initializers/active_support_backports.rb# Fix IRB deprecation warning on tab-completion. # # Backports the fix for https://github.com/rails/rails/issues/37097 # from https://github.com/rails/rails/pull/37100 # # Backports proposed fix for https://github.com/rails/rails/pull/37468 # from https://github.com/rails/rails/pull/37468 module ActiveSupportBackports warn "[DEPRECATED] #{self} should no longer be needed. Please remove!" if Rails.version >= '6.1' def self.prepended(base) base.class_eval do delegate :hash, :instance_methods, :respond_to?, to: :target end end end module ActiveSupport class Deprecation class DeprecatedConstantProxy prepend ActiveSupportBackports end end end参考
- 投稿日:2020-07-25T22:20:01+09:00
Herokuへのデプロイ後、HTTPエラー500が出た
Ruby on Railsで簡単な掲示板アプリを作成し、初めてherokuのデプロイに成功した。
ただ、herokuでsqliteが未対応なことを知らなかったり、フロント周りをslimで初実装した為に、デプロイ前後で少々エラーに苦しんだので、備忘録として解決方法を残す。
sqliteでherokuデプロイ失敗した時の対処法
恐らくrailsでwebアプリを作成した際、デフォルトではsqliteがDBとして設定されていると思う。
そのままデプロイしようとすると失敗するので、
※エラー参考記事1、エラー参考記事2、 herokuデプロイの手順以下を削除
Gemfile.gem 'sqlite3'以下を追記
Gemfile.group :development, :test do gem 'sqlite3' end group :production do gem 'rails_12factor' #heroku logsを詳細表示できる便利gem(必須ではないがあると便利) gem 'pg' #デプロイ後はpostgresqlを使うように指定 endその後
$git push heroku master
をしたらデプロイは成功した。herokuデプロイは成功しているのにアプリが表示できない時の対処法
その後、
$heroku open
でデプロイできたアプリをブラウザで見ようとしたところ、HTTP500のエラーが出てサイトが表示されないというエラーが出た。
このエラーの原因は、viewにslimを導入しており、slimのgem記述位置がdeveropmentにあったためだった。
なので、以下2つのgemを、group :development doから、全ての環境で適応される場所に記述。Gemfile.gem 'slim-rails' gem 'html2slim'we're sorry, but something went wrongのエラーへの対処法
その後、rootパスのURLは表示に成功したが、違うコントローラーのURLが通らない。
we're sorry, but something went wrongという表記が出てしまう。これは、デプロイ前のエラーの原因sqliteが関係していた。
we're sorry, but something went wrongでgoogle画像検索を実行して出てきたこのサイトにある現象と似ていたので、それを実行してみたところエラーが解決した。
$heroku run rake db:migrate
今回のエラーで学んだこと
herokuでデプロイ後なにか表示に問題があった場合は、
$heroku logs -t
でログが確認できる。
Google画像検索も有効
エラーを検索した時に、SEO的強いにQiitaや質問サイトが上の方に出てくるが、Google画像検索だとSEO的に弱いサイトのサムネなども検索できる。
参考になりそうなサムネをクリックすると解決できるかも..??
- 投稿日:2020-07-25T22:10:45+09:00
都道府県 + 市町村をチェックボックスで複数選択。登録する方法。
やりたいこと
チーム開発で、一人のマッサージ師に対して複数の出張範囲を登録出来る機能を実装した。モデルの関係性など勉強になったのでメモ。完全自分用です。
モデルの関係性
マッサージ師
class Masseur < ApplicationRecord has_many :business_trip_ranges, dependent: :delete_all has_many :cities, through: :business_trip_ranges accepts_nested_attributes_for :business_trip_ranges, reject_if: :reject_business_trip_range, allow_destroy: true出張範囲
class BusinessTripRange < ApplicationRecord belongs_to :masseur belongs_to :city end市町村
class City < ApplicationRecord belongs_to :prefecture has_many :masseurs, through: :business_trip_ranges has_many :business_trip_ranges endややこしいですが図にするとこんな感じ。
作業の流れ
1、APIで取ってきた都道府県 + 市町村データをPrefectureモデルとCityモデルに保存する
2、保存したデータを使って都道府県チェックボックスを作成していきます
3、チェックボックスにチェックした出張範囲はBusinessTripRangeに保存されるざっくりしすぎか。
APIでデータを取ってくる
このサイトから都道府県 + 市町村データがAPIで取ってこれます。APIが使えるならこっちの方が手っ取り早いです。なおAPIキーが必要になるのでサイト内で申請してください。
https://opendata.resas-portal.go.jp/まずは以下のようにしてAPIデータを取得し
module StoreManager::BusinessTripRangesHelper require 'net/http' require 'uri' require 'json' # 都道府県のAPIを叩き、データを出力 def prefectures_api(url) uri = URI.parse(URI.escape(url)) https = Net::HTTP.new(uri.host, uri.port) https.use_ssl = true param = {} param['X-API-KEY'] = '123hsydeusnsindidkm' # 自分が取得したAPI-KEY req = Net::HTTP::Get.new(uri.request_uri, param) res = https.request(req) json = res.body result = JSON.parse(json) end endseeds.rbファイルで取得したデータをPrefectureモデルとCityモデルのカラムに入れて都道府県 + 市町村データを格納します
include StoreManager::BusinessTripRangesHelper # 都道府県データを取得 prefectures = prefectures_api("https://opendata.resas-portal.go.jp/api/v1/prefectures") # 東京都の市/区データを取得 cities = prefectures_api("https://opendata.resas-portal.go.jp/api/v1/cities?prefCode=13") prefectures["result"].each do |value| prefecture_name = value["prefName"] Prefecture.find_or_create_by(name: prefecture_name) end cities["result"].each do |value| city_name = value["cityName"] City.find_or_create_by(name: city_name, prefecture_id: 13) end$ rails db:seedこれでデータがPrefectureとCityに入りました。
都道府県 + 市町村だからとんでもなくデータ多いです。写真はPrefectureモデルに入っているデータですがCityモデルにも市町村データはちゃんと入ってるぞい。保存したデータを元にチェックボックス作る
今回使ったのはcolection_check_boxesというメソッド。なんか最初はややこしかったけど分かると使いやすいかも。
<%= form_with(model: @current_masseur, url: store_manager_business_trip_ranges_update_path(@current_masseur), method: :patch, local: true) do |f| %> <table class="prefecture table table-hover"> <thead> # Prefectureモデルに格納した47都道府県データを全てブロック変数prefectureに代入。 <%= collection_check_boxes :prefecture, :prefecture_ids, Prefecture.all, :id, :name, include_hidden: false do |prefecture| %> <tr> <th> #ブロック変数.textで都道府県名、ブロック変数.checkboxでチェックボックスを作成 <%= prefecture.check_box + prefecture.text %> </th> </tr> </thead> <tbody> <tr> <td class="city-check-boxes"> <div id="city-list"> #市町村も同様です <%= f.collection_check_boxes :city_ids, City.all, :id, :name, include_hidden: false do |city| %> <ul class="city-check-box"> <% if prefecture.object.id == city.object.prefecture_id %> <div id="boxes"> <li class="city-check-box-item"><%= city.check_box + city.text %></li> </div> <% end %> </ul> <% end %> </div> </td> </tr> <% end %> </tbody> </table> <div class="actions text-center"> <%= f.submit "登録する", class: "btn btn-primary mt-5 w-50" %> </div> <% end %>こうなります。
ちなみにコントローラーはこうなってます。
class StoreManager::BusinessTripRangesController < StoreManager::Base before_action :set_masseur, only: [:edit, :update, :show] def edit @prefectures = Prefecture.all @ranges = @current_masseur.business_trip_ranges end def update # チェックがあった場合 if params[:masseur].present? @current_masseur.update(city_business_trip_range_params) flash[:success] = "出張範囲を更新しました。" redirect_to store_manager_masseurs_business_trip_ranges_url # 一つもチェックがなかった場合 else flash[:danger] = "出張範囲を選択してください。" render :edit end end private def set_masseur @current_masseur = Masseur.find(params[:masseur_id]) end def city_business_trip_range_params if params[:masseur].present? params.require(:masseur).permit(city_ids: []) end end end重要なのはストロングパラメーターで配列を受け取る時に
このように書く↓ params.require(:masseur).permit(city_ids: [])もう一つはupdateアクションの@current_masseur.update(city_business_trip_range_params)
このように書くことで「作成」「編集」「削除」が同時にできてしまうこと。
故に「new」「create」「destroy」は必要ありません。途中で眠くなったわ。。
- 投稿日:2020-07-25T20:28:53+09:00
Railsアプリを速度改善する①
EC2でデプロイ後にレスポンス速度を確かめる
herokuでのデプロイは、起動までのレスポンスが遅くユーザーがその間に離脱してしまうのを恐れたので、AWS(EC2)にデプロイしました。
といいつつも、アプリの起動が遅く感じられたのでトップページが表示されるまでのレスポンス速度を測ってみました。
PageSpeed Insightsで測ってみた結果
モバイル
パソコン
使っていないCSSファイルを全部削除
上記のみ残して、CSSファイルを全削除しました。
モバイル
パソコン
6~7パーセント改善されました。
モバイルはまだまだ改善の余地ありなので、他にも試していこうと思います。
- 投稿日:2020-07-25T19:38:59+09:00
Ruby on Rails チュートリアル(第4版) 第13章
13.1.1 演習
1.RailsコンソールでMicropost.newを実行し、インスタンスを変数micropostに代入してください。その後、user_idに最初のユーザーのidを、contentに "Lorem ipsum" をそれぞれ代入してみてください。この時点では、 micropostオブジェクトのマジックカラム (created_atとupdated_at) には何が入っているでしょうか?
>> micropost = Micropost.new => #<Micropost id: nil, content: nil, user_id: nil, created_at: nil, updated_at: nil> >> micropost.user_id = 1 => 1 >> micropost.content = "Lorem ipsum" => "Lorem ipsum" >> micropost => #<Micropost id: nil, content: "Lorem ipsum", user_id: 1, created_at: nil, updated_at: nil>2.先ほど作ったオブジェクトを使って、micropost.userを実行してみましょう。どのような結果が返ってくるでしょうか? また、micropost.user.nameを実行した場合の結果はどうなるでしょうか?
>> micropost.user User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] => #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2020-07-18 13:20:13", updated_at: "2020-07-23 15:00:35", password_digest: "$2a$10$qFFzrhOelczLx3DO.2p6quDaFlV5T1ciSrCbDXTe44d...", remember_digest: nil, admin: true, activation_digest: "$2a$10$OBqUPKe0HwaDUBtqARDRzO9NSFaoKAPHmjNzuTvoqz1...", activated: true, activated_at: "2020-07-18 13:20:13", reset_digest: "$2a$10$HwxkqWWqbizL4WV0Z8G4TuiCHSQsNR.Ce.mg5xsbB/....", reset_sent_at: "2020-07-23 16:07:58"> >> micropost.user.name => "Example User"3.先ほど作ったmicropostオブジェクトをデータベースに保存してみましょう。この時点でもう一度マジックカラムの内容を調べてみましょう。今度はどのような値が入っているでしょうか?
>> micropost.save (0.1ms) begin transaction SQL (2.4ms) INSERT INTO "microposts" ("content", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["content", "Lorem ipsum"], ["user_id", 1], ["created_at", "2020-07-24 14:59:51.939467"], ["updated_at", "2020-07-24 14:59:51.939467"]] (7.0ms) commit transaction => true >> micropost => #<Micropost id: 1, content: "Lorem ipsum", user_id: 1, created_at: "2020-07-24 14:59:51", updated_at: "2020-07-24 14:59:51">13.1.2 演習
1.Railsコンソールを開き、user_idとcontentが空になっているmicropostオブジェクトを作ってみてください。このオブジェクトに対してvalid?を実行すると、失敗することを確認してみましょう。また、生成されたエラーメッセージにはどんな内容が書かれているでしょうか?
>> micropost = Micropost.new => #<Micropost id: nil, content: nil, user_id: nil, created_at: nil, updated_at: nil> >> micropost.valid? => false >> micropost.errors.messages => {:user=>["must exist"], :user_id=>["can't be blank"], :content=>["can't be blank"]}2.コンソールを開き、今度はuser_idが空でcontentが141文字以上のmicropostオブジェクトを作ってみてください。このオブジェクトに対してvalid?を実行すると、失敗することを確認してみましょう。また、生成されたエラーメッセージにはどんな内容が書かれているでしょうか?
>> micropost = Micropost.new => #<Micropost id: nil, content: nil, user_id: nil, created_at: nil, updated_at: nil> >> micropost.content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" => "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" >> micropost.valid? => false >> micropost.errors.messages => {:user=>["must exist"], :user_id=>["can't be blank"], :content=>["is too long (maximum is 140 characters)"]}13.1.3 演習
1.データベースにいる最初のユーザーを変数userに代入してください。そのuserオブジェクトを使ってmicropost = user.microposts.create(content: "Lorem ipsum")を実行すると、どのような結果が得られるでしょうか?
>> micropost = user.microposts.create(content: "Lorem ipsum") (0.1ms) begin transaction SQL (2.7ms) INSERT INTO "microposts" ("content", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["content", "Lorem ipsum"], ["user_id", 1], ["created_at", "2020-07-24 15:37:48.474081"], ["updated_at", "2020-07-24 15:37:48.474081"]] (7.6ms) commit transaction => #<Micropost id: 2, content: "Lorem ipsum", user_id: 1, created_at: "2020-07-24 15:37:48", updated_at: "2020-07-24 15:37:48">2.先ほどの演習課題で、データベース上に新しいマイクロポストが追加されたはずです。user.microposts.find(micropost.id)を実行して、本当に追加されたのかを確かめてみましょう。また、先ほど実行したmicropost.idの部分をmicropostに変更すると、結果はどうなるでしょうか?
>> user.microposts.find(micropost.id) Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? AND "microposts"."id" = ? LIMIT ? [["user_id", 1], ["id", 1], ["LIMIT", 1]] => #<Micropost id: 1, content: "Lorem ipsum", user_id: 1, created_at: "2020-07-24 14:59:51", updated_at: "2020-07-24 14:59:51"> >> user.microposts.find(micropost) Traceback (most recent call last): 1: from (irb):8 ArgumentError (You are passing an instance of ActiveRecord::Base to `find`. Please pass the id of the object by calling `.id`.)3.user == micropost.userを実行した結果はどうなるでしょうか? また、user.microposts.first == micropost を実行した結果はどうなるでしょうか? それぞれ確認してみてください。
>> user == micropost.user => true >> user.microposts.first == micropost Micropost Load (0.1ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."id" ASC LIMIT ? [["user_id", 1], ["LIMIT", 1]] => true13.1.4 演習
1.Micropost.first.created_atの実行結果と、Micropost.last.created_atの実行結果を比べてみましょう。
13.1.1 の演習の後で休憩して、また13.1.1の演習やっちゃったのでmicropostがちょうど2つあった!>> Micropost.first.created_at Micropost Load (1.0ms) SELECT "microposts".* FROM "microposts" ORDER BY "microposts"."created_at" DESC LIMIT ? [["LIMIT", 1]] => Fri, 24 Jul 2020 15:37:48 UTC +00:00 >> Micropost.last.created_at Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" ORDER BY "microposts"."created_at" ASC LIMIT ? [["LIMIT", 1]] => Fri, 24 Jul 2020 14:59:51 UTC +00:002.Micropost.firstを実行したときに発行されるSQL文はどうなっているでしょうか? 同様にして、Micropost.lastの場合はどうなっているでしょうか? ヒント: それぞれをコンソール上で実行したときに表示される文字列が、SQL文になります。
>> Micropost.first Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" ORDER BY "microposts"."created_at" DESC LIMIT ? [["LIMIT", 1]] => #<Micropost id: 2, content: "Lorem ipsum", user_id: 1, created_at: "2020-07-24 15:37:48", updated_at: "2020-07-24 15:37:48"> >> Micropost.last Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" ORDER BY "microposts"."created_at" ASC LIMIT ? [["LIMIT", 1]] => #<Micropost id: 1, content: "Lorem ipsum", user_id: 1, created_at: "2020-07-24 14:59:51", updated_at: "2020-07-24 14:59:51">3.データベース上の最初のユーザーを変数userに代入してください。そのuserオブジェクトが最初に投稿したマイクロポストのidはいくつでしょうか? 次に、destroyメソッドを使ってそのuserオブジェクトを削除してみてください。削除すると、そのuserに紐付いていたマイクロポストも削除されていることをMicropost.findで確認してみましょう。
>> user = User.first User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]] => #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2020-07-18 13:20:13", updated_at: "2020-07-23 15:00:35", password_digest: "$2a$10$qFFzrhOelczLx3DO.2p6quDaFlV5T1ciSrCbDXTe44d...", remember_digest: nil, admin: true, activation_digest: "$2a$10$OBqUPKe0HwaDUBtqARDRzO9NSFaoKAPHmjNzuTvoqz1...", activated: true, activated_at: "2020-07-18 13:20:13", reset_digest: "$2a$10$HwxkqWWqbizL4WV0Z8G4TuiCHSQsNR.Ce.mg5xsbB/....", reset_sent_at: "2020-07-23 16:07:58"> >> user.microposts.first.id Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."created_at" DESC LIMIT ? [["user_id", 1], ["LIMIT", 1]] => 2 >> user.destroy (0.1ms) begin transaction Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."created_at" DESC [["user_id", 1]] SQL (2.2ms) DELETE FROM "microposts" WHERE "microposts"."id" = ? [["id", 2]] SQL (0.1ms) DELETE FROM "microposts" WHERE "microposts"."id" = ? [["id", 1]] SQL (0.7ms) DELETE FROM "users" WHERE "users"."id" = ? [["id", 1]] (7.8ms) commit transaction => #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2020-07-18 13:20:13", updated_at: "2020-07-23 15:00:35", password_digest: "$2a$10$qFFzrhOelczLx3DO.2p6quDaFlV5T1ciSrCbDXTe44d...", remember_digest: nil, admin: true, activation_digest: "$2a$10$OBqUPKe0HwaDUBtqARDRzO9NSFaoKAPHmjNzuTvoqz1...", activated: true, activated_at: "2020-07-18 13:20:13", reset_digest: "$2a$10$HwxkqWWqbizL4WV0Z8G4TuiCHSQsNR.Ce.mg5xsbB/....", reset_sent_at: "2020-07-23 16:07:58"> >> Micropost.find_by(user_id:1) Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."created_at" DESC LIMIT ? [["user_id", 1], ["LIMIT", 1]] => nil13.2.1 演習
1.7.3.3で軽く説明したように、今回ヘルパーメソッドとして使ったtime_ago_in_wordsメソッドは、Railsコンソールのhelperオブジェクトから呼び出すことができます。このhelperオブジェクトのtime_ago_in_wordsメソッドを使って、3.weeks.agoや6.months.agoを実行してみましょう。
>> helper.time_ago_in_words(3.weeks.ago) => "21 days" >> helper.time_ago_in_words(6.months.ago) => "6 months"2.helper.time_ago_in_words(1.year.ago)と実行すると、どういった結果が返ってくるでしょうか?
>> helper.time_ago_in_words(1.year.ago) => "about 1 year"3.micropostsオブジェクトのクラスは何でしょうか? ヒント: リスト 13.23内のコードにあるように、まずはpaginateメソッド (引数はpage: nil) でオブジェクトを取得し、その後classメソッドを呼び出してみましょう。
>> user = User.first User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]] => #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2020-07-24 15:57:45", updated_at: "2020-07-24 15:57:45", password_digest: "$2a$10$yzLVq462FQ51EbIhDs4FiuPyt1.WstZxPXZX2dDelpX...", remember_digest: nil, admin: true, activation_digest: "$2a$10$jw5ZFmNfN1SKy56aWVmoWumqyJOgVG9O4D71auy.2FM...", activated: true, activated_at: "2020-07-24 15:57:45", reset_digest: nil, reset_sent_at: nil> >> microposts = user.microposts.paginate(page: nil) Micropost Load (0.1ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."created_at" DESC LIMIT ? OFFSET ? [["user_id", 1], ["LIMIT", 11], ["OFFSET", 0]] => #<ActiveRecord::AssociationRelation []> >> microposts.class => Micropost::ActiveRecord_AssociationRelation13.2.2 演習
1.(1..10).to_a.take(6)というコードの実行結果を推測できますか? 推測した値が合っているかどうか、実際にコンソールを使って確認してみましょう。
1~10までの配列から6個。1,2,3,4,5,6
と予想!>> (1..10).to_a.take(6) => [1, 2, 3, 4, 5, 6]2.先ほどの演習にあったto_aメソッドの部分は本当に必要でしょうか? 確かめてみてください。
>> (1..10).take(6) => [1, 2, 3, 4, 5, 6]3.Fakerはlorem ipsum以外にも、非常に多種多様の事例に対応しています。Fakerのドキュメント (英語) を眺めながら画面に出力する方法を学び、実際に大学名や電話番号、Hipster IpsumやChuck Norris facts (参考: チャック・ノリスの真実) を画面に出力してみましょう。(訳注: もちろん日本語にも対応していて、例えば沖縄らしい用語を出力するfaker-okinawaもあります。ぜひ遊んでみてください。)
省略13.2.3 演習
1.リスト 13.28にある2つの'h1'のテストが正しいか確かめるため、該当するアプリケーション側のコードをコメントアウトしてみましょう。テストが green から redに変わることを確認してみてください。
RED。2.リスト 13.28にあるテストを変更して、will_paginateが1度のみ表示されていることをテストしてみましょう。ヒント: 表 5.2を参考にしてください。
assert_select 'div.pagination', count: 1
13.3.1 演習
1.なぜUsersコントローラ内にあるlogged_in_userフィルターを残したままにするとマズイのでしょうか? 考えてみてください。
DRYじゃないから。13.3.2 演習
1.Homeページをリファクタリングして、if-else文の分岐のそれぞれに対してパーシャルを作ってみましょう。
/app/views/static_pages/home.html.erb<% if logged_in? %> <%= render 'static_pages/form' %> <% else %> <%= render 'static_pages/home' %> <% end %>/app/views/static_pages/_form.html.erb<div class="row"> <aside class="col-md-4"> <section class="user_info"> <%= render 'shared/user_info' %> </section> <section class="micropost_form"> <%= render 'shared/micropost_form' %> </section> </aside> </div>/app/views/static_pages/_home.html.erb<div class="center jumbotron"> <h1>Welcome to the Sample App</h1> <h2> This is the home page for the <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a> sample application. </h2> <%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %> </div> <%= link_to image_tag("rails.png", alt: "Rails logo"), 'http://rubyonrails.org/' %>13.3.3 演習
1.新しく実装したマイクロポストの投稿フォームを使って、実際にマイクロポストを投稿してみましょう。Railsサーバーのログ内にあるINSERT文では、どういった内容をデータベースに送っているでしょうか? 確認してみてください。
INSERT INTO "microposts" ("content", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["content", "test"], ["user_id", 1], ["created_at", "2020-07-24 17:11:12.992282"], ["updated_at", "2020-07-24 17:11:12.992282"]]
2.コンソールを開き、user変数にデータベース上の最初のユーザーを代入してみましょう。その後、Micropost.where("user_id = ?", user.id)とuser.microposts、そしてuser.feedをそれぞれ実行してみて、実行結果がすべて同じであることを確認してみてください。ヒント: ==で比較すると結果が同じかどうか簡単に判別できます。
>> user = User.first User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]] => #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2020-07-24 16:10:08", updated_at: "2020-07-24 16:10:08", password_digest: "$2a$10$tQRLa33AWEnVY6Iv0P6QJeW6zfanS6l.Wux54rFANYO...", remember_digest: nil, admin: true, activation_digest: "$2a$10$dHd0zoYxFpnvto1Yf/wBd.XViarjimYcpZgUluQAg0m...", activated: true, activated_at: "2020-07-24 16:10:08", reset_digest: nil, reset_sent_at: nil> >> micropost = Micropost.where("user_id = ?", user.id) Micropost Load (0.5ms) SELECT "microposts".* FROM "microposts" WHERE (user_id = 1) ORDER BY "microposts"."created_at" DESC LIMIT ? [["LIMIT", 11]] => #<ActiveRecord::Relation [#<Micropost id: 301, content: "test", user_id: 1, created_at: "2020-07-24 17:11:12", updated_at: "2020-07-24 17:11:12">, #<Micropost id: 295, content: "Ipsa sapiente et eum omnis magnam assumenda aut fu...", user_id: 1, created_at: "2020-07-24 16:10:28", updated_at: "2020-07-24 16:10:28">, #<Micropost id: 289, content: "Atque eos aut minima commodi qui voluptatem adipis...", user_id: 1, created_at: "2020-07-24 16:10:28", updated_at: "2020-07-24 16:10:28">, #<Micropost id: 283, content: "Dolores labore nesciunt est suscipit.", user_id: 1, created_at: "2020-07-24 16:10:28", updated_at: "2020-07-24 16:10:28">, #<Micropost id: 277, content: "Libero consequatur eos aut est omnis qui quisquam ...", user_id: 1, created_at: "2020-07-24 16:10:28", updated_at: "2020-07-24 16:10:28">, #<Micropost id: 271, content: "Odit natus nesciunt dolorem sunt.", user_id: 1, created_at: "2020-07-24 16:10:28", updated_at: "2020-07-24 16:10:28">, #<Micropost id: 265, content: "Aut sed dolor autem asperiores aliquid voluptates ...", user_id: 1, created_at: "2020-07-24 16:10:28", updated_at: "2020-07-24 16:10:28">, #<Micropost id: 259, content: "Quia dolores necessitatibus labore et magnam.", user_id: 1, created_at: "2020-07-24 16:10:28", updated_at: "2020-07-24 16:10:28">, #<Micropost id: 253, content: "Quidem aut unde ut dolor omnis voluptatum.", user_id: 1, created_at: "2020-07-24 16:10:28", updated_at: "2020-07-24 16:10:28">, #<Micropost id: 247, content: "Aperiam ut harum neque nesciunt distinctio et dolo...", user_id: 1, created_at: "2020-07-24 16:10:28", updated_at: "2020-07-24 16:10:28">, ...]> >> micropost == user.microposts Micropost Load (0.4ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."created_at" DESC [["user_id", 1]] Micropost Load (0.3ms) SELECT "microposts".* FROM "microposts" WHERE (user_id = 1) ORDER BY "microposts"."created_at" DESC => true >> micropost == user.feed => true13.3.4 演習
1.マイクロポストを作成し、その後、作成したマイクロポストを削除してみましょう。次に、Railsサーバーのログを見てみて、DELETE文の内容を確認してみてください。
DELETE FROM "microposts" WHERE "microposts"."id" = ? [["id", 302]]
2.redirect_to request.referrer || root_urlの行をredirect_back(fallback_location: root_url)と置き換えてもうまく動くことを、ブラウザを使って確認してみましょう (このメソッドはRails 5から新たに導入されました)。
省略13.55マイクロポストのUIに対する統合テストがREDでエラー。
ERROR["test_micropost_interface", MicropostsInterfaceTest, 2.046640218999528] test_micropost_interface#MicropostsInterfaceTest (2.05s) ActionView::Template::Error: ActionView::Template::Error: Missing partial microposts/_form, application/_form with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :coffee, :jbuilder]}. Searched in: * "/home/ec2-user/environment/sample_app/app/views" app/views/static_pages/home.html.erb:2:in `_app_views_static_pages_home_html_erb___2042311693849903102_70052435259280' app/controllers/microposts_controller.rb:12:in `create' test/integration/microposts_interface_test.rb:15:in `block (2 levels) in <class:MicropostsInterfaceTest>' test/integration/microposts_interface_test.rb:14:in `block in <class:MicropostsInterfaceTest>'前の演習で移動したパーシャルが原因っぽい。
rails tutorial 13章の演習問題で疑問
こちらを参考に、13.3.2の演習の部分を訂正したらGREENに。13.5.5 演習
1.リスト 13.55で示した4つのコメント (「無効な送信」など) のそれぞれに対して、テストが正しく動いているか確認してみましょう。具体的には、対応するアプリケーション側のコードをコメントアウトし、テストが redになることを確認し、元に戻すと greenになることを確認してみましょう。
省略2.サイドバーにあるマイクロポストの合計投稿数をテストしてみましょう。このとき、単数形 (micropost) と複数形 (microposts) が正しく表示されているかどうかもテストしてください。ヒント: リスト 13.57を参考にしてみてください。
test "micropost sidebar count" do log_in_as(@user) get root_path assert_match "#{@user.microposts.count} microposts", response.body # まだマイクロポストを投稿していないユーザー other_user = users(:malory) log_in_as(other_user) get root_path assert_match "0 microposts", response.body other_user.microposts.create!(content: "A micropost") get root_path assert_match "1 micropost", response.body end13.59のテストがREDのエラー。
GREENになるはずのテストがRED。サーバー再起動しても、ターミナル作り直してもダメ。
Railsチュートリアル中にNameError: uninitialized constant Micropost::PictureUploaderが出た時の対処法
こちらを参考にspringを再起動。無事GREENに。13.4.1 演習
1.画像付きのマイクロポストを投稿してみましょう。もしかして、大きすぎる画像が表示されてしまいましたか? (心配しないでください、次の13.4.3でこの問題を直します)。
省略2.リスト 13.63に示すテンプレートを参考に、13.4で実装した画像アップローダーをテストしてください。テストの準備として、まずはサンプル画像をfixtureディレクトリに追加してください (コマンド例: cp app/assets/images/rails.png test/fixtures/)。リスト 13.63で追加したテストでは、Homeページにあるファイルアップロードと、投稿に成功した時に画像が表示されているかどうかをチェックしています。なお、テスト内にあるfixture_file_uploadというメソッドは、fixtureで定義されたファイルをアップロードする特別なメソッドです18 。ヒント: picture属性が有効かどうかを確かめるときは、11.3.3で紹介したassignsメソッドを使ってください。このメソッドを使うと、投稿に成功した後にcreateアクション内のマイクロポストにアクセスするようになります。
/test/integration/microposts_interface_test.rbassert_select 'input[type="file"]' # 無効な送信 assert_no_difference 'Micropost.count' do post microposts_path, params: { micropost: { content: "" } } end assert_select 'div#error_explanation' # 有効な送信 content = "This micropost really ties the room together" picture = fixture_file_upload('test/fixtures/rails.png', 'image/png') assert_difference 'Micropost.count', 1 do post microposts_path, params: { micropost: { content: content, picture: picture } } end assert assigns(:micropost).picture?13.4.2 演習
1.5MB以上の画像ファイルを送信しようとした場合、どうなりますか?
省略2.無効な拡張子のファイルを送信しようとした場合、どうなりますか?
省略13.4.3 演習
1.解像度の高い画像をアップロードし、リサイズされているかどうか確認してみましょう。画像が長方形だった場合、リサイズはうまく行われているでしょうか?
省略2.既にリスト 13.63のテストを追加していた場合、この時点でテストスイートを走らせると紛らわしいエラーメッセージが表示されることがあります。このエラーを取り除いてみましょう。ヒント: リスト 13.68にある設定ファイルを修正し、テスト時はCarrierWaveに画像のリサイズをさせないようにしてみましょう。
13.4.3 演習
1.本番環境で解像度の高い画像をアップロードし、適切にリサイズされているか確認してみましょう。長方形の画像であっても、適切にリサイズされていますか?
どう頑張ってもエラーに勝てなくてスキップ。
実装しようとしたらApplication errorになっちゃって。
しかしなぜか、13.4.4の内容は消したら本番環境で画像アップロード出来るように・・・
- 投稿日:2020-07-25T18:43:35+09:00
devise 導入 メモ
devise導入メモ
deviseの導入時の流れを簡単にメモ
流れ
- Gemのインストール
- フラッシュメッセージの追加(飛ばしてもOK)
- deviseのViewファイルのインストール
- Userモデルの作成
- Usersテーブルの作成
- ヘッダーの非表示 (飛ばしてもOK)
1. Gemのインストール
Gemfileにdeviseのgemを追加
gem 'devise'$ bundle installdeviseのインストール
$ rails generate devise:install2. フラッシュメッセージの追加(飛ばしてもOK)
<% if flash[:notice] %> <div class="alert alert-info"> <%= flash[:notice] %> </div> <% end %> <% if flash[:alert] %> <div class="alert alert-danger"> <%= flash[:alert] %> </div> <% end %>3. deviseのViewファイルのインストール
$ rails generate devise:views4. Userモデルの作成
$ rails g devise Userroutes.rbにdeviseのルーティングが追加される
routes.rbdevise_for :users5. Usersテーブルの作成
先程モデルを作成したのでテーブルを作成
$ rails db:migrateこの時点でdeviseの導入は完了!!
サインアップかサインインページにアクセスすればページが表示されます。6. ヘッダーの非表示 (飛ばしてもOK)
deviseを導入するといくつかdeviseのヘルパーメソッドが使えるようになるので
その1つを使ってサインインしていないユーザーにはヘッダーを非表示にします。ヘッダーがいくつかのページで表示されることを想定してpartial化されている場合
renderしている最後に「if current_user」を追加。<%= render 'partial/header' if current_user %>こうすることによって「current_user」がサインインしているかを条件式が確認してヘッダーを表示/非表示してくれます。
参考 devise系
devise公式GitHub
Rails deviseで使えるようになるヘルパーメソッド一覧
devise にusername カラムを追加し、usernameを登録できるようにする。
- 投稿日:2020-07-25T16:44:13+09:00
Active Admin 管理者画面からユーザー作成できない
経緯
rails g active_admin:resource userを実行し、
class DeviseCreateUsers < ActiveRecord::Migration[6.0] def change create_table :users do |t| t.string :email, null: false, default: "" t.string :encrypted_password, null: false, default: "" t.string :reset_password_token t.datetime :reset_password_sent_at t.datetime :remember_created_at t.timestamps null: false end add_index :users, :email, unique: true add_index :users, :reset_password_token, unique: true end endusersテーブルのカラムに合わせて
ActiveAdmin.register User do permit_params :email, :reset_password_token, :reset_password_sent_at, :remember_created_at endとpermit_paramsを書いて
フォーム入力後にユーザー作成ボタンを押したらユーザー作成できなかった。そこでadmin_users.rbにならってuser.rbを書き換えたところ
ActiveAdmin.register User do permit_params :email, :password, :password_confirmation index do selectable_column id_column column :email column :current_sign_in_at column :sign_in_count column :created_at actions end filter :email filter :current_sign_in_at filter :sign_in_count filter :created_at form do |f| f.inputs do f.input :email f.input :password f.input :password_confirmation end f.actions end end
- 投稿日:2020-07-25T16:09:54+09:00
WSL上で実行したRSpecにエラー(NotImplementedError:fork() function is unimplemented on this machine)が出る問題の解決法
ポートフォリオ作成のために勉強目的で作成していたプログラムでRSpecがエラーで動作しなかったので解決方法を記載します。
結論から先に書くとWSL1にはUbuntu 18.04をインストールしましょうということです。
環境
- ホストOS:Windows 10 64bit
- 仮想環境:WSL1
- ゲストOS:Ubuntu 20.04 LTS
- Ruby:Ruby2.6.6
- Rails:Rails5.2.4.3
使用しているGem
- better_errors
- byebug
- capybara
- factory_bot_rails
- pry-byebug
- rspec-rails
- spring-commands-rspec
- sqlite3
- webdrivers
全部だと多いのでテストグループに記載しているgemのみです
エラー内容と解決方法
まずはWSL1上で開発していたプログラムをRSpecを使ってテストを開始しました。
しかしNotImplementedError:fork() function is unimplemented on this machineというエラーが出て動作しません。
Got 0 failures and 2 other errors: 1.1) Failure/Error: visit '/' NotImplementedError: fork() function is unimplemented on this machine # ./spec/system/users_spec.rb:10:in `block (4 levels) in <top (required)>' 1.2) Failure/Error: @pid = Kernel.fork { # Children of the forked process will inherit its process group # This is to make sure that all grandchildren dies when this Process instance is killed ::Process.setpgid 0, 0 if leader? if @cwd Dir.chdir(@cwd) end exec_r.close NotImplementedError: fork() function is unimplemented on this machineエラーが出たものと同じソースコードを他のPC(Ubuntu 20.04)上で実行するとエラーもなく通ります。
ここで同じバージョンのOSで動くのでWSLが原因ではと考えます。
次にエラー名で検索するとGitHubのWSLリポジトリのIssueに同じエラーが出るというものがありました。
https://github.com/microsoft/WSL/issues/5238RSpecでエラーが出た訳では無いですがWSL上でUbuntu 20.04を起動してエラーが出た点というのは一致しています。
なのでWSL1上でUbuntu 20.04を起動しているのが原因ではと考えます。
*ちなみにIssueにはWSL2を利用した場合は動作したと記載があるのでWSL2が利用できる場合は利用したほうが簡単に済むと思います。調べてみるとQiitaにWSL1にはUbuntu 20.04をインストールしないほうが良いという記事がありました。
https://qiita.com/AumyF/items/eaf42dd3345a2285ff9eRSpecでエラーが出るとは書いていないのでこれが原因かはわかりませんがとりあえずUbuntu 18.04をインストールしRSpecを実行してみるとエラーが無く通りました。
やっぱり最新版を使用するより安定している少し古いバージョンの方が開発には向いているかもと思いました。
これを教訓に最新版を使用する際は気をつけます。最後にQiita初投稿&初心者なのでどこか問題点があれば教えていただきたいです。
- 投稿日:2020-07-25T14:45:13+09:00
チャットアプリ制作
個人の学習の知見を広げるため、チャットアプリを制作しました。
アプリの概要
・ユーザーの登録ができる
・ユーザーがグループを作成できる
・グループを指定して、メッセージを送ることができる使用技術
・Ruby
・Ruby on Rails
・JavaScript
・MySQL
・AWS
・nginx
・unicorn
・Capistrano本番環境のリンク
githubのリンク
https://github.com/mitsugu3/ChatSpace
感想
アプリ制作の流れを掴むことができた。
AWSで、本番環境にあげるのが
シークレットキーなどの知識が必要だったので難しく感じたが、
検索記事を参考に自走することができた。
- 投稿日:2020-07-25T14:32:54+09:00
slickでスライドショーをお洒落に実装したかった。
スライドショーを実装するためにslickを導入
詰まりまくったことを解決したので投稿
環境
rails : 6.0.3.2
ruby : 2.6.6
Docker, docker-compose参考URL
http://kenwheeler.github.io/slick/
先にできていること
jQueryの導入
slick導入編
slick本体をインストール
qiita.rb$ docker-compose run --rm web npm i slick-carousel なんやかんや 40 packages are looking for funding run `npm fund` for details found 0 vulnerabilitiesapplocation.html.erbのhead要素に追記
qiita.rb<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.css"/> <link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick-theme.css"/> <script type="text/javascript" src="//cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.min.js"></script>jsファイル
slideの表示方法の設定については公式に書かれているので、一部だけ紹介。
slickの読み込みがどうもうまくいかなかったので、多分他の人とは違う書き方だと思う。slideshow.jsconst jQuery = require('jquery'); require('slick-carousel'); (function($) { $(function() { $('.theTarget').slick({ dots: true, autoplay: true, fade: true, autoplaySpeed: 3000 }); }) })(jQuery);viewにスライドショーで表示させたい画像の記述
show.html.erb<div class = "theTarget"> <%= image_tag 'abc.png' %> <%= image_tag 'def.png' %> <%= image_tag 'ghi.png' %> <%= image_tag 'jkl.png' %> <%= image_tag 'mno.png' %> </div> <%= javascript_pack_tag 'slideshow.js' %> #jsファイルの読み込みjsの読み込みのエラーが出た場合。
今回であれば、bin/webpackを実行してコンパイルすればエラーを解決できた。
webpackを理解できてないから、わざわざなんでこれをしないといけないのかが分からないqiita.rb% docker-compose run --rm web bin/webpack Version: webpack 4.43.0 Time: 15190ms Built at: 07/24/2020 11:18:43 PM
- 投稿日:2020-07-25T13:53:29+09:00
Rails アプリケーション作成手順
概要
Dockerを使ってRails開発を始めれるように自分用のメモとして作成しました。
使用するDBはmysqlです。1.アプリケーション用のbuild contextを作成
フォルダの名前:アプリケーション名
build context内:Dockerfile, docker-compose.yml, Gemfile Gemfile.lock
を作成します。2.rails new を実行する
コマンド$docker-compose run web rails new . --force --database=mysql --skip-bundle3.database.ymlを編集する
database.ymldefault: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: password # docker-compose.ymlのMYSQL_ROOT_PASSWORD host: db # docker-compose.ymlのservice名4.docker buildしてGEMを読み込む
コマンド# コンテナをビルド $ docker-compose build # コンテナを起動 $ docker-compose up -dDBを作成
コマンド$ docker-compose run web rails db:createブラウザでlocalhost:XXXXにアクセスしてサーバ起動を確認する。
- 投稿日:2020-07-25T13:50:21+09:00
Active Admin リソースの削除
- 投稿日:2020-07-25T00:11:05+09:00
RailsでGoogleMapsAPIを表示・ピン表示まで
はじめに
過去に自分のポートフォリオでGoogleMapsAPIを利用していましたが、流れを忘れていたのでリマインドです。
環境
rails 5.2.3
ruby 2.6.3今回すること
・現在地情報から経度緯度を取得しマーカーを表示する。
・取得した一覧情報をjson形式に変え、マーカーとして地図上に配置。
・地図の表示表示させるコントローラー作成、今回アクション名はsearchで。
spaces_controller.rbdef search @spaces = Space.all endモデルの作成、住所を入力後緯度経度を自動取得させる。
space.rbclass Space < ApplicationRecord geocoded_by :address after_validation :geocode, if: :address_changed? endschema.rbcreate_table "spaces", force: :cascade do |t| t.string "address" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.float "latitude" t.float "longitude" endMAPを表示させるscript
javascriptfunction initMap() //マップを表示させる箇所 var target = document.getElementById('gmap'); //マップ表示 var map = new google.maps.Map(document.getElementById('gmap'), { center: {lat: 35.681167, lng: 139.767052},//中心点設定 zoom: 8//mapの拡大率設定 }); //現在地マーカーの作成 //現在地取得できない場合 if(!navigator.geolocation){ infoWindow.setPosition(map.getCenter()); infoWindow.setContent('Geolocation に対応していません。'); infoWindow.open(map); } navigator.geolocation.getCurrentPosition(function(position) { //現在地の軽度緯度取得 var pos = { lat: position.coords.latitude, lng: position.coords.longitude }; var mark = new google.maps.Marker({ //ドロップダウンアニメーションの設定 animation: google.maps.Animation.DROP, position: pos, map: map, // 現在地ピンのアイコン作成。今回デフォルトのデザインは複数のマーカーに使用するので変更。 icon: { fillColor: "rgb(48, 255, 176)", fillOpacity: 1.0, path: google.maps.SymbolPath.BACKWARD_CLOSED_ARROW, scale: 4, strokeColor: "green", strokeWeight: 1.0 } }); }, function() { infoWindow.setPosition(map.getCenter()); infoWindow.setContent('Error: Geolocation が無効です。'); infoWindow.open(map); }); //複数マーカー //一覧のデータをjson形式に var spaces = #{raw @spaces.to_json}; var marker = []; var info; for(var i = 0; i < spaces.length; ++i) { //一覧から一つずつ経度緯度の情報を取り出してマーカー作成 spot = new google.maps.LatLng({lat: spaces[i].latitude, lng: spaces[i].longitude}); marker[i] = new google.maps.Marker({ position: spot, map: map, animation: google.maps.Animation.DROP }); markerEvent(i); } //複数マーカーのhover時イベント function markerEvent(i) { marker[i].addListener('mouseover', function() { var target = $('#' + (i + 1)); $(".highlight").removeClass("highlight"); target.addClass("highlight"); var position = target.offset().top - 280; $('body,html').animate({scrollTop:position}, 400, 'swing'); }); } //------------------------------------------------------------- } script src="https://maps.googleapis.com/maps/api/js?key=#{ENV[""]}&callback=initMap" async defer今回はテンプレートエンジンをslimにしてその中に直接書いているのでデータの変数格納のあたりが通常と違っているので注意。
gemのgeocoderを使用すると名前から経度と緯度を取得するのが非常に楽ですが、精度が悪く、番地単位まで表示してくれないので今回はGoogle Geocodingを使用しています。