20191028のRailsに関する記事は18件です。

railsでサジェスト機能を実装してみた

railsでサジェスト機能を実装した時のメモ?

autocomplete系のgemが軒並みメンテされていなかったので、jquery-uiで実装していきます。

動作環境

rails 5.2.2.1
jquery-ui-rails 6.0.1

やること

company属性を持つUserというモデルを想定し、
User作成画面でcompanyのテキストフィールドに入力した際、
既にDBに存在するデータをもとに候補をサジェストする機能を実装します?

こういうやつ↓
サジェスト.mov.gif

Gemfile

Gemfileに下記を追加しbundle install

Gemfile
gem 'jquery-ui-rails'
bundle install

application.js

下記を追加

/assets/javascripts/application.js
//= require jquery-ui/widgets/autocomplete

application.scss

下記追加

/assets/stylesheets/application.scss
 @import "jquery-ui/autocomplete";
 @import "jquery-ui/theme";
 @import "jquery-ui/menu";

筆者環境だと、theme、menuを外すと表示が崩れました?

routes.rb

サジェストの配列を返すルートを追加します。

routes.rb
  resources :users do
    get '/autocomplete_company/:company', on: :collection, action: :autocomplete_company
  end

モデル

前方一致検索のscopeを追加します。

user.rb
  # 前方一致検索
  scope :by_company_like, lambda { |company|
    where('company LIKE :value', { value: "#{sanitize_sql_like(company)}%"})
  }

コントローラー

サジェストの候補を返すaction追加
受け取ったパラメータをもとにサジェストしたい文字列の配列を返すようにします。

user_controller.rb
  def autocomplete_company
    # params[:company]の値でUser.companyを前方一致検索、company列だけ取り出し、nilと空文字を取り除いた配列
    companies = User.by_company_like(autocomplete_params[:company]).pluck(:company).reject(&:blank?)
    render json: companies
    # レスポンスの例: ["てすと1会社","てすと2会社","てすと3会社"]
  end

  private

    def autocomplete_params
      params.permit(:company)
    end

ビュー

autocompleteのsourceに
サジェスト候補の配列を取得する関数をセット。

_form.html.slim
= form_with(model: @user, local: true) do |form|
 .form-group
  = form.label :company
  = form.text_field :company
  / id='user_company'で生成される

javascript:
  $(function() {
    const dataList = function(request, response) {
      $.ajax({
        url: '/users/autocomplete_company/' + request.term,
        dataType: 'json',
        type: 'GET',
        cache: true,
        success: function(data) {
          response(data);
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
          response(['']);
        }
      });
    }

    // #user_companyの部分は必要に応じてidなり指定してください
    $('#user_company').autocomplete({
      source: dataList,
      autoFocus: true, // 自動的に先頭の項目にフォーカスするか
      delay: 300, // 入力してからサジェストが動くまでの時間(ms)
      minLength: 2 // 2文字入力しないとサジェストが動かない
    })
  });

テキストフィールドの内容に応じて、動的に内容を変える必要がなければ
dataListにサジェストしたい文字列の配列を直接入れればOKです!

javascript:
  $(function() {
    const dataList = ["こうほ1","こうほ2"];
  });

まとめ

jquery-uiを使って、サジェスト機能を実装しました。
今回は説明のため、Viewに直接javascriptを書いてますが
別ファイルにしたり、ヘルパーを切り出したりすると良いと思われます☺️

間違っているところがあればご指摘ください!

autocompleteのドキュメント

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

Rails5.2 + Vue.js + Dockerでプロジェクトを作成

はじめに

Railsを使っていてVueも一通り学んだのでRailsとVueを使えるように環境構築してみようと思い勉強してみたことをアウトプット。

Rubyのバージョンは2.5.3
Railsのバージョンは5.2.3
DBはMysqlを使用

Railsのプロジェクトを作成するディレクトリを事前に作成しておく
$ mkdir <任意のフォルダ名>
フォルダを作成したら作成したディレクトリに移動しておく

Docker用のファイルの作成

Dockerのコンテナを作成するためのファイルを作成

Dockerfile
docker-compose.yml
Gemfile
Gemfile.lock
の4つのファイルを作成する。

Dockerfile
FROM ruby:2.5.3

RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - && apt-get update && \
    apt-get install -y nodejs --no-install-recommends && rm -rf /var/lib/apt/lists/*

RUN apt-get update -qq && apt-get install -y build-essential libpq-dev

RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && apt-get install -y yarn

RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - && \
    apt-get install nodejs

RUN yarn add node-sass

RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
COPY . /app

docker-compose.yml
version: '3'
services:
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/app
    ports:
      - 3000:3000
    depends_on:
      - db
    tty: true
    stdin_open: true
  db:
    image: mysql:5.7
    volumes:
      - db-volume:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
volumes:
  db-volume:
Gemfile
source 'https://rubygems.org'
ruby '2.5.3'

Gemfile.lock
はbuildした後に自動的に記述されるので空にしておく。(ファイルは必要)

この4つのファイルを作成し、先ほど作成したディレクトリに置く。

Railsプロジェクトの作成

次にRailsのプロジェクトを作成するため次のコマンドを実行
$ docker-compose run web rails new . --force --database=mysql
(rails newの . は現在いるディレクトリにそのままプロジェクトを作成するというもの)

プロジェクトの作成が終わったらdocker-compose psでコンテナが作成されているか確認。
次にRailsプロジェクトのdatabase.ymlを編集します。

config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  host: db

passwordとhostの部分をdocker-compose.ymlの記述と合わせます。

$ docker-compose upコマンドでコンテナを立ち上げ、localhost:3000に接続し、RailsのHello World画面が表示されれば無事成功です!

Vue.jsの導入

vue.jsをRailsで使用できるようにするためにまずはWebpackerの導入が必要。Gemfileに以下を追加します。

Gemfile
gem 'webpacker'

記述したら

$ docker-compose run web rails webpacker:installを実行

自分の場合、Gemfileの記述を
gem 'webpacker', github: 'rails/webpacker'
とするとyarnエラーが出てインストールができませんでした。

インストールが完了したらいろいろRailsのプロジェクトにファイルが追加されると思います。

次にVueをインストールしていきます。
$docker-compose run web rails webpacker:install:vue

これでVue.jsの導入が完了しました。

vue.jsファイルのビルド

次にVue.js関連のコンポーネントをJavascriptにコンパイルするため
$ docker-compose run web bin/webpackコマンドを実行します。

RailsのViewsファイルに
<%=javascript_pack_tag 'hello_vue'%>と記述し問題なく表示されていれば成功です!

参考
dockerでrails+vueの環境を作ったので解説
Rails5.2 + Docker環境にVue.js (Webpacker) を導入する

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

Rails: validates: 指定した値の時だけ複数カラムでuniquenessを制約を掛ける方法備忘録

ケース

一つのfugaに対して紐付く複数のhogeの内、is_piyoがfalseであれば幾らでも登録できるが、trueのものは一つしか登録できないようにしたい

コード

app/models/user.rb
class Hoge < ApplicationRecord
  belongs_to :fuga

  validates :is_piyo,
            inclusion: { in: [true, false] },
            uniqueness: { scope: :fuga_id,
                          conditions: -> { where(is_piyo: true) }}
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rubyの予約語を使っちゃったカラム名をfactory_botでテストしたい

例えば class というカラムを作ってしまっけれど factory_bot でテストしたいと思ったら…

factory :reservation do
  add_attribute(:class) { 'A組' }
end

add_attribute

"Getting Started" に書いてある!
https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#method-name--reserved-word-attributes

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

railsでfaviconを3ステップで実装してみた

STEP1

下記ファイルに<%= favicon\_link\_tag('favicon.ico') %>を追加する

application.html.erb
<!DOCTYPE  html>

<html>
<head>
  <title>Sample</title>

  <%=  favicon\_link\_tag('favicon.ico') %>//この1行を追加する

  </head>

  [省略]

STEP2

下記のサイトでアイコンにしたい画像を変換する
https://ao-system.net/favicon/
favicon.icoが生成される

STEP3

assets/assets/images配下にfavicon.icoファイルを設置する
スクリーンショット 2019-10-28 21.17.20.png

あとはサーバーを再起動すれば実装されています!!

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

【rails】かんたんログイン機能導入方法

現在railsでポートフォリを作成中ですが、よりスムーズに使ってほしいためにこの機能を導入したくなったので作りました。
若干手抜き感が否めないですが、一応使えます。

これはdivise導入済みで進めていきます。

まずはテストユーザーで新規登録します。

name:テストユーザー
email:test@example.com
password:testtest

ログインを簡単にする機能なのでまずは登録ないと始まりません。

view側を編集

もともとviews/devise/sessions/new.html.slimというファイルがありますが中身を真似て、
views/devise/sessions/_testuser.html.slimというファイルを作ります。

_testuser.html.slim
    h2
      | かんたんログイン
    = form_for(resource, as: resource_name, url: session_path(resource_name)) do |f|
      .field
        =f.hidden_field :email ,value: "test@example.com"
        =f.hidden_field :password ,value: "testtest"
      .actions
        = f.submit "かんたんログイン"

このように書いてviews/devise/registrations/new.html.slim

new.html.slim
.......
= render 'devise/sessions/testuser'

これで新規登録画面にかんたんログインボタンが表示されるようになります。

編集ボタンを隠す

私の場合はviews/users/show.html.slimにユーザー詳細画面がありますがテストユーザーのみ編集ボタンをを隠したいと思います

show.html.slim
.....
 - unless @user.email == "test@example.com"
  = link_to "edit",edit_user_registration_path

これではurlに直接打ち込むとアクセスできてしまうのが注意です。

deviseに対応したコントローラーを導入

$ rails g devise:controllers users

ルーティングの編集

userのコントローラーを作ったので、そこにアクセスするようにルーティングを編集します。

routes.rb
  devise_for :users, controllers: {
    registrations: 'users/registrations'
  }

コントローラー内を編集

テストユーザーを編集、削除されてほしくないので制限する。

registrations_controller.rb
......
before_action :forbid_test_user, {only: [:edit,:update,:destroy]}
......

  private
  def forbid_test_user
      if @user.email == "test@example.com"
        flash[:notice] = "テストユーザーのため変更できません"
        redirect_to root_path
      end
  end
.......

これによりかんたんログイン機能ができるようになります。
参考:【学習アウトプット2】離脱率を下げる!かんたんログイン機能の実装

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

Dockerで起動したRails(DB:postgres)のDBにDBeaverで接続する

はじめに

Dockerで作り始めたRailsアプリのデータベースをpostgresにしたので
Sequel Proよろしく中身を見に行くか〜!と思って簡単に考えていたら
思ったよりも大変だったのでまとめておく。
というより前の記事のせいで苦労した

環境

  • MacOS Mojave 10.14.5
  • Rails 5.2.3
  • ruby 2.5.7
  • postgres 11

設定

ここでの設定はDockerでRailsの環境構築してHerokuへデプロイするで紹介されている内容と一緒になります。

Docker-compose.yml

docker-compose.yml
version: '3'
services:
  db:
    image: postgres:11
    ports:
      - '5432:5432'
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: test_db
    volumes:
      - postgresql-data:/var/lib/postgresql/data
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
volumes:
  postgresql-data:
    driver: local

database.yml

config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password:
  pool: 5

development:
  <<: *default
  database: myapp_development

test:
  <<: *default
  database: myapp_test

production:
  <<: *default
  database: myapp_production
  username: myapp
  password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>

DBeaverのインストール

こちらの記事を参考にインストールしてください。

DBeaverを使ってpostgresへ接続

  • dockerでRailsアプリの起動
$ docker-compose start
  • DBeaverを起動して設定する 新しい接続を作成する.png 新しい接続を作成する-2.png

テスト接続に成功すると
Connection_Test_と_新しい接続を作成する.png

こんな感じになる。
接続が完了したら、終了を押して完了させる。

データベースの情報を表示させる

無事にデータベースへの接続が完了したら
DBeaver_6_2_3_-_myapp_development.png
DBeaver_6_2_3_-_public.png
DBeaver_6_2_3_-_users.png
これでデータベースに保存されているカラムの内容が表示されます。
もちろん書き換えもできます。

FATAL: role “postgres” does not exist と出る時

結論は、「他のpostgresサーバーが5432ポートで起動している」ため
postgresのコンテナサーバーへの接続にエラーが出ているようです。

まずは基本に立ち返って、エラー文に書いてあることを解消していきます。
こちらの記事を参考に、データベースにrole postgresがあるか確認しにいきます。

  • 稼働しているコンテナの状況を確認
$ docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
c920fadb8d27        application_web     "entrypoint.sh bash …"   30 hours ago        Up 55 minutes       0.0.0.0:3000->3000/tcp   application_web_1
2479f579d66e        postgres:11         "docker-entrypoint.s…"   30 hours ago        Up 55 minutes       0.0.0.0:5432->5432/tcp   application_db_1

データベースのコンテナの名前は"application_db_1"のようですね。
(名前はそれぞれの環境によって異なります)

  • データベースのコンテナに入る
$ docker exec -it application_db_1 bash
root@2479f579d66e:/# ここでコマンド待ちの状態になる
  • データベースにアクセスする
psql -U postres を実行する

root@2479f579d66e:/# psql -U postgres
psql (11.5 (Debian 11.5-3.pgdg90+1))
Type "help" for help.

postgres=# ここでコマンド待ちの状態になる
  • roleの状態を確認する
\du を実行する

postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

postgres=# 

どうやら、postgresは存在するようです。
原因は他にあるようですが・・・?

他のpostgreインスタンスが動いていた

こちらの記事では、同じような問題に対して
The problem was simple enough that my computer was already running an instance of Postgres that I was not aware was still running (not inside Docker) on :5432, checked with:
と説明されています。コマンドも示されているので試してみましょう。
(ターミナルで実行してください)

$ lsof -n -i:5432 | grep LISTEN
postgres  419 user_name    5u  IPv6 0xe1a2b61a846df097      0t0  TCP [::1]:postgresql (LISTEN)
postgres  419 user_name    6u  IPv4 0xe1a2b61a8514b617      0t0  TCP 127.0.0.1:postgresql (LISTEN)
com.docke 594 user_name   18u  IPv6 0xe1a2b61a96bd6f57      0t0  TCP *:postgresql (LISTEN)

一番下のcom.dockeがdockerで動かしているデータベースのコンテナのようですが
他に2つ動いているようです。(実際にはPIDが419で同じなので1つです)
先ほどの記事では、他のposgresインスタンスをストップさせれば接続できるようなので
早速ストップさせてみます。

  • postgresインスタンスの状態を確認する
$ pg_ctl status
pg_ctl: server is running (PID: 419)
/usr/local/Cellar/postgresql/11.5/bin/postgres "-D" "/usr/local/var/postgres"

先ほどと同じPIDのサーバーが動いていることが確認できました。
こいつをストップさせましょう。

  • postgresインスタンスをストップさせる
$ pg_ctl stop -D "/usr/local/var/postgres" -m s
waiting for server to shut down.... done
server stopped

止まったようですね!本当に止まっているか、念の為確認しておきましょう

$ pg_ctl status
pg_ctl: server is running (PID: 76742)
/usr/local/Cellar/postgresql/11.5/bin/postgres "-D" "/usr/local/var/postgres"

新たに生まれ落ちているようですね・・・自動再起動しているようです。
とりあえずもう一度削除を試みますが・・・

$ pg_ctl stop -D "/usr/local/var/postgres" -m s
waiting for server to shut down............................................................... failed
pg_ctl: server does not shut down
HINT: The "-m fast" option immediately disconnects sessions rather than
waiting for session-initiated disconnection.

$ pg_ctl stop -D "/usr/local/var/postgres" -m fast
waiting for server to shut down............................................................... failed
pg_ctl: server does not shut down

$ pg_ctl stop -D "/usr/local/var/postgres" -m i
waiting for server to shut down............................................................... failed
pg_ctl: server does not shut down

stopのオプションたちを全て試してみるも、posgresインスタンが止まらないようです。
これは困った。

lanchctlでなんとかした

こちらの記事で紹介されているコマンドでpostgresインスタンスの削除を試みます。

$ launchctl unload -w ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist

$ pg_ctl status
pg_ctl: no server running

やりました!postgresインスタンスを削除できたようです!
これでもう一度、コンテナを立ち上げ直してDBeaverから接続を試すと、成功するはずです!

立ち上がっていたインスタンスは何者か?

前の記事でサーバーを建てて放置していたのが原因っぽいです。
終わったら片付けることは大事ですね・・・

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

Railsアプリ〜デプロイへの道〜その③Capistrano3設定編【ConoHa VPS・CentOS・Capistrano3・Nginx・Unicorn】

Railsアプリケーションをデプロイした時の手順まとめ第3弾です。
Railsアプリ〜デプロイへの道〜はこの記事でいったん完結します。

今回はnginxのインストールからCapistrano3の設定、デプロイまで一気に紹介するので、
今までよりボリュームが多いです。
てんこ盛りです。

前回、前々回同様こちらの記事がベースとなっています。

https://qiita.com/ryo2132/items/f62690f0b16ec11270fe

これまでの記事同様、この記事は基本的に手順を記したものなので(僕の理解が不十分であることも否めませんが)、詳しい説明は省いています。
背景などを理解したい方は、ぜひ引用元の記事(リンク先記事)をご覧ください。

〈関連記事〉
Railsアプリ〜デプロイへの道〜その①リモートサーバーへのSSH接続編
Railsアプリ〜デプロイへの道〜その②Ruby・MySQLインストール編

開発環境

・Mac OS

・Rails 5.2.3

・Ruby 2.5.1

・ConoHa VPS

・CentOS 7.6

・Capistrano3

・Nginx

・Unicorn

Nginx

WebサーバーNginxのインストールおよび設定を行います。
〈参考〉
https://koooza.net/post-382
https://qiita.com/glvty83/items/abd99a6b712e4e006af1

1.インストール

yumで一発です。
サーバー

$ cd ~
$ sudo yum install nginx
#確認。バージョン出ればOK
$ nginx -v

2.設定ファイルの編集

〈参考〉
https://qiita.com/naoki_mochizuki/items/657aca7531b8948d267b

リクエストの処理方法、webアプリのディレクトリ設定等を行います。

まずファイルを作成。

$ cd /etc/nginx/conf.d/
$ sudo vi hoge_app.conf # 名前は任意。webアプリの名前など

続いてファイルの中身を以下のように修正してください。

hoge_appの部分は任意の名称に、serer_nameの部分はconohaのipアドレスに変えてください。

#各種ログのディレクトリ設定
  error_log  /var/www/hoge_app/current/log/nginx.error.log;
  access_log /var/www/hoge_app/current/log/nginx.access.log;
#処理を受け取る最大許容量
  client_max_body_size 2G;
  upstream app_server {
# 連携するunicornのソケットのパス
    server unix:/var/www/hoge_app/current/tmp/sockets/.unicorn.sock fail_timeout=0;
  }
  server {
    listen 80;
    server_name xxx.xxx.xxx.xxx; # conohaのipアドレス
#次のリクエストが来るまでの待ち時間(秒
    keepalive_timeout 5;
#静的ファイルを読みに行くディレクトリ
    root /var/www/hoge_app/current/public;
#キャッシュのディレクトリ
    try_files $uri/index.html $uri.html $uri @app;
    location @app {
      # HTTP headers
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_redirect off;
      proxy_pass http://app_server;
    }
#エラーページを設置する場所
    error_page 500 502 503 504 /500.html;
    location = /500.html {
      root /var/www/hoge_app/current/public;
    }
  }

 /var/www/hoge_app/フォルダはのちほど作成します。

3.ファイアウォールのポート開放

ファイアウォールの80番ポートを解放します。
ファイアウォールのポートの開放をしないと、httpでの通信ができません。

なぜ80番ポートなのかと言うと、80番ポートがhttp通信用のポートだからです。

〈参考〉
http://inaba.hatenablog.com/entry/2017/02/26/040218

アクティブなゾーンを確認

ファイアウォールは「事前に定義されたゾーンに対して、指定されたルールの通信を通す。」という事をしています。
なので、まずはどのゾーンへのファイアウォールが動いているかを確認します。

$ firewall-cmd --get-active-zones
public
  interfaces: eth0

--get-active-zonesというオプションをつけると、現在アクティブなゾーンが表示されます。
上記だとpublicというゾーンがアクティブだとわかります。
アクティブなゾーンが複数ある場合は、eth0が外部公開されているインタフェースなので、eth0が定義されているゾーンが外部向けポートを追加する対象です。

許可されているポートの確認

次は先程確認したアクティブなゾーンのpublicについて、現在許可されているポートを確認します。

$sudo firewall-cmd --info-zone public
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: dhcpv6-client ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  sourceports:
  icmp-blocks:
  rich rules:

servicesには定義されているサービス(ルールのような物)が表示されます。
上の例だとservicesにdhcpv6-clientとsshが設定されています。

次のコマンドでサービスの内容を確認できます。

$ sudo firewall-cmd --info-service dhcpv6-client

詳しくはこちらの記事をお読みください。
http://inaba.hatenablog.com/entry/2017/02/26/040218


portsにはサービスとは別に開放されているポートが表示されます。

今回はportsには何も表示されていませんが、例えば8080番ポートが開放されていると、ports: 8080/tcpのように表示されます。

定義されているサービスを確認

サービスの一覧は—get-servicesオプションで確認できます。

$ firewall-cmd --get-services
RH-Satellite-6 amanda-client amanda-k5-client bacula bacula-client ceph ceph-mon dhcp dhcpv6 dhcpv6-client dns docker-registry dropbox-lansync freeipa-ldap freeipa-ldaps freeipa-replication ftp high-availability http https imap imaps ipp ipp-client ipsec iscsi-target kadmin kerberos kpasswd ldap ldaps libvirt libvirt-tls mdns mosh mountd ms-wbt mysql nfs ntp openvpn pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy proxy-dhcp ptp pulseaudio puppetmaster radius rpc-bind rsyncd samba samba-client sane smtp smtps snmp snmptrap squid ssh synergy syslog syslog-tls telnet tftp tftp-client tinc tor-socks transmission-client vdsm vnc-server wbem-https xmpp-bosh xmpp-client xmpp-local xmpp-server

結構量が多いのですが、この中にhttpというサービスがあります。

httpサービスの内容を確認します。

$sudo firewall-cmd --info-service http
http
  ports: 80/tcp
  protocols:
  source-ports:
  modules:
  destination:


80番ポートがルールとして定義されています。

サービスをゾーンに追加

httpサービスが80番ポートを開放するサービスという事がわかったので、publicゾーンにhttpサービスを追加します。

$sudo firewall-cmd --permanent --zone public --add-service http
success
$sudo firewall-cmd --reload
success

--permanentは設定の永続化。(無いと再起動時に設定が消えます。)

--zone publicはゾーンの指定。
--add-service httpは追加するサービスの指定です。
--add-serviceだけでは設定が反映されないので、設定をした後に--reloadでファイアウォールに設定を反映させます。

設定が反映されているか確認します。

$sudo firewall-cmd --info-zone public
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: dhcpv6-client http ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  sourceports:
  icmp-blocks:
  rich rules:

設定が反映されました。

4.自動起動設定

サーバーの再起動の際にもNginxが自動的に起動するよう設定します。

$ chkconfig nginx on

自動起動確認

$ systemctl is-enabled nginx
enabled 

nginx基本コマンド

〈参考〉
https://qiita.com/MuuKojima/items/afc0ad8309ba9c5ed5ee

起動
$ sudo systemctl start nginx
停止
$ sudo systemctl stop nginx
再起動
$ sudo systemctl restart nginx
再起動しても設定ファイルが反映されない場合など
$ sudo nginx -s reload
状態の確認
$ sudo systemctl status nginx

Githubの公開鍵登録

capisatranoでは、直接ローカルからファイルを送るのではなく、githubなどのホスティングサービスを経由します。
なので、サーバー側からgithubへsshで接続できるようにキーペアの作成・登録を行います。

〈参考〉
https://qiita.com/shizuma/items/2b2f873a0034839e47ce

1.キーの作成

サーバー

$ cd ~/.ssh/
$ mkdir github
$ cd github
# キーペアの作成
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/hoge/.ssh/id_rsa): /home/hoge/.ssh/github/id_rsa # 先程作成したフォルダを指定
Enter passphrase (empty for no passphrase): # Enter
Enter same passphrase again: #Eneter

$ cat id_rsa.pub
# 出力をコピーして、githubのコンソールより公開鍵を登録

# 設定ファイルを作成
$ sudo vi ~/.ssh/config
# 以下を記述
Host github github.com
  Hostname github.com
  User git
  IdentityFile ~/.ssh/github/id_rsa 

※Host名に注意してください。
❌Host github
⭕️Host github github.com

githubだけではエラーが発生しました。

2.公開鍵をGitHubにアップする

以下のリンクから公開鍵をGithubにアップできます。(GitHubに登録していることが前提条件です)
https://github.com/settings/ssh

手順はこちらの記事でご確認ください。
>>https://qiita.com/shizuma/items/2b2f873a0034839e47ce

接続確認

$ ssh -T github
#確認はyes
#以下のような文章が出力されればOK
You've successfully authenticated, but GitHub does not provide shell access.

Rails

1.データベースの設定

本番環境用のデータベースの設定をします。
Rails

config/database.yml
default: &default
  adapter: sqlite3
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

development:
  <<: *default
  database: db/development.sqlite3

test:
  <<: *default
  database: db/test.sqlite3

# ここから変更
production:
  adapter: mysql2
  encoding: utf8mb4
 charset: utf8mb4
  pool: 5
  database: hoge_app_production
  username: root
  password: root # その1で設定したサーバー側のmysqlのパスワード
  socket: /var/lib/mysql/mysql.sock

2.Gemfile修正

groupでくくられていないgem ’sqlite3’をコメントアウトし、developmentのグループのなかに’sqlite3’を追加します。
さらにproductionのグループを追記し、そちらにmysql2を設定しています。

Gemfile
.
.

# Use sqlite3 as the database for Active Record
# gem 'sqlite3' コメントアウト
.
.

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '~> 2.13'
  gem 'selenium-webdriver'
  # 追加
  gem 'sqlite3'
end
.
.
# 以下追加
group :production, :staging do
  gem 'mysql2'
end

インストール

$ bundle install

3.Githubでのバージョン管理開始

CapistranoではGithubを介したデプロイを行うので、githubのremoteリポジトリの登録とpushを行います。

# 変更履歴のコミット
$ git add . && git commit -m 'first commit'

# リモートリポジトリの登録(事前にご自身のgithubでリポジトリを作っておいてください)
# リポジトリ追加の際に表示される案内に従ってコマンドを入力
$ git remote add origin git@github.com:[ユーザID]/[リポジトリ].git

# リモートへのアップ
$ git push -u origin master

Capistrano

Capistranoとは、Ruby製のデプロイ自動化ツールです。
アプリケーションのファイルをサーバーにアップしてインターネット上に公開し、ユーザーが使える状態にするデプロイ作業を自動で行ってくれます。

Capistranoがデプロイを自動化するツールなら、ここまでの作業はなんだったのか??
デプロイの準備作業ということになりますね。

実を言うと、僕は手動デプロイをしたことがないのですが、手動デプロイには引き継ぎや再利用がしづらいといったデメリットがあるようです。

Capistranoは保守性が高く、再利用もしやすいと言ったメリットがありますが、それでも設定する項目が多く複雑です。

仕組み部分の理解がこれまで以上に重要になってきます。

設定に入る前に、こちらの記事に目を通すことを強くお勧めします。
https://labs.gree.jp/blog/2013/12/10084/

〈参考〉
https://qiita.com/naoki_mochizuki/items/657aca7531b8948d267b

1.インストール

Railsアプリにcapistranoおよびunicornのgemをインストールします。

Rails

Gemfile
group :development do
  # Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '>= 3.0.5', '< 3.2'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
  # 以下追記
  gem 'capistrano'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano-rbenv'
end

group :production, :staging do
 gem 'mysql2'
 # 以下追記
 gem 'unicorn'
end

ローカル

$ bundle install

2.capistranoの設定ファイル生成

新たにcapコマンドが使えるのでそれでcapistranoの設定ファイルを作成します。

$ bundle exec cap install

以下のようなファイルが生成されます。
hogeapp
├─ Capfile
├─ config
│ ├─ deploy
│ │ ├─production.rb
│ │ └─staging.rb
│ └─deploy.rb
└─ lib
└─capistrano
└─tasks

3.capistranoの基本設定

Rails
capistranoの設定ファイルを編集します。

まず、何を読み込むかを、Capistranoでどのような動作を行うかに合わせて決めます。

最初に記載されている内容は削除で大丈夫です。

今回は下の用に設定しましょう。

require hogehogeの部分で読み込むファイルを設定しています。

capfile
require "capistrano/setup"
require "capistrano/deploy"
require "capistrano/rbenv"
require "capistrano/bundler"
require "capistrano/rails/assets"
require "capistrano/rails/migrations"
require "capistrano/scm/git"

install_plugin Capistrano::SCM::Git

# taskを記述したファイルを読み込む用に設定。
# なおデフォルトでは *.rakeとなっているのでもとの記述をそのまま使う場合は注意!!
Dir.glob("lib/capistrano/tasks/*.rb").each { |r| import r }

4.productionの環境設定

生成したconfig/deploy配下にあるprouction.rbにサーバーの情報を記述します。
ちなみにstaging.rbはその名の通り、ステージングの情報です。

こちらも元のコードは全削除で大丈夫です。

config/deploy/production.rb
# conohaのサーバーのIP、ログインするユーザー名、サーバーの役割
# xxxの部分はサーバーのIPアドレス
# 10022はポートを変更している場合。通常は22
server 'xxx.xxx.xxx.xxx', user: 'hoge', group: "wheel", roles: %w{app db web}, port: 10022 

#デプロイするサーバーにsshログインする鍵の情報。サーバー編で作成した鍵のパス
  set :ssh_options, {
    keys: %w(~/.ssh/id_rsa),
    forward_agent: true,
    auth_methods: %w(publickey)
  }

次にproductionとstaging共通の設定について、deploy.rbに記述します。

こちらも最初の記述は全削除で。

※ capistranoのバージョンを確認して、以下記述のバージョンを調整してください。

rubyのバージョンからアプリケーション名、デプロイで送るgithubのリポジトリ、capistranoのタスクなどを記述します。

config/deploy.rb
# capistranoのバージョン固定
lock "~> 3.10.1"

# デプロイするアプリケーション名
set :application, 'hoge_app'

# cloneするgitのレポジトリ
# 1-3で設定したリモートリポジトリのurl
set :repo_url, 'git@github.com:hogehoge/hoge_app.git'

# deployするブランチ。デフォルトはmasterなのでなくても可。
set :branch, 'master'

# deploy先のディレクトリ。
set :deploy_to, '/var/www/hoge_app'

# Default value for :pty is false
 set :pty, true

# シンボリックリンクをはるファイル
# Default value for :linked_files is []
 append :linked_files, "config/master.key"
# シンボリックリンクをはるフォルダ
# Default value for linked_dirs is []
 append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "vendor/bundle", "public/system"

# 保持するバージョンの個数(※後述)
set :keep_releases, 5

# rubyのバージョン
# rbenvで設定したサーバー側のrubyのバージョン
set :rbenv_ruby, 2.5.1

# 出力するログのレベル。
set :log_level, :debug

# デプロイのタスク
namespace :deploy do

  # unicornの再起動
  desc 'Restart application'
  task :restart do
    invoke 'unicorn:restart'
  end

  # データベースの作成
  desc 'Create database'
  task :db_create do
    on roles(:db) do |host|
      with rails_env: fetch(:rails_env) do
        within current_path do
                # データベース作成のsqlセット
                # データベース名はdatabase.ymlに設定した名前で
                  sql = "CREATE DATABASE IF NOT EXISTS hoge_app_production;"
                # クエリの実行。
                # userとpasswordはmysqlの設定に合わせて
                execute "mysql --user=root --password=root -e '#{sql}'"

        end
      end
    end
  end

  after :publishing, :restart

  after :restart, :clear_cache do
    on roles(:web), in: :groups, limit: 3, wait: 10 do
    end
  end
end

各パラメータの内容は、次の参考記事で詳しく説明してくれています。
こちらも一読することをオススメします。

(Capistrano編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで - Qiita


5.master.keyの設定

Railsで設定しているmaster.keyの内容をサーバーにコピーします。
Rails5.2からはmaster.keyはcredentials.yml.encファイルで設定します。
詳しくは次の参考記事をお読みください。
〈参考〉
https://qiita.com/yuuuking/items/53a37a2e998972be32b8
https://qiita.com/katsu105/items/88675da5119762d73d92

まず必要なディレクトリを作成します。
サーバー

$ cd /var
$ sudo mkdir -p www/hoge_app/shared/config
# 所有者を設定
$ sudo chown -R hoge www
# ファイルの作成
$ cd www/hoge_app/shared/config

shared/configにmaster.keyを作ります。

$sudo touch /var/www/hoge_app/shared/config/master.key

作成したmaster.keyを編集します。

$sudo vim /var/www/hoge_app/shared/config/master.key

ローカルのmaster.keyの内容をコピーし、本番環境のmaster.keyにコピーします。

〈メモ〉
mkdir -p

-pオプション(--parentsオプション)を指定することで、ディレクトリが存在していてもエラーメッセージを表示せず、現在あるディレクトリはそのままにして新規に作成することはなく子ディレクトリを作成する。
また、親ディレクトリが存在しなくてもエラーメッセージを表示せずに親ディレクトリと子ディレクトリを作成する。

参考:https://eng-entrance.com/linux-command-mkdir

〈メモ〉
chown -R

指定したディレクトリとそのディレクトリ以下のファイルやディレクトリの所有権を再帰的に変更

参考:https://webkaru.net/linux/chown-command/

unicornのセットアップタスク

unicornのセットアップタスクを記述します。
unicornはアプリケーションサーバーで、Railsアプリケーションを制御します。

〈参考〉
https://qiita.com/naoki_mochizuki/items/657aca7531b8948d267b

Rails

lib/capistrano/tasks/unicorn.rb
#unicornのpidファイル、設定ファイルのディレクトリを指定
namespace :unicorn do
  task :environment do
    set :unicorn_pid,    "#{current_path}/tmp/pids/unicorn.pid"
    set :unicorn_config, "#{current_path}/config/unicorn/production.rb"
  end

#unicornをスタートさせるメソッド
  def start_unicorn
    within current_path do
      execute :bundle, :exec, :unicorn, "-c #{fetch(:unicorn_config)} -E #{fetch(:rails_env)} -D"
    end
  end

#unicornを停止させるメソッド
  def stop_unicorn
    execute :kill, "-s QUIT $(< #{fetch(:unicorn_pid)})"
  end

#unicornを再起動するメソッド
  def reload_unicorn
    execute :kill, "-s USR2 $(< #{fetch(:unicorn_pid)})"
  end

#unicronを強制終了するメソッド
  def force_stop_unicorn
    execute :kill, "$(< #{fetch(:unicorn_pid)})"
  end

#unicornをスタートさせるtask
  desc "Start unicorn server"
  task start: :environment do
    on roles(:app) do
      start_unicorn
    end
  end

#unicornを停止させるtask
  desc "Stop unicorn server gracefully"
  task stop: :environment do
    on roles(:app) do
      stop_unicorn
    end
  end

#既にunicornが起動している場合再起動を、まだの場合起動を行うtask
  desc "Restart unicorn server gracefully"
  task restart: :environment do
    on roles(:app) do
      if test("[ -f #{fetch(:unicorn_pid)} ]")
        reload_unicorn
      else
        start_unicorn
      end
    end
  end

#unicornを強制終了させるtask
  desc "Stop unicorn server immediately"
  task force_stop: :environment do
    on roles(:app) do
      force_stop_unicorn
    end
  end
end

killの種類

kill -QUIT : 停止
kill -HUP : 再起動
kill -USR2 : 緩やかな停止

6.unicornの設定ファイル

unicornの設定ファイルproduction.rbを作成し、ファイルのパスなどを設定します。
中身は以下のように記述してください。

config/unicorn/production.rb
#ワーカーの数
  $worker  = 2
#何秒経過すればワーカーを削除するのかを決める
  $timeout = 30
#自分のアプリケーション名、currentがつくことに注意。
  $app_dir = "/var/www/hoge_app/current"
#リクエストを受け取るポート番号を指定。後述
  $listen  = File.expand_path 'tmp/sockets/.unicorn.sock', $app_dir
#PIDの管理ファイルディレクトリ
  $pid     = File.expand_path 'tmp/pids/unicorn.pid', $app_dir
#エラーログを吐き出すファイルのディレクトリ
  $std_log = File.expand_path 'log/unicorn.log', $app_dir

# 上記で設定したものが適応されるよう定義
  worker_processes  $worker
  working_directory $app_dir
  stderr_path $std_log
  stdout_path $std_log
  timeout $timeout
  listen  $listen
  pid $pid

#ホットデプロイをするかしないかを設定
  preload_app true

#fork前に行うことを定義
  before_fork do |server, worker|
    defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
    old_pid = "#{server.config[:pid]}.oldbin"
    if old_pid != server.pid
      begin
        Process.kill "QUIT", File.read(old_pid).to_i
      rescue Errno::ENOENT, Errno::ESRCH
      end
    end
  end

#fork後に行うことを定義
  after_fork do |server, worker|
    defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
  end

githubへのpush

今までの変更をgithubへpushします。
capistranoはgithubを介してサーバーにファイルを送るためです。

ローカル

# 変更履歴をステージング
$ git add .
# コミット
$ git commit -m 'config complete'
# githubへ送信
$ git push origin master

デプロイ

いよいよデプロイを行います。

1.データベース作成

デプロイ前に本番用のデータベースを作成します。

サーバー

$ sudo mkdir /var/www/hoge_app/current
#サーバー側でディレクトリの作成

次にローカル側のデプロイするアプリのディレクトリで以下のコマンドを実行します。

$ bundle exec cap production deploy:db_create

どうやら一度きり実行するものはcap deploy時にtask名を明示してあげないといけないみたいなので、初回のみDBを作成するtaskを明示してあげないといけないようです。

最後に先程作成したサーバー側のcurrentディレクトリを削除します。
サーバー

$ sudo rm -r /var/www/hoge_app/current

なぜこのような手順を追うかと言うと、先ほどのデータベース作成時にはcurrentがないと、デプロイ時にはcurrentがあるとエラーが発生することがあるみたいです。
もっといいやり方があるかもしれません。

〈メモ〉
rm -r
rmコマンドは、オプションを設定しなければ、ディレクトリを削除の対象としない。
ディレクトリも削除の対象とする場合は、-rオプションを指定する。
参考:https://eng-entrance.com/linux_command_rm#-r--recursive

2.デプロイの実行

ついにやってまいりました。
デプロイのお時間です!!!

ローカルで次のコマンドを入力してください。

$ bundle exec cap production deploy

3.Nginxの起動

デプロイがうまくいったら、サーバーにアクセスしてnginxを起動してください。

サーバー

$ sudo service nginx start

4.サイト確認

それではサイトにアクセスしてください。

$ open http://xxx.xxx.xxx.xxx # conohaのipアドレス

無事に表示されればデプロイ成功です!

お疲れ様でした!!

おまけ

ここからはおまけになりますが、一応読んでおいてください。

僕はデプロイが完了した後、いったんConoHaサーバーを停止し、また起動させました。
すると、

We're sorry, but something went wrong.
If you are the application owner check the logs for more information

というエラーメッセージが表示され、アプリが表示されなくなってしまいました。

色々といじるも解決せず、デプロイし直したら、今度はデプロイまでエラーが発生してしまいました。

SSHKit::Runner::ExecuteError: Exception while executing as fukaya@150.95.204.25: kill exit status: 1
kill stdout: kill: sending signal to 5001 failed: そのようなプロセスはありません
kill stderr: Nothing written

unicorn.pidを削除することでデプロイ時のエラーは解決しました。

$ cd /var/www/hoge_app/current/tmp/pids
$ sudo rm -r unicorn.pid

〈参考〉
http://movieman.hatenadiary.com/entry/2017/01/26/010635

再デプロイ後にnginxを起動させたら、きちんとアプリが表示されました。

何が言いたいかというと、

いったんデプロイしたら、不用意にConoHaサーバーを停止しないようにしましょう!!!

ということです。

まとめ

いかかがでしたか??

スムーズにデプロイできましたか??

僕もそうでしたが、初めてのデプロイだとなかなかスムーズにはいかないと思います。

ですが、試行錯誤しながら苦労してデプロイをしたことで、確実にデプロイ前より成長しているはずです。

ちなみに僕は初デプロイの時に途中で詰まり、色々とイジっていたら収拾がつかなくなったので、
最初からデプロイし直しました。

1からやり直したことでいい復習になり、結果的に理解も深まりました。

どうしようもなくなったら、思い切って最初からやり直すのもアリだと思います。

僕もまだまだわからないことばかりで、偉そうなことは言えないので、
これからもっと精進していきたいと思います。

初デプロイ達成、おめでとうございます!!

〈関連記事〉
Railsアプリ〜デプロイへの道〜その①リモートサーバーへのSSH接続編
Railsアプリ〜デプロイへの道〜その②Ruby・MySQLインストール編

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

ENV[HOGEHOGE]でenvファイルの環境変数にアクセスできない!

結論

springを再起動したら通りました。

$spring stop

springについては以下を参考。
https://ruby-rails.hatenadiary.com/entry/20141026/1414289421

超ざっくり説明すると、毎回全システム起動してたら時間かかるからよく使うやつロードしたままにするね!みたいな感じ

経緯

外部APIのtokenを隠しておこうと、dotenv-railsを導入。
.envファイルを作成して環境変数を定義。
いざENV[HOGEHOGE]で値を取りに行くとnilが帰ってきてしまった。
変数名、定義法もあっていたのでもしやと思いつつspringを止めてみると案の定でした。
環境変数の読み込みもspringでストックさるんですね。めでたしめでたし。

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

【第2回】Ruby + Seleniumを使ってスクレイピングしてみる

@cosmeの商品レビューをスクレイピングしてみる

第1回の前置きが長くなってしまいましたが、今回からコーディングしていきたいと思います。

想定仕様

1.プロダクトIDが入ったURLを受け取る
2.上記で指定した商品の各レビューページに設置されている「続きを読む」リンクを踏み、全文レビューページに遷移
3.レビュー全文を取得する
4.同ページにある「次へ」リンクを踏み、次のレビュー全文ページに飛ぶ
5.3&4を任意で指定したレビュー取得件数分繰り返す
6.完了したらchromeを閉じる

こんな感じの仕様ができればと思います。Seleniumを使うことで、「4.同ページにある「次へ」リンクを踏み、次のレビュー全文ページに飛ぶ」という仕様ができるのが本当にデカいですね。これなら各レビューIDを指定する必要もないので、100件でも1000件でも楽々取得できるようになります。

Let's ruby

今回使用するライブラリはこんな感じです

#自動ブラウジング
require 'selenium-webdriver'
#HTMLをパースする
require 'nokogiri'
#指定したURLを開く&レビュー本文を取得
require 'open-uri'
#既存のxlsxフォーマットの書き込み
require 'rubyXL'

nokogiriopen-uriはスクレイピングではほぼ必須のライブラリ。
今回はxlsxファイルへの「書き込み」のみ(読み込みはしない)ですのでrubyXLを使用します。

Selenium起動&全文レビューページに遷移

#Seleniumを立てる(今回はchromeを使います)
driver = Selenium::WebDriver.for :chrome

#商品ページのURLを変数input_urlで受け取る
input_url = "https://www.cosme.net/product/product_id/10163439/top"

#input_urlで受け取ったページに移動する
driver.navigate.to("#{input_url}")

#「続きを読む」リンクを踏み、全文レビューページに遷移する
driver.find_element(:partial_link_text,'続きを読む').click

#カウンター(後のwhile文で使います)
count = 0

#取得レビュー件数を変数limitで受け取る
limit = 50

#商品名を変数nameで受け取る(任意の商品名を設定する。出力するxlsxのファイル名になります。)
name = "チェリー本"

#変数reviewsの空配列を置いておく(取得した各レビューは、変数reviewsの配列の要素として代入されます。)
reviews = []

driver = Selenium::WebDriver.for :chrome
今回はchromeで行いたいと思います。firefox, IE, Safariなどにも対応しているようです。

limit = 50
取得レビュー件数はここで指定します。今回はwhile構文を使った繰り返し処理を行いますが、その繰り返しの回数=limitの値になります。

reviews = []
取得した各レビューは配列の要素としてreviewsに追加できるようにします。

while文による繰り返し処理

while count < limit.to_i
  #現在のページのURLを変数current_urlで取得
  current_url = driver.current_url

  #UTF-8に変換(@cosmeの文字コードはShift_JISなので)
  doc = Nokogiri::HTML.parse(open(current_url, "r:Shift_JIS:UTF-8").read)

  #レビューを指定&本文のみを変数nに代入
  n = doc.css("p.read").text

  #変数reviewsに配列要素としてnを代入する
  reviews << n

  #カウンターを追加
  count+=1

  #Dos対策(次のレビューページに遷移するまで1秒以上空ける)
  sleep 1

  #ページ内の「次へ」を選択&ページ遷移
  driver.find_element(:partial_link_text,'次へ').click
end

while count < limit.to_i
今回はwhile文を使ってみました。構文内にカウンターを設置し一周ごとにcount+=1になるようにしてます。limitで指定した取得レビュー件数を上回るまで繰り返し処理を実行する、という仕組みです。

doc = Nokogiri::HTML.parse(open(current_url, "r:Shift_JIS:UTF-8").read)
なんとよくよくみたら@cosmeはShift-JISだったことが判明。UTF-8に変換しておきます。

<meta http-equiv="Content-Type" content="text/html; charset=shift_jis">

sleep 1
次のHTTPリクエストまで1秒以上空けます。

取得したレビューをEXCELに書き込む

#フォーマットのxlsxを選択
workbook = RubyXL::Parser.parse("@cosme_format.xlsx")

#シートを指定&シート名を変更
worksheet_a = workbook[0]
worksheet_a.sheet_name ="@cosmeレビュー収集"

#指定したセルに各レビューを書き出す
p = 1
reviews.each do |re|
  worksheet_a.add_cell(p,2,"#{re}")
  p+=1
end

#書き込みが完了したらブラウザを終了する
driver.quit

#保存する(序盤で任意で設定したnameの値がここに代入されます。)
workbook.write("@cosmeレビュー収集結果_#{name}.xlsx")

workbook = RubyXL::Parser.parse("@cosme_format.xlsx")
エクセルを操作できるrubyのライブラリは色々ありますが、今回は読み込みはせず書き込みだけなのでrubyXLを使ってみました。

アウトプット例

モザイクかけましたがこんな感じです。
image.png

まとめ

sleep 1で次のリクエストまで1秒開けているものの、あまりにも膨大な量を続けてリクエストすることはあまり良くないので、使用には十分注意する。長時間連続して回し続けないこと。
・特殊絵文字?などがレビュー本文に含まれている場合、エラーが起きて処理が止まってしまうので例外処理を用いて止まらないようにする。

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

【Rails】検索機能を実装しよう

はじめに

検索機能を実装しましょう!
今回は完全一致、部分一致、前方一致、後方一致を実装します。
それぞれ簡単に実装できるのでこの記事を理解して実装してみてください!!
今回はPostテーブルのtextカラムを検索する機能を実装します

実装方法

機能の大まかな内容は以下の通りです。
1. 検索方法を選択し、検索フォームに単語を入力する
2. 検索ボタンをクリックするとsearchアクションに繋がる
3. searchアクションでテーブルから検索をかける
4. 検索結果をビューで表示する

実装方法をビュー、モデル、コントローラーの順に説明していきます

ビュー

以下、検索フォームのソースです。

app/views/posts/search.html.erb
<%= form_tag(posts_search_path , method: :get) do %>
    <%= select(@search_content, :search_method, [["前方一致","forward_match"], ["後方一致","backward_match"], ["完全一致","perfect_match"], ["部分一致","partial_match"]])%>
    <%= text_field(@search_content, :search_word)%>
    <%= submit_tag "検索" %>
<% end %>

@search_contentsearch_methodsearch_wordが含まれています。
search_methodが検索方法です。ドロップダウンリストで選択します。
search_wordが入力フォームに入力した単語を代入します。

モデル

以下がモデルに検索のメソッドを定義する部分です。

app/models/post.rb
    def self.search(method,word)
                if method == "forward_match"
                        @posts = Post.where("text LIKE?","#{word}%")
                elsif method == "backward_match"
                        @posts = Post.where("text LIKE?","%#{word}")
                elsif method == "perfect_match"
                        @posts = Post.where("#{word}")
                elsif method == "partial_match"
                        @posts = Post.where("text LIKE?","%#{word}%")
                else
                        @posts = Post.all
                end
    end

引数のmethodによって検索方法を選択し、wordで検索します。

コントローラー

以下、コントローラーの内容です

app/controllers/posts_controller.rb
def search
    method = params[:search_method]
    word = params[:search_word]
    @posts = Post.search(method,word)
end

検索方法と単語を引数に渡し検索をします

終わりに

以上が検索機能の実装方法になります。

疑問、気になるところがございましたら、質問、コメントよろしくお願いします!!!

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

Rails6 のちょい足しな新機能を試す100(不正なURLパラメータのリクエスト編)

はじめに

Rails 6 に追加された新機能を試す第100段。 今回は、 不正なURLパラメータのリクエスト編です。
Rails 6 では、 不正なパラメータのリクエストの場合でもエラーにならずに、Railsのエラー画面を表示するようになりました。

Ruby 2.6.5, Rails 6.0.0 で確認しました。

$ rails --version
Rails 6.0.0

今回は、Userの CRUD を作って確認します。

Rails プロジェクトを作る

$ rails new rails_sandbox
cd rails_sandbox

User の CRUD を作る

$ bin/rails g scaffold User name

データベースのマイグレーションを実行する

$ bin/rails db:create db:migrate

不正なパラメータのURLにアクセスする

ここで、 rails server を実行して、不正なパラメータつきの存在しないURLにブラウザからアクセスしてみます。
今回は、 http://localhost:3000/foo?x=1&x[y]=2 にアクセスしてみます

エラー画面が表示されます。

error1.png

このときパラメータの情報は画面には表示されません。

試しに不正ではないパラメータを使い http://localhost:3000/foo?x=1 にアクセスしてみます。

このときは、パラメータの情報が画面に表示されます。

error2.png

Rails 5 では

Rails 5.2.3 では、 http://localhost:3000/foo?x=1&x[y]=2 にアクセスしたときに Rails のエラー画面は表示されません。
error3.png

試したソース

試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try100_malformed_url

参考情報

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

遷移元のコントローラーとアクションを取得して、条件分岐をする

~同じコントローラーのアクションを使って今いるページからのリンク先を変える方法~

起きていたこと

1.新規登録の時(修正前)

/signup/cards

cards.png
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

/card/show

show.png

2.カード情報を追加登録の時(修正前)

/card/new

new.png
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

/card/show

show.png

"1.新規登録"の時の遷移先を/signup/finishにしたいが
問題のコントローラーを確認すると/signup/finishに飛んでない!!**

card_controller.rb(修正前)
  def pay 
    Payjp.api_key = ENV["PAYJP_ACCESS_KEY"]
          [省略]
      if @card.save//保存できたら
        redirect_to action: "show"//カード情報を表示する
      else//保存できなかったら
        redirect_to action: "pay"
      end
    end
  end

やりたいこと

/signup/finishを設定してない遷移元のコントローラーとアクションを指定して条件分岐できないだろうか?
=>会員登録の時とユーザー設定ページのそれぞれでcardコントローラーでnewを使用したした時で分けたい
理想形.png

結論:request.referrerを使用する

request.referrerの例
遷移元のコントローラーを取得
Rails.application.routes.recognize_path(request.referrer)
 {:controller=>"users", :action=>"index"}

こちらで遷移元の URL が取得できる
request.referrer
 "http://localhost:3000/users"

=========================================

request.referrerを実装する

card_controller.rb(修正後)
  def pay 
    Payjp.api_key = ENV["PAYJP![cards.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487723/8eae145d-f132-acff-0c61-a44229d99489.png)
_ACCESS_KEY"]
          [省略]
       path = Rails.application.routes.recognize_path(request.referer)
        if path[:controller] == "card" && path[:action] == "new" //もしも、"card"コントローラでnewを行ったら、
          redirect_to action: "show" //showを行う
        else //違ったらfinishへ飛ばす
          redirect_to finish_signup_index_path
        end
          [省略]

修正した結果

1.新規登録の時(修正版)

/signup/cards

cards.png
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

/signup/finish

finish.png
falseで読み込まれるため/signup/finishへ飛ぶ

実行したところ
        else //違ったらfinishへ飛ばす
          redirect_to finish_signup_index_path

2.カード情報を追加登録の時

trueのためこちらの結果は修正前と変わらない

参考記事

https://qiita.com/sayama0402/items/ffe96ff76148231a0c22
http://kawahiro.hatenablog.jp/entry/2014/03/21/164449

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

Ubuntu18.04 で コマンド`$ rails server` を実行した時にエラーが出た話

目的

エラー内容

$ rails s
=> Booting Puma
=> Rails 6.0.0 application starting in development 
=> Run `rails server --help` for more startup options
RAILS_ENV=development environment is not defined in config/webpacker.yml, falling back to production environment
Exiting
Traceback (most recent call last):
        68: from bin/rails:4:in `<main>'
        67: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:325:in `require'
        66: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:291:in `load_dependency'

・
・
・
2: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:84:in `data'
         1: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:87:in `load'
/home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:91:in `rescue in load': Webpacker configuration file not found /home/miriwo/workspace/aaa/config/webpacker.yml. Please run rails webpacker:install Error: No such file or directory @ rb_sysopen - /home/miriwo/workspace/aaa/config/webpacker.yml (RuntimeError)

解決方法

  • コマンド$ rails webpacker:installを実行しようとしたところでエラーがでた。
$ rails webpacker:install
Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/
  • yarnが入っていないためエラーが出たようなのでコマンドbrew install yarnを実行して入れた。
$ brew install yarn
==> Installing dependencies for yarn: node
==> Installing yarn dependency: node
==> Downloading https://homebrew.bintray.com/bottles/node-12.12.0.high_sierra.bottle.tar.gz
==> Downloading from https://akamai.bintray.com/0f/0f35e88be5a84c808dba472d053af25639b300c095392f63e85d9ae94cf12b20
・
・
・
  • コマンド$ rails webpacker:installを実行した。
$ rails webpacker:install
RAILS_ENV=development environment is not defined in config/webpacker.yml, falling back to production environment
      create  config/webpacker.yml
Copying webpack core config
      create  config/webpack
      create  config/webpack/development.js
      create  config/webpack/environment.js
・
・
・
  • コマンド$ rails serverを実行したところ、正常にローカルサーバが起動した。
$ rails s
=> Booting Puma
=> Rails 6.0.0 application starting in development 
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 3.12.1 (ruby 2.6.4-p104), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
・
・
・

付録

  • コマンド$ rails serverを実行した時のエラーを記載する。
$ rails s
=> Booting Puma
=> Rails 6.0.0 application starting in development 
=> Run `rails server --help` for more startup options
RAILS_ENV=development environment is not defined in config/webpacker.yml, falling back to production environment
Exiting
Traceback (most recent call last):
        68: from bin/rails:4:in `<main>'
        67: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:325:in `require'
        66: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:291:in `load_dependency'
        65: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:325:in `block in require'
        64: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
        63: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi'
        62: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
        61: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi'
        60: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require'
        59: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/commands.rb:18:in `<main>'
        58: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/command.rb:46:in `invoke'
        57: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/command/base.rb:65:in `perform'
        56: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/thor-0.20.3/lib/thor.rb:387:in `dispatch'
        55: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/thor-0.20.3/lib/thor/invocation.rb:126:in `invoke_command'
        54: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/thor-0.20.3/lib/thor/command.rb:27:in `run'
        53: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/commands/server/server_command.rb:138:in `perform'
        52: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/commands/server/server_command.rb:138:in `tap'
        51: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/commands/server/server_command.rb:147:in `block in perform'
        50: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/commands/server/server_command.rb:37:in `start'
        49: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/commands/server/server_command.rb:77:in `log_to_stdout'
        48: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/server.rb:354:in `wrapped_app'
        47: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/server.rb:219:in `app'
        46: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/server.rb:319:in `build_app_and_options_from_config'
        45: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/builder.rb:40:in `parse_file'
        44: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/builder.rb:49:in `new_from_string'
        43: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/builder.rb:49:in `eval'
        42: from config.ru:in `<main>'
        41: from config.ru:in `new'
        40: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/builder.rb:55:in `initialize'
        39: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/builder.rb:55:in `instance_eval'
        38: from config.ru:3:in `block in <main>'
        37: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:48:in `require_relative'
        36: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:325:in `require'
        35: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:291:in `load_dependency'
        34: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:325:in `block in require'
        33: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/zeitwerk-2.2.0/lib/zeitwerk/kernel.rb:23:in `require'
        32: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
        31: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi'
        30: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
        29: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi'
        28: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require'
        27: from /home/miriwo/workspace/aaa/config/environment.rb:5:in `<main>'
        26: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/application.rb:363:in `initialize!'
        25: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/initializable.rb:60:in `run_initializers'
        24: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:205:in `tsort_each'
        23: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:226:in `tsort_each'
        22: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:347:in `each_strongly_connected_component'
        21: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:347:in `call'
        20: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:347:in `each'
        19: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:349:in `block in each_strongly_connected_component'
        18: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:431:in `each_strongly_connected_component_from'
        17: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
        16: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:228:in `block in tsort_each'
        15: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/initializable.rb:61:in `block in run_initializers'
        14: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/initializable.rb:32:in `run'
        13: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/initializable.rb:32:in `instance_exec'
        12: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/railtie.rb:84:in `block in <class:Engine>'
        11: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker.rb:27:in `bootstrap'
        10: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/commands.rb:14:in `bootstrap'
         9: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/manifest.rb:18:in `refresh'
         8: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/manifest.rb:83:in `load'
         7: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:47:in `public_manifest_path'
         6: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:43:in `public_output_path'
         5: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:39:in `public_path'
         4: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:80:in `fetch'
         3: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:84:in `data'
         2: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:88:in `load'
         1: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:88:in `read'
/home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:88:in `read': No such file or directory @ rb_sysopen - /home/miriwo/workspace/aaa/config/webpacker.yml (Errno::ENOENT)
        67: from bin/rails:4:in `<main>'
        66: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:325:in `require'
        65: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:291:in `load_dependency'
        64: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:325:in `block in require'
        63: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
        62: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi'
        61: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
        60: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi'
        59: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require'
        58: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/commands.rb:18:in `<main>'
        57: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/command.rb:46:in `invoke'
        56: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/command/base.rb:65:in `perform'
        55: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/thor-0.20.3/lib/thor.rb:387:in `dispatch'
        54: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/thor-0.20.3/lib/thor/invocation.rb:126:in `invoke_command'
        53: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/thor-0.20.3/lib/thor/command.rb:27:in `run'
        52: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/commands/server/server_command.rb:138:in `perform'
        51: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/commands/server/server_command.rb:138:in `tap'
        50: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/commands/server/server_command.rb:147:in `block in perform'
        49: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/commands/server/server_command.rb:37:in `start'
        48: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/commands/server/server_command.rb:77:in `log_to_stdout'
        47: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/server.rb:354:in `wrapped_app'
        46: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/server.rb:219:in `app'
        45: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/server.rb:319:in `build_app_and_options_from_config'
        44: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/builder.rb:40:in `parse_file'
        43: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/builder.rb:49:in `new_from_string'
        42: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/builder.rb:49:in `eval'
        41: from config.ru:in `<main>'
        40: from config.ru:in `new'
        39: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/builder.rb:55:in `initialize'
        38: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/builder.rb:55:in `instance_eval'
        37: from config.ru:3:in `block in <main>'
        36: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:48:in `require_relative'
        35: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:325:in `require'
        34: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:291:in `load_dependency'
        33: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:325:in `block in require'
        32: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/zeitwerk-2.2.0/lib/zeitwerk/kernel.rb:23:in `require'
        31: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
        30: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi'
        29: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
        28: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi'
        27: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require'
        26: from /home/miriwo/workspace/aaa/config/environment.rb:5:in `<main>'
        25: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/application.rb:363:in `initialize!'
        24: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/initializable.rb:60:in `run_initializers'
        23: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:205:in `tsort_each'
        22: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:226:in `tsort_each'
        21: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:347:in `each_strongly_connected_component'
        20: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:347:in `call'
        19: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:347:in `each'
        18: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:349:in `block in each_strongly_connected_component'
        17: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:431:in `each_strongly_connected_component_from'
        16: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
        15: from /home/linuxbrew/.linuxbrew/Cellar/ruby/2.6.5/lib/ruby/2.6.0/tsort.rb:228:in `block in tsort_each'
        14: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/initializable.rb:61:in `block in run_initializers'
        13: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/initializable.rb:32:in `run'
        12: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/initializable.rb:32:in `instance_exec'
        11: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/railtie.rb:84:in `block in <class:Engine>'
        10: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker.rb:27:in `bootstrap'
         9: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/commands.rb:14:in `bootstrap'
         8: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/manifest.rb:18:in `refresh'
         7: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/manifest.rb:83:in `load'
         6: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:47:in `public_manifest_path'
         5: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:43:in `public_output_path'
         4: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:39:in `public_path'
         3: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:80:in `fetch'
         2: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:84:in `data'
         1: from /home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:87:in `load'
/home/linuxbrew/.linuxbrew/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:91:in `rescue in load': Webpacker configuration file not found /home/miriwo/workspace/aaa/config/webpacker.yml. Please run rails webpacker:install Error: No such file or directory @ rb_sysopen - /home/miriwo/workspace/aaa/config/webpacker.yml (RuntimeError)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初心者向け】RailsにRspecを導入してみた話

Rspecとは

Wikipediaから引用すると、Rspecとは

RSpec is a 'Domain Specific Language' (DSL) testing tool written in Ruby to test Ruby code.

自分なりに和訳してみると、

RSpecとはRubyによって書かれた、Rubyによるコードをテストするための'ドメイン固有言語'なテストツールである。

といった感じでしょうか。

つまりは、Ruby用のテストツールでして、Rubyベースのフレームワークのテストに使われています。

ちなみに @jnchito さんのこちらのスライドによると2015年時点では、利用者および情報量の観点ではRSpecが多数派のようです。

Gemfile

今回はこちらの公式ドキュメントを参考にRailsに導入していきます。

手順は簡単で、まずはGemfileを編集し、下記のコードを追加します。

Gemfile
group :development, :test do
  gem 'rspec-rails', '~> 3.8'
end

その後、プロジェクトのディレクトリで

$ bundle install

$ rails generate rspec:install
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  spec/rails_helper.rb

と入力すれば完了です。

bundle install でRSpecのダウンロードとインストールを行い、
rails generate rspec:installでRSpecに必須な設定ファイルが作成されます。

これで準備が完了です。

あとはテストコードを作成し、コンソールにて

$ bundle exec rspec

と叩けば、テストが実行されます。

Springによる高速化

ここまでの内容でRSpecを用いてテストを実施することができますが、Springを用いることで、テストの所要時間を短縮することができます。

公式ドキュメントには

Spring is a Rails application preloader. It speeds up development by keeping your application running in the background so you don't need to boot it every time you run a test, rake task or migration.

とありまして、こちらも和訳してみると、

SpringはRailsアプリケーションにおけるプリローダーです。アプリケーション実行時にバックグラウンドで起動し続けることにより、テストやレイクタスク、マイグレーション毎にアプリケーションを起動させる必要がなくなるので、開発の速度があげることができます。

といった感じでしょうか。

ちなみにSpringはRailsのバージョン4.2からrails newを実行時に自動でインストールされるようになっています。

というわけで、今回はRSpecを導入するにあたって、こちらを参考にSpringも利用することにしました。

こちらも利用は簡単です。

まずは、Gemfileに下記のように追加します。

Gemfile
group :development, :test do
  gem 'rspec-rails', '~> 3.8'
  gem 'spring-commands-rspec'
end

先ほど示したGemfileにgem 'spring-commands-rspec'を追加しただけです。

追加したら、

$ bundle exec spring binstub rspec

とコンソールで入力し、スタブファイル(bin/rspec)を作成します。

これで準備は完了です。

あとは

$ bundle exec bin/rspec

と叩けばSpringとRSpecを用いたテストが実施されます。

実行時間の調査

準備ができたので、実際にテストコードの所要時間を比較してみます。

まず、テストコードを作成したいので、scaffoldを実行します。(scaffoldについても記事にしているので、参考にしてみてください。)

今回は下記のコマンドを実行しました。

$ rails generate scaffold Task title:string priority:integer

これによりRSpecのテストコードも自動で作成されますので、今回はこのテストコードを用います。

というわけでSpringを使った結果と使わなかった結果がこちらです。

Spring未使用
$ bundle exec rspec
(省略)
Finished in 3.66 seconds (files took 21.22 seconds to load)
27 examples, 0 failures, 13 pending
Spring使用
$ bundle exec bin/rspec
(省略)
Finished in 3.59 seconds (files took 2.29 seconds to load)
27 examples, 0 failures, 13 pending

比べてみますとSpring使用時の方が読み込みにかかった時間が圧倒的に短いですし、テスト自体の実行時間もわずかに速いです。

今回の例ですと、テストケースが40ケースですが、テストの数がより増えてくるとより威力が発揮されるのではないかと思います。

まとめ

RSpecを導入する場合は
1. Gemのインストール
2. コマンドの実行
とかなり少ないステップで用いることができます。

また、Springを用いることで、テストを高速化することができます。

ちなみにRSpecを導入するタイミングによっては、Minitestによって作られている「test」ディレクトリが残ったままになってしまいますので、削除するのをお忘れなく。

最後までお読みいただきありがとうございました。

参考文献

RSpec基礎情報(Wikipedia)
https://en.wikipedia.org/wiki/RSpec

RSpecとMinitest、使うならどっち?
https://speakerdeck.com/jnchito/number-kanrk06

RSpec公式リポジトリ
https://github.com/rspec/rspec-rails

Spring公式リポジトリ
https://github.com/rails/spring

spring-commands-rspec公式リポジトリ
https://github.com/jonleighton/spring-commands-rspec

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

lazysizesでRails画像遅延読み込み

Railsを使った画像遅延読み込み

画像遅延読み込みとは

遅延読み込みという技術は、Webサイトに表示される画像を一度に読み込まず、必要に応じて必要な分だけ読み込むというものです。不必要な画像の読み込みを後回しにして、画像以外のCSSやJSファイルの読み込みが先に行われます。そうすることで、表示速度を速くすることができます。

https://alaki.co.jp/blog/?p=2527

目的

lazysizesを使用し画像遅延読み込みさせることでWebサイトの表示速度向上を図ります
今回使用するのはlazysizesです。
スクリーンショット 2019-10-28 1.48.00.png

lazysizes

lazysizesの導入

読み込み

app/views/layouts/application.html.erb
<%= javascript_include_tag 'https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.1.2/lazysizes.min.js' %>

使い方

下記のように遅延させたいimgタグにclasslazyloadをつけると画像を遅延読み込みし、読み込むとclassがlazyloadからlazyloadedに変わります

data-srcは遅延読み込みさせたい画像パスを入れます

<img data-src="画像パス" class="lazyload">

ここでrailsで image_tagのように使えるようにするためにhelperを作成します

helper作成

app/helpers/application_helper.rb
    def lazysizes_image_tag(source, options={})
      options['data-src'] = source
      if options[:class].blank?
        options[:class] = "lazyload"
      else
        options[:class] = "lazyload #{options[:class]}"
      end
      image_tag('画像を読み完了してない時の画像パス', options) + ('<noscript><img src=' + source +'></noscript>').html_safe
    end

SEO対策

<noscript>を付け足している理由としてはクローラはスクロールしない=画像が読み込まれないので対象画像がインデックスされません。
そこで<noscript>の中に <img>を入れることでインデックス対象にしています。

呼び出し

<%= lazysizes_image_tag '画像パス' %>

これで画像の遅延読み込みが可能になりました。

 参考記事

jQuery Lazyloadプラグインで遅延読み込み
lazysizesの使い方を通して学ぶ、画像の遅延読み込みとレスポンシブイメージの基本
noscript内のコンテンツをGoogleは無視するが画像は例外的にインデックスする

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

オリジナルアプリにパートナー申請機能を実装する

概要

  • オリジナルアプリ作成にあたり、ユーザ(current_user)が他ユーザに対してパートナー申請をする画面をトップページ(toppages#index)に実装したい。
  • 申請手順は以下の通りとなる。
    1. 自分(ユーザA)がパートナー(ユーザB)に対して招待を送る。その際にユーザAは「秘密の言葉」を設定しておく。
    2. パートナーのトップページに「招待が届きました」というメッセージが届き、それを「承認」か「拒否」かを選択する。承認する場合にはユーザAが設定した「秘密の言葉」を入力する必要がある。
    3. 承認された場合はユーザAとユーザBはパートナーとなる。
  • ユーザと他ユーザがパートナーである事は中間テーブルrelationshipsに定義する。

手順

パートナー申請フォーム作成

中間テーブルrelationshipsにて多対多の関係(ユーザと他ユーザがパートナーである状態)を表す。

  • 中間テーブルrelationshipsのカラム構成
id user_id partner_id status secret_words

form_withを用い、relationshipsテーブルにデータが登録されるようにする。
relationshipsのパーシャルでパートナー申請フォームを作成する。

relationships/_offer_form.html.erb
<div class="row">
    <div class="col-sm-6 offset-sm-3">
        <%= form_with(model: relationship, local: true) do |f| %>
            <div class="form-group">
                # relationshipテーブルに無いデータの入力の為、"f.~"ではなく"~_tag"を用いる
                # 初期値をテキストボックスに表示しておきたい場合、""内に値を入れる(今回は不要の為、ブランク)
                <%= label_tag :name, "パートナー申請先(ユーザ名)" %>
                <%= text_field_tag :name, "", class: "form-control" %>
            </div>
            <div class="form-group">
                <%= f.label :secret_words, "秘密の言葉" %>
                <%= f.text_field :secret_words, class: "form-control" %>
            </div>

            <%= hidden_field_tag :status, "承認待ち" %>

            <%= f.submit "招待する", class: "btn btn-primary btn-block" %>
        <% end %>
    </div>
</div>

パートナー申請画面作成

relationshipsのパーシャルで作成した申請フォームをrenderで読み込む。

views/toppages/index.html.erb
<div class="text-center">
    <h1>パートナー申請画面</h1>
</div>
# classを跨ぐ場合はインスタンス変数を用いるとclass間で依存関係が出来てしまうので、使用しないほうが良い
<%= render "relationships/offer_form", relationship: @relationship %>

toppages controllerの実装

relationshipsのパーシャルで申請フォームを作成した為、インスタンス変数もRelationshipsControllerで定義するものだと勘違いしやすいが、それは誤りである。仮に別クラスのパーシャルであったとしてもviewに表示されているインスタンス変数はそのアクションを定義しているcontrollerに紐づいている為、今回の場合はインスタンス変数(@relationship)はtoppages#indexで定義する。

controllers/toppages_controller.rb
class ToppagesController < ApplicationController
  def index
    if logged_in?
      # インスタンス変数を@relationshipとし、form_withのmodel引数に設定してあげることで
      # action先をRelationshipsController#createに暗に飛ばすことが出来る
      @relationship = current_user.relationships.build
    end
  end
end

(補足情報)

current_userとlogged_in?のメソッドはSessionsHelperにて定義している。

helpers/sessions_helper.rb
module SessionsHelper
    def current_user
        @current_user ||= User.find_by(id: session[:user_id])
    end

    def logged_in?
        !!current_user
    end
end

helperはviewでのみしか機能しないので、controllerで使用したい場合はmix-inをする。
今回、ToppagesControllerで使用したいが、他でも使用する可能性が高い為、全体に適用すべくApplicationControllerにmix-inしておく。

controllers/application_contoller.rb
class ApplicationController < ActionController::Base
    # SessionsHelperをmix-in
    include SessionsHelper

    private

    def require_user_logged_in
        unless logged_in?
            redirect_to login_url
        end
    end
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RSpec導入方法

環境

  • Mac OS
  • Ruby 2.6.3
  • Rails 5.2.3
  • MySQL 8.0

RSpecについて

TDD(テスト駆動開発)で使用される、
Rubyの代表的なテスティングフレームワーク。

TDD(テスト駆動開発)とは

  1. 先にテストコードを書き実行、テストを失敗させる(レッド)
  2. テストコードが成功するようにコードを書く(グリーン)
  3. テストコードを実行し、テストを成功させる(リファクタリング)

を繰り返し、ある程度のところでリファクタリングをする
というように開発を進めていく手法。

  • バグを開発段階で発見、修正できる
  • テストを繰り返すことで実装するシステムへの理解が深まる
  • 有効なリファクタリングかどうかの確認がしやすい

などのメリットがある。

Capybaraについて

WebアプリケーションのE2Eテスト
(単体テストとは違い、システム全体を実稼働時に近い状況で動かしつつテストする手法)
用のテストフレームワーク。

FactoryBotについて

テスト用のデータの作成をサポートするgem
テスト用のデータを簡単に作成し、テストから呼び出して使用できる。

【1】 gemをインストールする

Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end

Gemfileの上記の部分に

gem 'rspec-rails', '~> 3.7'
gem 'factory_bot_rails', '~> 4.11'

を追加して下記のようにする。

Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails', '~> 3.7'
  gem 'factory_bot_rails', '~> 4.11'
end

その後bundle installを実行する。

$ bundle

【2】 RSpecの設定ファイルを作成する

$ rails g rspec:install

上記のコマンドを実行しRSpecの設定ファイルを作成する。

その後、元々あったtestディレクトリ(Minitestで使うもの)を削除する。

$ rm -r ./test

【3】 Capybaraを使う準備をする

spec_helper.rb
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
RSpec.configure do |config|
  # rspec-expectations config goes here. You can use an alternate
  # assertion/expectation library such as wrong or the stdlib/minitest
  # assertions if you prefer.

作成されたspecディレクトリにある
上記のようなspec_helper.rbに対して必要なコードを加え、下記のようにする。

spec_helper.rb
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration

require 'capybara/rspec'

RSpec.configure do |config|
  config.before(:each, type: :system) do
    driven_by :selenium_chrome_headless
  end
  # rspec-expectations config goes here. You can use an alternate
  # assertion/expectation library such as wrong or the stdlib/minitest
  # assertions if you prefer.

感じたこと

RSpecはどうやって導入するんだっけ?
と忘れてしまう事もあるので自分用のメモとしてさらっとまとめました!(笑)
まだまだ勉強中の身なのでしっかり学習していきます!!

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