20200725のRailsに関する記事は14件です。

Google Chartがモーダルで上手く表示できない時

簡単にグラフが作れて人気なGoogle Chart。その中の「GeoChart」は都道府県別の日本地図を作成できます。以下のように都道府県別で色分でき、カーソルを当てるとパラメータを表示してくれます。
map.png

やりたいこと

今回は既にあるオリジナルサービス内に、ユーザー詳細ページにあるリンクをクリックするとモーダルでユーザーのデータが反映された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">&times;</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.rb
def show
    gon.map_data = @user.prefecture_data
end

prefecture_dataメソッドはmodels/user.rb内に作ったメソッドで、都道府県に行ったデータを取得していると思ってください。

問題

さあ準備ができたので、実際にブラウザでリンクをクリックしてみましょう。

スクリーンショット 2020-07-25 23.41.13.png

あ、あれ!!??(・_・;

上手く表示されていません…
モーダルタイトルの「ゲストユーザーがイベントで訪れた都道府県」は表示されていますが肝心な日本地図は表示されませんでした。

解決

どうやら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-25 23.40.53.png

無事成功しました!

参考

Google maps APIを使ったmapをBootstrapのmodal上で表示させる

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails][IRB][Pry]SourceAnnotationExtractor is deprecated 解決法

起こったこと

Rails6binding.pry などIRBTab 補完しようとすると

以下のようなエラーが出る。
(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

参考

https://github.com/rails/rails/issues/37775

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Herokuへのデプロイ後、HTTPエラー500が出た

Ruby on Railsで簡単な掲示板アプリを作成し、初めてherokuのデプロイに成功した。

ただ、herokuでsqliteが未対応なことを知らなかったり、フロント周りをslimで初実装した為に、デプロイ前後で少々エラーに苦しんだので、備忘録として解決方法を残す。

sqliteでherokuデプロイ失敗した時の対処法

恐らくrailsでwebアプリを作成した際、デフォルトではsqliteがDBとして設定されていると思う。
そのままデプロイしようとすると失敗するので、
エラー参考記事1エラー参考記事2herokuデプロイの手順

以下を削除

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的に弱いサイトのサムネなども検索できる。
参考になりそうなサムネをクリックすると解決できるかも..??

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

都道府県 + 市町村をチェックボックスで複数選択。登録する方法。

やりたいこと

チーム開発で、一人のマッサージ師に対して複数の出張範囲を登録出来る機能を実装した。モデルの関係性など勉強になったのでメモ。完全自分用です。

モデルの関係性

マッサージ師

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

ややこしいですが図にするとこんな感じ。

スクリーンショット 2020-07-25 20.28.36.png

作業の流れ

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

end

seeds.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に入りました。
スクリーンショット 2020-07-25 20.54.20.png
都道府県 + 市町村だからとんでもなくデータ多いです。写真は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 %>

こうなります。

スクリーンショット 2020-07-25 21.20.08.png

ちなみにコントローラーはこうなってます。

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」は必要ありません。

途中で眠くなったわ。。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsアプリを速度改善する①

EC2でデプロイ後にレスポンス速度を確かめる

herokuでのデプロイは、起動までのレスポンスが遅くユーザーがその間に離脱してしまうのを恐れたので、AWS(EC2)にデプロイしました。

といいつつも、アプリの起動が遅く感じられたのでトップページが表示されるまでのレスポンス速度を測ってみました。

PageSpeed Insightsで測ってみた結果

モバイル

image.png

パソコン

image.png

使っていないCSSファイルを全部削除

image.png

上記のみ残して、CSSファイルを全削除しました。

モバイル

image.png

パソコン

image.png

6~7パーセント改善されました。

モバイルはまだまだ改善の余地ありなので、他にも試していこうと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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]]
=> true

13.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:00

2.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]]
=> nil

13.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_AssociationRelation

13.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
=> true

13.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
  end

13.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.rb
assert_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の内容は消したら本番環境で画像アップロード出来るように・・・

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

devise 導入 メモ

devise導入メモ

deviseの導入時の流れを簡単にメモ:man_tone2:

流れ

  1. Gemのインストール
  2. フラッシュメッセージの追加(飛ばしてもOK)
  3. deviseのViewファイルのインストール
  4. Userモデルの作成
  5. Usersテーブルの作成
  6. ヘッダーの非表示 (飛ばしてもOK)

参考 devise公式GitHub

1. Gemのインストール

Gemfileにdeviseのgemを追加

gem 'devise'
$ bundle install

deviseのインストール

$ rails generate devise:install

2. フラッシュメッセージの追加(飛ばしても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:views

4. Userモデルの作成

$ rails g devise User

routes.rbにdeviseのルーティングが追加される

routes.rb
devise_for :users

5. 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を登録できるようにする。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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
end

usersテーブルのカラムに合わせて

ActiveAdmin.register User do
  permit_params :email, :reset_password_token, :reset_password_sent_at, :remember_created_at
end

とpermit_paramsを書いて
ユーザーを作成する(失敗).png
フォーム入力後にユーザー作成ボタンを押したらユーザー作成できなかった。

そこで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

以下のように表示が変わり
ユーザーを作成する(成功).png
ユーザー作成できました!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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/5238

RSpecでエラーが出た訳では無いですがWSL上でUbuntu 20.04を起動してエラーが出た点というのは一致しています。

なのでWSL1上でUbuntu 20.04を起動しているのが原因ではと考えます。
*ちなみにIssueにはWSL2を利用した場合は動作したと記載があるのでWSL2が利用できる場合は利用したほうが簡単に済むと思います。

調べてみるとQiitaにWSL1にはUbuntu 20.04をインストールしないほうが良いという記事がありました。
https://qiita.com/AumyF/items/eaf42dd3345a2285ff9e

RSpecでエラーが出るとは書いていないのでこれが原因かはわかりませんがとりあえずUbuntu 18.04をインストールしRSpecを実行してみるとエラーが無く通りました。

やっぱり最新版を使用するより安定している少し古いバージョンの方が開発には向いているかもと思いました。
これを教訓に最新版を使用する際は気をつけます。

最後にQiita初投稿&初心者なのでどこか問題点があれば教えていただきたいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

チャットアプリ制作

個人の学習の知見を広げるため、チャットアプリを制作しました。

アプリの概要

・ユーザーの登録ができる
・ユーザーがグループを作成できる
・グループを指定して、メッセージを送ることができる

使用技術

・Ruby
・Ruby on Rails
・JavaScript
・MySQL
・AWS
・nginx
・unicorn
・Capistrano

本番環境のリンク

18.178.232.222

githubのリンク

https://github.com/mitsugu3/ChatSpace

感想

アプリ制作の流れを掴むことができた。
AWSで、本番環境にあげるのが
シークレットキーなどの知識が必要だったので難しく感じたが、
検索記事を参考に自走することができた。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 vulnerabilities

applocation.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.js
const 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
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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-bundle

3.database.ymlを編集する

database.yml
default: &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 -d

DBを作成

コマンド
$ docker-compose run web rails db:create

ブラウザでlocalhost:XXXXにアクセスしてサーバ起動を確認する。

スクリーンショット 2020-08-09 16.18.37.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Active Admin リソースの削除

結論

$ rails destroy active_admin:resource モデル名

これで削除できます。

ググってもなかなか出てこなかったので、書きました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsでGoogleMapsAPIを表示・ピン表示まで

はじめに

過去に自分のポートフォリオでGoogleMapsAPIを利用していましたが、流れを忘れていたのでリマインドです。

環境

rails 5.2.3
ruby 2.6.3

今回すること

・現在地情報から経度緯度を取得しマーカーを表示する。
・取得した一覧情報をjson形式に変え、マーカーとして地図上に配置。
・地図の表示

表示させるコントローラー作成、今回アクション名はsearchで。

spaces_controller.rb
  def search
    @spaces = Space.all
  end

モデルの作成、住所を入力後緯度経度を自動取得させる。

space.rb
class Space < ApplicationRecord
  geocoded_by :address
  after_validation :geocode, if: :address_changed?
end
schema.rb
create_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"
end

MAPを表示させるscript

javascript
  function 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を使用しています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む