20201021のRailsに関する記事は29件です。

ユーザー認証の導入

ユーザー認証の導入

Basic認証

HTTP通信の規格に備え付けられている、ユーザー認証の仕組みのこと
d5d42271f315066cae86af0e91d3b5cc.png

RailsアプリケーションにBasic認証を導入

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :basic_auth
  (省略)

  private

  def basic_auth
    authenticate_or_request_with_http_basic do |username, password|
      username == 'admin' && password == '1111'
    end
  end
end

開発環境の環境変数に、ユーザー名とパスワードを設定

macOSがCatalina以降

ターミナル
% vim ~/.zshrc

# .zshrcを開いたら、「iとタイプしてインサートモードに移行

# .zshrcの内部に次の記述を追加
export BASIC_AUTH_USER='admin'
export BASIC_AUTH_PASSWORD='2222'
# 記述を追加したらescキーを押してインサートモードを抜け :wqと入力して保存して終了する

# .zshrcを再読み込みし定義した環境変数を有効にする
% source ~/.zshrc

macOSがMojave以前の方

ターミナル
$ vim ~/.bash_profile

# .bash_profileを開いたら、「iとタイプしてインサートモードに移行

# .bash_profileの内部に次の記述を追加
export BASIC_AUTH_USER='admin'
export BASIC_AUTH_PASSWORD='2222'
# 記述を追加したらescキーを押してインサートモードを抜け :wqと入力して保存して終了する

# .bash_profileを再読み込みし定義した環境変数を有効にする
$ source ~/.bash_profile
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails DB作成から追加、保存、削除

はじめに

rails consoleでDBの作成、内容の追加、保存、削除まで。

Userテーブルの作成

$ rails g model User name:string email:string
id name(string) email(string)
1 alice alice@gmail.com
2 tom tom@gmail.com

データベースに変更を反映

$ rails db:migrate

データの追加(C)

$ rails console
> user = User.new(name:"alice", email:"alice@gmail.com")
> user.save

データの読み取り(R)

> user = User.all
> user[0]

データの更新(U)

> user = User.all
> user0 = user[0]
> user[0].name = "alice_alice"
> user[0].save

データの削除(D)

> user[0].destroy

バリデーション

オブジェクトがDBに保存される前に、そのデータが正しいかどうかを検証する仕組みをバリデーションという

「emailの重複がないか」をチェックするためのバリデーション

class User < ApplicationRecord
    validates :email, {uniqueness: true}
end

文字数をチェックするバリデーション

class Post < ApplicationRecord
    validates :content, {presence: true, length: {maximum: 140}}
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails DB作成から追加、保存、削除、カラムの追加

はじめに

rails consoleでDBの作成、内容の追加、保存、削除まで。

Userテーブルの作成

$ rails g model User name:string email:string
id name(string) email(string)
1 alice alice@gmail.com
2 tom tom@gmail.com

データベースに変更を反映

$ rails db:migrate

データの追加(C)

$ rails console
> user = User.new(name:"alice", email:"alice@gmail.com")
> user.save

データの読み取り(R)

> user = User.all
> user[0]

データの更新(U)

> user = User.all
> user0 = user[0]
> user[0].name = "alice_alice"
> user[0].save

データの削除(D)

> user[0].destroy

バリデーション

オブジェクトがDBに保存される前に、そのデータが正しいかどうかを検証する仕組みをバリデーションという

「emailの重複がないか」をチェックするためのバリデーション

class User < ApplicationRecord
    validates :email, {uniqueness: true}
end

文字数をチェックするバリデーション

class Post < ApplicationRecord
    validates :content, {presence: true, length: {maximum: 140}}
end

カラムの追加

id name(string) email(string)
1 alice alice@gmail.com
2 tom tom@gmail.com

これにユーザーの画像の情報を追加する!

$ rails g migration add_image_name_to_users

マイグレーションフォルダ /db/migration/ にファイルが追加される。

マイグレーションファイルの見方

/db/migration/20201010_create_post.rbの中身

rails g model で作ったマイグレーションファイルには、changeメソッドは自動生成されていた。
なので、特に変更することなく、rails db:migrate で変更を反映できていた。

class CreateUsers < ActiveRecord::Migration[5.0]
    def change
        create_table :users do |t| #postsという名前のテーブルを作成
            t.string :name #データ方がstringであるnameという名前のカラムを作成
            t.string :email #データ方がstringであるemailという名前のカラムを作成
            t.timestamps
        end
    end
end

カラムの追加は自分でしないといけない

今回、カラムを追加するので、自分でchangeメソッドの中身を書く必要がある。

class AddImageNameToUsers < ActiveRecord::Migration[5.0]
    def change
        add_column uses, image_name, string #テーブル名、カラム名、データ型
    end
end

changeメソッドの中身を実行する

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

rails DB作成から追加、保存、削除、カラムの追加、画像の保存

はじめに

rails consoleでDBの作成、内容の追加、保存、削除まで。

Userテーブルの作成

$ rails g model User name:string email:string
id name(string) email(string)
1 alice alice@gmail.com
2 tom tom@gmail.com

データベースに変更を反映

$ rails db:migrate

データの追加(C)

$ rails console
> user = User.new(name:"alice", email:"alice@gmail.com")
> user.save

データの読み取り(R)

> user = User.all
> user[0]

データの更新(U)

> user = User.all
> user0 = user[0]
> user[0].name = "alice_alice"
> user[0].save

データの削除(D)

> user[0].destroy

バリデーション

オブジェクトがDBに保存される前に、そのデータが正しいかどうかを検証する仕組みをバリデーションという

「emailの重複がないか」をチェックするためのバリデーション

class User < ApplicationRecord
    validates :email, {uniqueness: true}
end

文字数をチェックするバリデーション

class Post < ApplicationRecord
    validates :content, {presence: true, length: {maximum: 140}}
end

カラムの追加

id name(string) email(string)
1 alice alice@gmail.com
2 tom tom@gmail.com

これにユーザーの画像の情報を追加する!

$ rails g migration add_image_name_to_users

マイグレーションフォルダ /db/migration/ にファイルが追加される。

マイグレーションファイルの見方

/db/migration/20201010_create_post.rbの中身

rails g model で作ったマイグレーションファイルには、changeメソッドは自動生成されていた。
なので、特に変更することなく、rails db:migrate で変更を反映できていた。

class CreateUsers < ActiveRecord::Migration[5.0]
    def change
        create_table :users do |t| #postsという名前のテーブルを作成
            t.string :name #データ方がstringであるnameという名前のカラムを作成
            t.string :email #データ方がstringであるemailという名前のカラムを作成
            t.timestamps
        end
    end
end

カラムの追加は自分でしないといけない

今回、カラムを追加するので、自分でchangeメソッドの中身を書く必要がある。

class AddImageNameToUsers < ActiveRecord::Migration[5.0]
    def change
        add_column uses, image_name, string #テーブル名、カラム名、データ型
    end
end

changeメソッドの中身を実行する

$ rails db:migrate

画像の保存

ファイルの書き込み

File.write を使う。

$ rails console
> File.write("public/aaa.txt", "Hello World")
# File.write(書き込む場所, 内容)

画像データの書き込み

File.binwritereadメソッドを使う。
public/user_images/"1.jpg" に 読み込んだimageを書き込んで保存する。

    if image = params[:image]
      @user.image_name = "#{@user.id}.jpg"
      File.binwrite("public/user_images/#{@user.image_name}", image.read)
    end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

続・データベースになくても、データとして扱える活動的なハッシュ 〜表示編

はじめに

 ActiveHashの使い方については以前投稿した、こちらを参考にしてください。

ActiveHashの文字列を取り出す方法

ActiveHashに入れて保存されているデータを、ビューに表示させたいときは、カラム名だけでは、数値が表示されるだけなので、

ex)
item.prefecture.name

とカラム名の後にnameとつけると、idに紐づいた文字列が表示されるようになる。

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

RailsのJSONレスポンスの表示形式についてまとめました

JOSNレスポンスの表示形式についてよくわかってなくて
はまったので整理しました。

ActiveModelSerializerには、アダプター(JSONの表示形式)を3種類ある。

  • :attributes (default)
  • :json
  • :json_api

attributes:デフォルトで設定されているアダプタ。ルートキーなしでjsonレスポンスを生成する。
json:レスポンスは常にルートキーありでjsonレスポンスを生成する
json_api:JSONAPIという、JSONの仕様を決めている組織が制定している表示形式に沿ったレスポンスが返ってくる

:jsonと:json_apiをデフォルトで使いたい場合には、initializersディレクトリに
別途active_model_serializers.rbというような(名前はなんでもOK)ファイルを作成し、
そこに以下のようにJSONの表示形式を設定する。

# config/initializers/active_model_serializers.rb
ActiveModel::Serializer.config.adapter = :json_api

実際のレスポンスは以下の感じになります

  • attributes
[
 {"id"=>69,
  "title"=>"鍋",
  "updated_at"=>"2020-10-20T20:52:09.044Z",
  "user"=>
   {"id"=>3,
    "name"=>"xu6i65h83tbvexx5dld89w39xn4u9",
    "email"=>"3_ahmad@smith-brekke.biz"}
 }
]
  • json

"articles"がルートキーになります。
ルートキー名はcontroller名を取得しています。

{"articles"=>
  [
    {"id"=>72,
     "title"=>"あらそう",
     "updated_at"=>"2020-10-20T20:58:15.458Z",
     "user"=>
      {"id"=>3,
       "name"=>"e8zu6a5m08jlgd3w1ddlxkoa",
       "email"=>"3_ernest_denesik@deckow-gutkowski.com"}
    },
  ]
}
  • json_api
{"data"=>
  [
    {"id"=>"66",
     "type"=>"articles",
     "attributes"=>{"title"=>"ひんきゃく", "updated-at"=>"2020-10-20T20:44:16.765Z"},
    "relationships"=>
     {"user"=>
      {"data"=>
       {"id"=>"3", 
        "type"=>"users"}
       }
      }
     }
  ]
}

だんだん構造化されていってる感じですね。
json_apiがJSONの仕様に沿った表示形式ということは
一番汎用化しやすいってことですかね。

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

Ruby on Rails メールの自動送信機能 実装

内容

登録されたメールアドレスに、確認メールを自動送信する機能を実装する。

実装

①アプリ作成

sampleというアプリを作ります。

$ rails new sample

ディレクトリを移動。

$ cd sample

新規に追加されたメールアドレスに送るアプリを作りますので、Userテーブルを作成します。
今回はカラムを2つにします。

$ rails g scaffold User name email

データベースを作成します。

$ rails db:migrate

②メール送信設定

Gmailを送れるように設定をしていきます。
①config/environments/development.rb 
②config/environments/production.rb
①、②に下記のを追加してください。

Rails.application.configure do
  config.action_mailer.raise_delivery_errors = true  #falseからtrueに変更
 #中略#
  config.action_mailer.delivery_method = :smtp 
  config.action_mailer.smtp_settings = {
    address: 'smtp.gmail.com',
    domain: 'smtp.gmail.com',
    port: 587,
    user_name: Rails.application.credentials.gmail[:user_name],
    password: Rails.application.credentials.gmail[:password],
    authentication: 'login',
    enable_starttls_auto: true
  }
end

③メーラー作成

メール送信におけるコントローラー的役割を果たすものです。

メーラーの名前はSampleMailerとします。

$ rails g mailer SampleMailer

実行すると、app/mailers以下に次の2つのメーラーが作成されます。

①application_mailer 「全体のメーラーの設定」
②sample_mailer   「先ほど作成したSampleMailerという個別のメーラーの設定」

③メーラーの編集

①application_mailer 「全体のメーラーの設定」

app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
  default from:     "Yamada Taro",  #差出人の名前
          reply_to: Rails.application.credentials.gmail[:user_name] #差出人のメールアドレス
  layout 'mailer'
end

②sample_mailer   「個別のメーラーの設定」

app/mailers/sample_mailer.rb
class PostMailer < ApplicationMailer
  default from: "Yamada Taro"
  def published_email(user)
    @user = user
    mail to: user.email  #新規登録されたメールアドレス
  end
end

④メールの本文作成

メールの本文はapp/views/sample_mailerの配下に作ります。
メールの本文は、「HTMLバージョン」、「テキストバージョン」の2タイプがあります。

今回は、これを作成します。
①published_email.html.erb 「HTMLバージョン」
②published_email.tex.erb  「テキストバージョン」

app/views/sample_mailer/published_email.html.erb
<!doctype html>
<html lang="ja">
<head>
  <meta content="text/html; charset=UTF-8" />
</head>
<body>
  <h2><%= @user.name %></h2>
  <hr />
  <p>
    こんにちは! <%= @user.name %>さん!</p>
  <hr />
</body>
</html>
app/views/sample_mailer/published_email.text.erb
===============================
<%= @user.name %>様
===============================

こんにちは! <%= @user.name %>さん

⑥コントローラーの編集

コントローラーの「createメゾット」に一行追加してください。

app/controllers/users_controller.rb
class UsersController < ApplicationController
    #中略 
  def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        SampleMailer.published_email(@user).deliver #こちらを追加する。
        format.html { redirect_to @user, notice: 'User was successfully created.' }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end
   #中略 
end

⑥ルーティングの編集

最後にルーティングの設定したら完了です。

config/routes.rb
Rails.application.routes.draw do
  resources :users
  root "users#index"  #こちらを追加する。
end

最後に起動させて確認して見ましょう!

$ rails s

このように画面が出てきます!
実際に操作して確認して見て下さい。

名前とメールアドレスを登録するとメールが自動送信されます。
9.png

以上実装は終了です。
ご視聴頂きありがとうございました。

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

Ruby on RailsでRSS/Atom形式のサイトマップをつくった

自社サイトのSEO対策でRSSフィード作成を担当したのでその方法をメモしておきます。

なんでSEO対策にRSSなのか?

その前にサイトマップについておさらい。

サイトマップとは「クローラーにページを見つけてもらいやすくするためにサーバーに置くファイル」
サイトマップには以下の種類がある。

XMLサイトマップ

  • クロール・インデックスさせたいURLをすべて記述する。
  • その分サイズが大きい。
  • そのためクローラーがあんまり見に来てくれないらしい。ぴえん

RSS/Atomフィード

  • 最近の変更のみ記述する。
  • そのためサイズが小さい。
  • だからXMLサイトマップよりもクローラーが見に来てくれる頻度が高い

私が開発を担当しているサイトは、イベント情報を載せて集客をするサイトなので、
1日に新規ページが何ページも増える
→新しい増えたページをできるだけ早くクロールしてもらいたい
 →サイトマップだけではなく、RSS/Atomフィードを設置することにした。

RSSフィード作成

標準ライブラリ

RailsにはRSSを扱うための標準ライブラリ(https://docs.ruby-lang.org/ja/latest/library/rss.html) が用意されていてrequireするだけで使える。

require 'rss'

フィード作成処理

あとはRSSフィードを作りたいところで

##
# [param] event_list : フィードに載せるエントリのリスト
#
def create_rss_feed(event_list)
  # 今回はAtom1.0フォーマットで作成
  feed = RSS::Maker.make('atom') do |maker|
    maker.channel.about = 'tag:sample.com:feed' # フィードを一意に示すID。多分一意ならなんでもいい。
    maker.channel.title = "新着イベント" # フィードのタイトル
    maker.channel.description = "イベントの最新情報をご紹介します。" # フィードの説明文
    maker.channel.link = 'https://sample.com/' # サイトURL
    maker.channel.author = 'イベント事務局' # フィードの作成者
    maker.channel.date = .strftime('%Y-%m-%d %H:%M:%S') # フィードの最終更新日時

    event_list.each_with_index do |event|
      maker.items.new_item do |item|
        item.link = event.url # 詳細ページのURL
        item.title = event.title # 詳細ページのタイトル
        item.date = event.start_time.strftime('%Y-%m-%d %H:%M:%S') # イベントなら開催日、記事なら公開日など
      end
    end
  end
  render xml: feed.to_xml
end

このような処理を書いて実行すると

このようにブラウザ上でRSSフィードが表示されました!
今回はAtomというフォーマットで作成しましたが、違うフォーマットで作成するときは
RSS::Maker.make('atom')
この「atom」の箇所を例えばRSS2.0であれば「2.0」に変えればよいそう。

おわりに

標準ライブラリが用意されていたのであっという間にできてしまいました。
Railsってすごい〜〜と思うことばかりです。

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

簡単なリコメンデーション機能を作りました。

リコメンデーション機能気になる理由

  • オンラインショップで良くオススメが見えました。
    image.png

  • SNSでオススメ友達が見えました

→ オススメが最近使われています
→ 面白いので、調べたい


関連する記事


まずに映画のオススメを作ります

  • ユーザーに面白いそう映画をオススメする機能

アルゴリズム(1)

image.png


アルゴリズム(2)

image.png


アルゴリズム(3)- スコアリング

  • 関係性が高い → 点数が高い
  • 点数が高い → オススメが多い

Railsでスコアリングを書きました。

    def recommend_movies # recommend movies to a user
      # find all other users, equivalent to .where(‘id != ?’, self.id)
      other_users = self.class.all.where.not(id: self.id)
      # instantiate a new hash, set default value for any keys to 0
      recommended = Hash.new(0)
      # for each user of all other users
      other_users.each do |user|
        # find the movies this user and another user both liked
        common_movies = user.movies & self.movies
        # calculate the weight (recommendation rating)
        weight = common_movies.size.to_f / user.movies.size
        # add the extra movies the other user liked
        common_movie_ids = common_movies.pluck(:id)
        user.movies.each do |movie|
          next if common_movie_ids.include? movie.id
          # put the movie along with the cumulative weight into hash
          recommended[movie] += weight
        end
      end
      # sort by weight in descending order
      sorted_recommended = recommended.sort_by { |key, value| value }.reverse
    end

Railsで表示する

https://github.com/phamthanhthuongbk/recommendation-rails

image.png


まずに友達のオススメを作ります。

  • 映画のアルゴリズムと同じ作ります。

結果は

https://github.com/phamthanhthuongbk/recommendation-rails

image.png


感想

  • アルゴリズムが分かりやすい、効果が見えました。
  • オススメの動きがイメージが出来ました。
  • スコアリングのため、全部のDBを見ないといけないので、大きなシステムだとどうかな
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsにBootstrapを導入!!

RailsにBootstrapを導入する方法を説明致します。
手順は、とても簡単ですのでご参考にどうぞ!!
手順は、4つあります。

手順

1.Bootstrapのインストール
2.SCSSファイルの作成
3.JSファイルの修正
4.Rails(Puma)の再起動

1.Bootstrapをgemでインストール

RailsでBootstrapを使う場合は、gemを使ってインストールする方法が一般的です。
Bootstrapは内部でjQueryを利用しているので、こちらもあわせてインストールしましょう。
Gemfileに以下を追記して、bundle installを実行してみてください。

Gemfile
gem 'bootstrap', '~> 4.3.1'
gem 'jquery-rails'
ターミナル
% bundle install

2. SCSSファイルを作成

次に、application.cssをapplication.scssというファイル名に変更します。
これは、Bootstrapが「SCSS」という記法で書かれており、Railsでもあわせて利用するためです。
「SCSS」とは、CSSを拡張した記法のことで、いまのWeb業界では多く利用されている記法になります。
ここでは具体的な解説はしませんが、CSSの記述よりも見やすく、書きやすくなった記法だと思ってください。

ファイルの拡張子を変更
 変更前 app/assets/stylesheets/application.css 
 変更後 app/assets/stylesheets/application.scss

ファイル名を変更したら、実際にファイルを開いて下さい。
*= require_tree .と*= require_selfを削除し、
@import "bootstrap";を追記します。

追記したコードが、Bootstrapを読み込むための設定になります。

app/assets/stylesheets/application.scss
/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *
 *= require_tree .    <(削除)
 *= require_self      <(削除)
 */
@import "bootstrap";  <(追加

3. JSファイルを修正

Bootstrapで使われる「JavaScript」や「jQuery」などの関連ファイルを読み込む設定をします。
app/assets/javascripts/application.jsを開き、以下を参考に元々あったコードの上に追記してください。

app/assets/javascripts/application.js
# 以下の3つを追記
//= require jquery3
//= require popper
//= require bootstrap

# 元々あったコード
//= require rails-ujs
//= require activestorage
//= require turbolinks

4. Rails(Puma)を再起動

ここで一度、ブラウザからアクセスしてみてください。
もし、この段階でエラーが表示されているのであれば、Rails(Puma)を再起動します。
それでもエラーが変わらない場合は、「node.js」のバージョンが古い可能性があります。
DockerでRailsを構築した方は、Dockerfileが以下のような設定になっているかを確認してください。

Dockerfile
# Railsに必要なパッケージをインストール
RUN apt-get update -qq && apt-get install -y nodejs
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
    && apt-get install -y nodejs

# 以下の公式サイトの記述ではnode.jsのバージョンが低くてbootstrapが使えない
# RUN apt-get update -qq && apt-get install -y nodejs

まとめ

導入手順は難しいと思うかもしれませんが、この説明した手順の通りに記述を削除したり、
書き換えたりするだけですので意外と簡単です。
是非試してみて下さい!!

以上。

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

【結合テストコード】date_selectから要素を選択する方法

簡単な結合テストコードを書いていてドツボにハマったので備忘録的に残しておきます。間違っていたらご指摘頂けると幸いです。

<%= raw sprintf(
    form.date_select(
      :birthday,
      class:'select-birth',
      id:"birth-date",
      use_month_numbers: true,
      prompt:'--',
      start_year: 1930,
      end_year: (Time.now.year - 5),
      date_separator: '%s'),
    "<p> 年 </p>", "<p> 月 </p>") + "<p> 日 </p>" %>

このような年、月、日を選択するフォームで思うように要素を選択できかったので悩んでいたのですが、以下の記事が参考になりました。

使えるRSpec入門・その4「どんなブラウザ操作も自由自在!逆引きCapybara大辞典」

結論としてはブラウザで検証を行い指定したい要素をチェックすると、きちんと1つずつname属性が割り当てられていたので、そのまま記述し

select '1930',from: 'dear_person[birthday(1i)]'
  select '12',from: 'dear_person[birthday(2i)]'
  select '12',from: 'dear_person[birthday(3i)]'

こちらで無事パスしました。
完全に私のミスです。

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

フォーム項目の入力有無による条件分岐

環境

この記事ではmacOS Catalina10.15.6にインストールしたRuby 2.6.5を使っています。

前提

下記の条件分岐を行うことがゴールです。
入力必須ではない項目が入力された時→詳細画面で表示(図1)
一方、入力されなかった時→詳細画面で表示されない(図2)

図1 入力された時?
スクリーンショット 2020-10-21 16.23.34.png

図2 入力されなかった時?
スクリーンショット 2020-10-21 16.25.08.png

結論 .present?を使用

if文の条件式の際に、.present?を使用することで、条件分岐することが出来ます。
そのため、@report.otherの値が存在する際には、備考の内容が表示されます。

show.html.erb
        <% if @report.other.present? %>
          <tr>
            <th class="detail-name">備考</th>
            <td class="detail-value"><%= @report.other %></td>
          </tr>
        <% end %>

以上です。
最後までお読みいただきありがとうございます!
同じことで悩んでいる方の手助けになったら幸いです!

参考

下記のサイトを参考にして、私自身も解決出来ました。
オブジェクトの記法についてより知りたい方は、下記ご確認ください!

https://qiita.com/fursich/items/e4be106b2aa639fd3e6a

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

入力必須ではない項目の入力有無による画面の表示方法

環境

この記事ではmacOS Catalina10.15.6にインストールしたRuby 2.6.5を使っています。

概要

下記の条件分岐を行うことがゴールです。
入力必須ではない項目が入力された時→詳細画面で表示(図1)
一方、入力されなかった時→詳細画面で表示されない(図2)

図1 入力された時?
スクリーンショット 2020-10-21 16.23.34.png

図2 入力されなかった時?
スクリーンショット 2020-10-21 16.25.08.png

結論 .present?を使用

if文の条件式の際に、.present?を使用することで、条件分岐することが出来ます。
そのため、@report.otherの値が存在する際には、備考の内容が表示されます。

show.html.erb
        <% if @report.other.present? %>
          <tr>
            <th class="detail-name">備考</th>
            <td class="detail-value"><%= @report.other %></td>
          </tr>
        <% end %>

以上です。
最後までお読みいただきありがとうございます!
同じことで悩んでいる方の手助けになったら幸いです!

参考

下記のサイトを参考にして、私自身も解決出来ました。
オブジェクトの記法についてより知りたい方は、下記ご確認ください!

https://qiita.com/fursich/items/e4be106b2aa639fd3e6a

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

PayjpのCustomer作成とdefault_cardの設定

はじめに

Payjpの決済方法の記事はたくさんありますが、default_card設定方法はなかったので書かせていただきます。
トークン化については他の方が書かれているので、javascriptの記述は割愛します。

開発環境

ruby 2.6.5
Rails 6.0.3.3

参考

説明不足なところはこちらで補ってください。

リファレンス:
https://pay.jp/docs/api/#customer-%E9%A1%A7%E5%AE%A2
https://pay.jp/docs/customer

Cardモデル

自分の場合はCardモデルで下記のカラムを保存しています。

id user_id card_token customer_token
integer tok_~ cus_~

Customer作成

Customer作成にはcard_token(tok_~)が必要になります。
javascriptで受け取ったtokenをコントローラーに渡して、下記の記述をします。

cards_controller.rb
def create
    # card_tokenが正しいか確認
    if params[:card_token] == nil
      redirect_to new_user_card_path
      return
    end
    # ユーザーのcustomer_tokenが存在する場合
    if Card.find_by(user_id: current_user.id)
      card = current_user.card
      customer = Payjp::Customer.retrieve(card[0][:customer_token])
      customer.cards.create(
        card: params[:card_token]
      )
    else
    # ユーザーがcustomer_tokenが存在していない場合 
    customer = Payjp::Customer.create(
      description: "test",
      card: params[:card_token],)
    end
    # cardテーブルに保存
    card = Card.new(
      user_id: current_user.id,
      card_token: params[:card_token],
      customer_token: customer.id)
end

Customer情報取得

配列@cardsを定義して、customer_tokenをもとにcard情報を入れます

card.controller.rb
cards = Card.where(user_id: current_user.id)
      @cards = []
      cards.each do |card|
        @customer = Payjp::Customer.retrieve(card.customer_token)
        @cards << @customer.cards
      end

ユーザーにカードを選択してもらい、引数「i」で選択されたindexを受け取れるようにフォームを作成します。
ビューで@cardsに対してeach_with_indexで下記の記述でカード情報を表示させられます。

select.html.erb
<%= form_with url: set_default_card_path, method: :post, local: true do |f| %>
 <% @cards.each_with_index do |card, i| %>
   <%=f.radio_button :selected, :"#{i}" ,id: "check_card", checked: (card.data[i] [:id] == @customer[:default_card])  %>
   <%= "**** **** **** #{ + card.data[i][:last4]}" %> 
   <%= "#{card.data[i][:exp_year]}#{+ card.data[i][:exp_month]}月" %>
 <% end %>
 <%= f.submit "次へ進む" %>
<% end %>

default_cardの設定方法

select.html.erbのform_withの中でradio_buttonを使い、params[:selected]に#{i}の値を受け取っています。
@customerの[:default_card]に代入して、@customer.saveで完了します。
※@customer.saveをしないと更新されません。

cards_controller
def set_default_card
 cards = Card.where(user_id: current_user.id)
      @cards = []
      cards.each do |card|
        @customer = Payjp::Customer.retrieve(card.customer_token)
        @cards << @customer.cards
      end
 @customer = Payjp::Customer.retrieve(card.customer_token)
 index = params[:selected].to_i
    @customer[:default_card] = @cards[0].data[index][:id]
    @customer.save
end

念のため

  • customerを作成していない場合、card_token(tok_~)があれば、Payjp::Charge.createができます。
  • customerを作成した場合、cardのid(car_~)、もしくはcustomerのid(cus_~)があればPayjp::Charge.createができます。
  • customerのidを渡した場合はcustomerのdefault_cardが使われます。 (指定しない場合は最後に登録したカードがdefault_cardになります。)

最後に

もっと簡便な記述もあるかも知れませんが、これで実装することはできます。
あとは、各々アレンジしてください。

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

確認画面を経由すると画像データがnilになる時の解決方法

投稿画面→確認画面→投稿完了の流れで作成したい時ってありませんか?
確認画面加えるだけなんですが、データの保存や扱いが少し違っていたことで詰まりました。。
その時の経験を備忘録として書いていきます!

この記事が参考になるであろう方

・確認画面では画像が表示されるのに、投稿詳細画面では画像がアップロードできていない。
binding.pry等でデバッグして投稿確認のアクション(confirmアクション)の挙動を確認すると、imageだけnilになっている。
・SQL操作をして確認してみても、やはり画像データだけが保存されてない。

なぜnilになるのか?

どうやら、確認画面を経由した場合には、確認画面から戻される情報に画像データは無いみたいです。

確認画面を表示する前に画像データを別で保存しておき、それを取り出して使う必要があるようです。

解決方法の結論

・ 確認画面内にhiddenの記述を加える。
:image_cacheのパラメータを使用する。
(コントローラ内で:image_cacheを渡すのを忘れないように。。)

hidden= 隠しデータをサーバーに送信する際に使用。value属性で指定した値がサーバーへ送信する。

image_cache= 画像のデータそのものを取り扱うパラメータ。(確認画面の実装を挟む際等に使用するパラメータです。)

参考コード

new.html.erb
<div class="thumbnail">
  <%= f.file_field :image %>
  <%= f.hidden_field :image_cache %>   ← 追記
</div>
<%= f.submit "確認画面へ" %>
confirm.html.erb
<%= form_with model: @tournament, url: tournaments_path, html: { method: :post }, local: true do |f| %>
  <%= f.hidden_field :start_time %>
  <%= f.hidden_field :image %>
  <%= f.hidden_field :image_cache %>   ← 追記
  <%= f.submit "作成する"%>
<% end %>
tournaments_controller.rb
def tournament_params
    params.require(:tournament).permit(:start_time, :image, :image_cache)
end

これで画像データが受け取れて表示できる!..はずです。

最後に

確認画面を経由した場合の記述は所々変わってきてくるので、意外に詰まってしまいますね。もっとたくさんの経験して成長したいと思います!!

同じ境遇になった方のお役に立てば嬉しいです。
解決や参考になったらLGTM:thumbsup:して頂けると喜びます。笑

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

【Rails】deviseの「新規登録」「ログイン」「情報更新」機能をカスタマイズする際に必要なストロングパラメーターのsanitizerメソッド

はじめに

deviseの「新規登録」「ログイン」「情報更新」機能をカスタマイズする際に必要なストロングパラメーターのsanitizerメソッド

と長いタイトルになってしまいましたが、要は「deviseのユーザー管理機能」についてです。
deviseを使うとユーザー管理機能が簡単に作れますが、デフォルトの機能を変更するには様々な設定が必要です。
今回は「新規登録」「ログイン」「情報更新」をカスタマイズする際に必要な処理について紹介します。

目次

1.結論
2.devise_parameter_sanitizerメソッドについて
3.sanitizerメソッドの構文
4.処理毎の記述
5.記述するファイル
6.まとめ

対象の方

deviseを使った事がある
deviseのデフォルト以外の実装がしたい
ストロングパラメーターを理解してる

開発環境

ruby 2.6.5
rails 6.0.0
devise 4.7.3

1.結論

まず結論は以下のような記述になります。

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  #もしdeviseのコントローラーの事なら全てのアクションの前にメソッドを読み込む
  before_action :configure_permitted_parameters, if: :devise_controller? #ログイン機能について
  before_action :configure_account_update_parameters, if: :devise_controller? #編集機能について

  private
  #ログイン機能について
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname,  :family_name_kanji, :first_name_kanji, :birthday])
  end
  #編集機能について
  def configure_account_update_parameters
    devise_parameter_sanitizer.permit(:account_update, keys: [:nickname,  :family_name_kanji, :first_name_kanji, :birthday])
  end

end

※注意:「新規登録」と「情報更新」しか実装していないので、その2つについて記述します。

2.devise_parameter_sanitizerメソッドについて

まずメソッドの説明をします。

2.1 使用するタイミング

「新規登録」「ログイン」「情報更新」をデフォルト以外にカスタマイズしたい時です。

2.2 sanitizerメソッド

sanitizerメソッドとはdeviseのUserモデルに関わるパラメーターを取得するメソッドです。
deviceの内部にデフォルトでパラメーターを取得する記述がされてますが、これに消毒剤=(sanitizer)をかけてカスタマイズできる状態にすることです。
※注意:個人的な解釈の仕方です。

次に、sanitizerメソッドとpermitメソッドを組み合わせます。
そうする事で、deviseにデフォルトで定義されているストロングパラメーターに対して、自分で新しく追加したカラムも含めることができます。

2.2 二種類あるpermitメソッドの違い

permitメソッドが二種類あるので、脱線しますが少し説明します。
「sanitizer」のpermitはdeviseのパラメーターを取得するためのメソッドです。
「Rails」のコントローラーで保存時などに使用してるparamsのpermitメソッドとは異なります。

下記がそれぞれの例です。

controller.rb
#例) paramsのpermitメソッド
params.require(:モデル名).permit(:許可したいキー)
app/controllers/application_controller.rb
#例) devise_parameter_sanitizerのpermitメソッド
devise_parameter_sanitizer.permit(:deviseの処理名, keys: [:許可したいキー(カラム名)]

3. sanitizerメソッドの構文

メソッド名はconfigure_permitted_parametersと慣習的に定義されてますが、自由に命名しても差し支えありません。

app/controllers/application_controller.rb
private
def configure_permitted_parameters  # メソッド名は自由に命名しても差し支えありません。

  # deviseのUserモデルにパラメーターを許可
  devise_parameter_sanitizer.permit(:deviseの処理名, keys: [:許可したいキー(カラム名)])
end

※注意:プライベートメソッドの中で定義します。

以上devise_parameter_sanitizerメソッドの説明でした。

4.処理毎の記述

「2.1 使用するタイミング」 でも触れましたが処理する目的で「:devise処理名」の記述が変わります。
処理する目的は「新規登録」「ログイン」「情報更新」です。

処理名 目的
:sign_in ログイン(サインイン)の処理を行うとき
:sign_up 新規登録(サインアップ)の処理を行うとき
:account_update アカウント情報更新の処理を行うとき

5.記述するファイル

「どこに記述するか」ですが、これは「すべてのコントローラーが継承しているファイル」です。
つまり、application_controller.rbファイルです。
このコントローラーが読み込まれた後、他すべてのコントローラーが読み込まれます。
また、全てのアクションの処理前に処理したいのでbefore_actionを使います。

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?
  #↑これ#
  private
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname])
                   #↑(:deviseの処理名, keys: [:許可したいキー(カラム名)])
  end
end

これでほとんどの実装ができました。あとはpermitも後を自分のしたい事に応じて編集するだけです。
上記は
deviseの処理名 = :sign_up
keys = [:nickname]
で実装してます。

6.まとめ

手順のポイントは
application_controller.rbに記述
before_actionを設定
sanitizer.permitメソッドを使用

以上、deviseの「新規登録」「ログイン」「情報更新」機能をカスタマイズする際に必要なストロングパラメーターのsanitizerメソッドについてでした。

最後に

私はプログラミング初学者ですが、同じ様に悩んでる方々の助けになればと思い、記事を投稿しております。
それでは、また次回お会いしましょう〜

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

【Rails6】Google Map をアプリに埋め込み、入力した住所にマーカーをつける。【細かいところの確認】

簡単に実装できるはずのGoogleMapAPIですが数々の沼にハマったので細かく注意していきます。

環境

Rails 6.0.0
Ruby 2.6.5
EC2
Amazon Linux2
Nginx
mariaDB
Capistrano

機能

住所を入れると48b7ab460e405caaf463dd4963cd52af.png
DBに住所が保存、緯度経度が自動で算出されて
f57e6c8b1a108791d56e024334075861.png

表示されます。
d801305aebecc331b0cfd2a2bb7970d2.jpg

Google Mapをアプリに埋め込む

Google Map API(サービス紹介ページ)

Google Map APIは、GoogleCloudのサービスのひとつで、GoogleCloudPlatformというコンソールから操作します、まずはそこで、Google Map javascript APIのAPIKeyを取得します。

GoogleCloudPlatformへ

☆Googleのアカウントがなければまずこちらから登録してください。
Googleアカウント登録
アカウントを作成したら(持っていたら)コンソールへ
https://console.cloud.google.com/

プロジェクトを作成し、APIKeyを取得→地図表示

https://qiita.com/nagaseToya/items/e49977efb686ed05eadb
一連の流れはこちらにわかりやすく書かれています。

今回は、ここに加えて任意の住所記録、保存、出力します。

Geocording

緯度と経度を算出して、特定の位置を見つけてくれる機能です。gemのGeocoderと、Google CloudのGeocodeing APIというサービスを使います。
gemだけでも位置情報を取得することはできますが、「東京駅」では取得できても、「東京都〇〇区〇〇○○ー◯○」という具体的なアドレスでは取得できません。また取得できたりできなかったりします。そのためにより性能の良いGeocodeing APIも使えるようにします。

コード

モデルは作成されているとします。(例Performancesモデル)

①マイグレーションファイルを作成(カラム追加)

% rails g migration AddColumnsToPerformances

・入力された住所addressカラム
・geocodeによって自動で算出される緯度、経度カラム

class AddColumnsToPerformances < ActiveRecord::Migration[6.0]
  def change
    add_column :performances, :address, :string
    add_column :performances, :latitude, :float
    add_column :performances, :longitude, :float
  end
end
% rails db:migrate

rollbackでもカラムは変更できますが、データが消えるのでなるべくadd_column(カラム追加)にすると良いと思います!

②入力フォームの作成

保存先はaddressのみで大丈夫です。

<%= form_with(model: @performance, local: true) do |f| %>
***抜粋***
<label for="group-name">住所(GoogleMap表示)</label>
<span class="indispensable-any">任意</span>
<%= f.text_area :address,class:"new-performance-box", id:"gmap", placeholder:"Google Mapの住所をコピーして貼り付けてください" %>  
***抜粋***

③コントローラー

ストロングパラメーターでaddressを指定します。

performances_controller.erb
before_action :set_performance, only: [:表示させるview]

def create
   @performance = Performance.new(performance_params)
   if @performance.valid?
     @performance.save
     redirect_to "/users/#{current_user.id}"
   else
     render :new
   end
end

def 表示させるview
    @performance = Performance.new(performance_params)
end

private

def set_performance
   @performance = Performance.find(params[:id])
end

def performance_params
 params.require(:performance).permit(:address).merge(user_id: current_user.id)
end

④ビュー

CSSは別記してます。
zoomControl: false,
mapTypeControl: false,
fullscreenControl: false,
treetViewControl: false,
は拡大縮小ボタンなどを消す地図表示のオプションです。

<div id='map'>
<script>
let map
function initMap(){
  map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: <%= @performance.latitude %>, lng: <%= @performance.longitude %>},
    zoom: 15,
       zoomControl: false,
       mapTypeControl: false,
       fullscreenControl: false,
       streetViewControl: false,
  });

  marker = new google.maps.Marker({
    position: {lat: <%= @performance.latitude %>, lng: <%= @performance.longitude %>},
    map: map
  });
   geocoder = new google.maps.Geocoder()
}
</script>
  <script src="https://maps.googleapis.com/maps/api/js?key=<%= ENV['GOOGLE_MAP_API'] %>&callback=initMap" async defer></script>
</div>

※key=<%= ENV['GOOGLE_MAP_API'] %>の表記は充分気をつけてください!ここで=の位置が違うだけで全てうまくいきません・・・

⑤モデル

これでgeocordが緯度経度を算出してカラムに保存してくれます

performance.rb
geocoded_by :address
after_validation :geocode, if: :address_changed?

※if: :address_changed?がないと作用しないことがあるので気をつけてください!私はこれを書かないとダメでした

⑥Geocording APIを使用するための記述

% rails generate geocoder:config
/config/initializes/geocoder.rb
Geocoder.configure(
  # Geocoding options
  # timeout: 5,                 # geocoding service timeout (secs)
  lookup: :google,         # name of geocoding service (symbol)
  # ip_lookup: :ipinfo_io,      # name of IP address geocoding service (symbol)
  # language: :en,              # ISO-639 language code
  use_https: true,           # use HTTPS for lookup requests? (if supported)
  # http_proxy: nil,            # HTTP proxy server (user:pass@host:port)
  # https_proxy: nil,           # HTTPS proxy server (user:pass@host:port)
  api_key: 'YOUR_API_KEY',               # API key for geocoding service
  # cache: nil,                 # cache object (must respond to #[], #[]=, and #del)
  # cache_prefix: 'geocoder:',  # prefix (string) to use for all cache keys

  # Exceptions that should not be rescued by default
  # (if you want to implement custom error handling);
  # supports SocketError and Timeout::Error
  # always_raise: [],

  # Calculation options
  units: :km # :km for kilometers or :mi for miles
  # distances: :linear          # :spherical or :linear
)

うまくいかない時の確認事項

・環境変数の設定
・viewの記述
・モデルのメソッド
・geocorder.rb

%rails c
[1] pry(main)> Geocoder.coordinates("〒150-0043 東京都渋谷区道玄坂2丁目1")
=> [35.6591376, 139.7007901]

で中身を変えながら出力されるか試してみる
・Google Map javascriptと、Geocoding APIのAPIkeyを一緒にしている場合、APIをもうひとつ作成し、別々にしてみる。
・本番環境での環境変数設定

[ec2-user@〜〜〜〜〜〜〜]$ sudo vim /etc/environment

変数設定後exit→再起動

[ec2-user@〜〜〜〜〜〜〜]$ env | grep YOUR_API_KEY

で確認
・EC2サーバーから再起動してみる(私はこれで最終的に本番環境で確認が取れました)

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

RSpecでコピペのテスト

権限によってペーストができなくなる機能のテストをしようと思ったら全然うまいこと行かずにかなりハマったのでメモ。

# コピー
page.execute_script('
  var copy_target = document.getElementById("copy_target");
  copy_target.select();
  document.execCommand("copy");
')

# ペースト
find_by_id('paste_target').send_keys [:control, 'V']
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails Tutorial 0章:事前基礎知識編①

1.事前基礎知識編

私がRailsを学び始めて最初に躓いたのが、ライブラリ・フレームワークといった謎の言葉達でした。
一つ一つGoogleで検索して言葉の意味を調べてもあまりしっくりきませんでした。

Ruby on RailsとはWebアプリケーションフレームワークです。そもそもWebアプリケーションフレームワークとは、動的なウェブサイト、Webアプリケーション、Webサービスの開発をサポートするために設計されたアプリケーションフレームワークのことを言います。フレームワークは日本語では「枠組み」というふうに言われますが、まさにその通りで、このRailsもプログラミング言語のRubyで使えるフレームワークなのです。Railsの基本理念は「Don’t Repeat Yourself(DRY)」、「Convention over Configuration(CoC)」でそれぞれ「同じことは繰り返さない」、「設定より規約」という意味になります。
引用:https://techacademy.jp/magazine/7011

理解力の乏しい私にはこの文章では理解できませんでした( ノД`)シクシク…

私の言葉で言い換えるとフレームワーク=テンプレート(雛型)です

みなさん、Microsoft WORDやEXCELなどを使って履歴書を一から作った事ありますか?
私は約15年前の学生時代にEXCELを使って自分で履歴書を一から作らさせられました。
今時代に履歴書を白紙状態から作るなんてことはないと思います。
履歴書の雛型(テンプレート)をダウンロードして必要な情報を埋めて履歴書を作りますよね?
それと同じでWEBアプリケーションも雛型を元に必要事項を埋める事で最低限の機能を持ったWEBアプリが作れる時代になっているみたいです。

RailsはRubyというプログラミング言語でWEBアプリケーションを作る時によく利用されるテンプレート

余談ですが、Pythonというプログラミング言語ではRailsの利用はできません。
PythonではWEBアプリケーションを作る為にdjangoというフレームワークがよく利用されている様です。
フレームワークは共通概念も多いので一つフレームワークを使ったアプリ開発を行うと、こんな風にやるのね~とイメージが掴めて別のフレームワークで開発を使用する際にも活きるようです。また現在のWEBアプリケーションは様々な言語が組み合わされて作られているそうで、Railsは主にログインやユーザー管理部分などウェブアプリケーションに必要な基本的な部分を作る為に使われている様です。
例えば、最近話題のAI(機械学習)の機能を持ったウェブアプリケーションを作りたい場合は、
機械学習が得意なpythonというプログラミング言語で機械学習部分を作成し、ウェブアプリケーションの基本的な部分はRuby on Railsで作って組み合わせる事が可能とのこと。

ライブラリって何?

フレームワーク」は、よく「ライブラリ」という言葉と混同されがちですが、ライブラリというのは特定の機能を提供し、プログラムの中でそれらを呼び出すことで動作するものです。
引用:https://techacademy.jp/magazine/7011

これも私の言葉で言い換えるとライブラリ=パーツ(部品)です

また履歴書を例にしますが、氏名を書く欄、写真を張る場所、学歴・職歴を書く欄、趣味・特技を書く欄などの様々なパーツが組み合わさって履歴書というテンプレートが出来ています。

履歴書と同じようにWEBアプリケーションもいろんな部品が組み合わさってテンプレートが出来ています。
その個々の部品の事をライブラリと呼ぶ様です。
例えば、ログイン機能を簡単に実装する為にdeviseというライブラリ(部品)があります。
一から作ると(。´・ω・)ん?わけわからないどうやって動いてるの?
ってなるログイン機能もdeviseという部品を使うと比較的簡単に実装出来ます。

プログラミング言語の得意分野・不得意分野

RubyはRailsがあるのでWEBアプリケーション開発が得意分野。
javaは大規模な分散処理が得意だったり、pythonは機械学習が得意らしいです。

何故、プログラミング言語に得意分野・不得意分野があるかというと、アプリケーションはライブラリ(部品)を組み合わせて作るからです。pythonは機械学習用の多くの部品が既に存在し、天才達が新たな部品を開発したり、今ある部品を改善してくれてくれたりしています。一方でRubyは機械学習用ライブラリが少なく、同様の機能を実装する為には部品を一つ一つ自作していく必要があります。
このような差がプログラミング言語の得意・不得意を持つ要因となっている様です。

セイト先生のWeb・IT塾主要プログラミング言語16選!特徴と初心者向けおすすめ度まとめ
プログラミング言語の得意分野などが開設されていて分かりやすい動画でした。
頭のいい方々は説明も上手なんですね。
【Web/IT業界あるある】締め切り、プログラミング中、エンジニア面接
学習の息抜きにこの動画も見てみました。
特に後半のエンジニア面接部分は非常に興味深かったです。
少しRuby on Railsを頑張ろうってモチベーションUPがアップしました。

まとめ
  • フレームワーク= WEBアプリケーション用に用意されたテンプレート
  • ライブラリ  = WEBアプリケーション用に利用できるパーツ
  • Rails     = Rubyで使えるWEBアプリケーション用フレームワーク
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails Tutorial 0 - 基礎知識

1.Railsの基礎知識

私がRailsを学び始めて最初に躓いたのが、ライブラリ・フレームワークといった謎の言葉達でした。
一つ一つGoogleで検索して言葉の意味を調べてもあまりしっくりきませんでした。

Ruby on RailsとはWebアプリケーションフレームワークです。そもそもWebアプリケーションフレームワークとは、動的なウェブサイト、Webアプリケーション、Webサービスの開発をサポートするために設計されたアプリケーションフレームワークのことを言います。フレームワークは日本語では「枠組み」というふうに言われますが、まさにその通りで、このRailsもプログラミング言語のRubyで使えるフレームワークなのです。Railsの基本理念は「Don’t Repeat Yourself(DRY)」、「Convention over Configuration(CoC)」でそれぞれ「同じことは繰り返さない」、「設定より規約」という意味になります。引用:https://techacademy.jp/magazine/7011

頭のいい方々は理解できるのかもしれませんが、理解力の乏しい私には理解できませんでした。

私の言葉で言い換えるとフレームワーク=テンプレート(雛型)です

みなさん、Microsoft WORDやEXCELなどを使って履歴書を一から作った事ありますか?
今の時代は流石にそんなことはないと思います。
履歴書の雛型(テンプレート)をダウンロードして必要な情報を埋めて履歴書を作りますよね?
それと同じでWEBアプリケーションもテンプレートをダウンロードして必要事項を埋めると最低限の機能を持ったモノが作れるようになっています。

結論:RailsはRubyというプログラミング言語でWEBアプリケーションを作る時によく利用されるテンプレート

余談ですが、Pythonというプログラミング言語ではWEBアプリケーションを作る為にdjangoというフレームワークがよく利用されている様です。Railsはpythonというプログラミング言語では利用できません。ただし、フレームワーク自体の構造は似ている様なのでフレームワークというモノを利用してどうやってアプリケーションを作る事のかを利用する事はできるそうです。

ライブラリって何?

フレームワーク」は、よく「ライブラリ」という言葉と混同されがちですが、ライブラリというのは特定の機能を提供し、プログラムの中でそれらを呼び出すことで動作するものです。
引用:https://techacademy.jp/magazine/7011

これも私の言葉で言い換えるとライブラリ=パーツ(部品)です

また履歴書を例にしますが、氏名を書く欄、写真を張る場所、学歴・職歴を書く欄、趣味・特技を書く欄などの様々なパーツが組み合わさって履歴書というテンプレートが出来ています。

履歴書と同じようにWEBアプリケーションもいろんな部品が組み合わさってテンプレートが出来ています。
その個々の部品の事をライブラリと呼ぶ様です。
例えば、ログイン機能を簡単に実装する為にdeviseというライブラリ(部品)があります。
一から作ると(。´・ω・)ん?わけわからないどうやって動いてるの?
ってなるログイン機能もdeviseという部品を使うと比較的簡単に実装出来ます。

まとめ
  • フレームワーク= WEBアプリケーション用に用意されたテンプレート
  • ライブラリ  = WEBアプリケーション用に利用できるパーツ
  • Rails     = Rubyで使えるWEBアプリケーション用フレームワーク
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails Tutorial 0章:事前基礎知識編

1.事前基礎知識編

私がRailsを学び始めて最初に躓いたのが、ライブラリ・フレームワークといった謎の言葉達でした。
一つ一つGoogleで検索して言葉の意味を調べてもあまりしっくりきませんでした。

Ruby on RailsとはWebアプリケーションフレームワークです。そもそもWebアプリケーションフレームワークとは、動的なウェブサイト、Webアプリケーション、Webサービスの開発をサポートするために設計されたアプリケーションフレームワークのことを言います。フレームワークは日本語では「枠組み」というふうに言われますが、まさにその通りで、このRailsもプログラミング言語のRubyで使えるフレームワークなのです。Railsの基本理念は「Don’t Repeat Yourself(DRY)」、「Convention over Configuration(CoC)」でそれぞれ「同じことは繰り返さない」、「設定より規約」という意味になります。
引用:https://techacademy.jp/magazine/7011

理解力の乏しい私にはこの文章では理解できませんでした( ノД`)シクシク…

私の言葉で言い換えるとフレームワーク=テンプレート(雛型)です

みなさん、Microsoft WORDやEXCELなどを使って履歴書を一から作った事ありますか?
私は約15年前の学生時代にEXCELを使って自分で履歴書を一から作らさせられました。
今時代に履歴書を白紙状態から作るなんてことはないと思います。
履歴書の雛型(テンプレート)をダウンロードして必要な情報を埋めて履歴書を作りますよね?
それと同じでWEBアプリケーションも雛型を元に必要事項を埋める事で最低限の機能を持ったWEBアプリが作れる時代になっているみたいです。

RailsはRubyというプログラミング言語でWEBアプリケーションを作る時によく利用されるテンプレート

余談ですが、Pythonというプログラミング言語ではRailsの利用はできません。
PythonではWEBアプリケーションを作る為にdjangoというフレームワークがよく利用されている様です。
フレームワークは共通概念も多いので一つフレームワークを使ったアプリ開発を行うと、こんな風にやるのね~とイメージが掴めて別のフレームワークで開発を使用する際にも活きるようです。また現在のWEBアプリケーションは様々な言語が組み合わされて作られているそうで、Railsは主にログインやユーザー管理部分などウェブアプリケーションに必要な基本的な部分を作る為に使われている様です。
例えば、最近話題のAI(機械学習)の機能を持ったウェブアプリケーションを作りたい場合は、
機械学習が得意なpythonというプログラミング言語で機械学習部分を作成し、ウェブアプリケーションの基本的な部分はRuby on Railsで作るという組み合わせるも可能との事です。

ライブラリって何?

フレームワーク」は、よく「ライブラリ」という言葉と混同されがちですが、ライブラリというのは特定の機能を提供し、プログラムの中でそれらを呼び出すことで動作するものです。
引用:https://techacademy.jp/magazine/7011

これも私の言葉で言い換えるとライブラリ=パーツ(部品)です

また履歴書を例にしますが、氏名を書く欄、写真を張る場所、学歴・職歴を書く欄、趣味・特技を書く欄などの様々なパーツが組み合わさって履歴書というテンプレートが出来ています。

履歴書と同じようにWEBアプリケーションもいろんな部品が組み合わさってテンプレートが出来ています。
その個々の部品の事をライブラリと呼ぶ様です。
例えば、ログイン機能を簡単に実装する為にdeviseというライブラリ(部品)があります。
一から作ると(。´・ω・)ん?わけわからないどうやって動いてるの?
ってなるログイン機能もdeviseという部品を使うと比較的簡単に実装出来ます。

各プログラミング言語には得意分野があるそうです。
RubyはRailsがあるのでWEBアプリケーション開発が得意分野。
javaは大規模な分散処理が得意だったり、機械学習はpythonが得意らしいです。

何故、プログラミング言語に得意分野・不得意分野があるかというと、
アプリケーションは部品をライブラリを組み合わせて作るからです。
pythonには多くの機械学習用ライブラリが存在し、今もなお天才の方々がライブラリを作ってくれています。
逆にRubyでは機械学習用ライブラリが少ないので同様の機能を全て自作していく必要があります。
このような差がプログラミング言語の得意・不得意に繋がっている様です。

まとめ
  • フレームワーク= WEBアプリケーション用に用意されたテンプレート
  • ライブラリ  = WEBアプリケーション用に利用できるパーツ
  • Rails     = Rubyで使えるWEBアプリケーション用フレームワーク

間違っていたらご指摘ください。( `・∀・´)ノヨロシク

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

link_toで改行したボタンを作りたい[備忘録]

link_toで改行したボタンを作りたい[備忘録]

改行を含んだボタンを作りたいなと思った時に、困ったので備忘録として記載します。

間違った例

<%= %>の中に改行させるべく</br>を入力するとそのまま出力されてしまいます。

<%= link_to "<h2>ログイン</h2></br>ログインすると、コメント・いいねが可能です!",new_user_registration_path, {class: "btn btn-success"} %>

キャプチャ.PNG

結論

原因は、エスケープ処理をしていないからです。
リンクするテキストにrawを含んでエスケープを無効化します。

= link_to raw("リンクテキスト一行目<br/>リンクテキスト二行目"), hoges_path

<%= link_to raw("<h2>ログイン</h2></br>ログインすると、コメント・いいねが可能です!"),new_user_registration_path, {class: "btn btn-success"} %>

キャプチャ2.PNG

エスケープ文字って何?

特殊文字 <p>や<br>などの特殊文字の効果を無効化させることです。

参照
https://noterr0001.hateblo.jp/entry/20151208/1449579773

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

Heroku上でのエラー解決方法

環境

この記事ではmacOS Catalina10.15.6にインストールしたRuby 2.6.5を使っています。

手順

Heroku上でエラーが発生した際には、エラーログを確認してエラー解決を行う必要があります。
以下の5つの手順で解決可能です。

1.エラー発生

Herokuへアクセスすると、下記の画像の内容が表示されました。

スクリーンショット 2020-10-21 9.23.35.png
サイトでは、エラーの具体的な内容がわからないのでターミナルでエラーログを確認します。

2.エラーログを出力

terminal
heroku logs --tail --app <<アプリケーション名>>

を入力するとエラーログが表示されます。

実際にエラーが起こったログを探します。

3.エラー発見

スクリーンショット 2020-10-21 9.50.37.png
エラーの内容から原因の仮説を立て、解決策を考えます。

4.仮説

エラー内容はHeroku上にコメントテーブルが存在しないよとのことなので、Heroku上のデータベースにマイグレーションの内容が反映されていないと予測。
Heroku上でマイグレーションを実行を行えば、解決する可能性有り。

実際に検証します。

5.検証

terminal
heroku run rails db:migrate

実行後、再度アクセス。
無事解決!

まとめ

Heroku上でエラーが起こった際の手順
大きく分けると3step
・エラーログを出力
・最新のエラーを発見
・仮説検証
以上です。

最後まで読んでいただきありがとうございます!
同じような課題にぶつかっている方のお役に立てれば、嬉しいです!

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

CapistranoでEC2への自動デプロイ時、SSHキー認証エラーが出たときの対処法

共有すること

Railsで開発を行っていて、Capistranoを使用しAWSへの自動デプロイを実装しました。
あるとき突然、SSHキー認証エラーが起きてデプロイできなくなってしまったので、
その解決策を簡単に共有します。

エラー内容

$ bundle exec cap production deploy

でデプロイ実行時、以下のようなエラーが出ました。

SSHKit::Runner::ExecuteError: Exception while executing as ec2-user@ElasticIP: Authentication failed for user ec2-user@ElasticIP

解決策

ターミナルを再起動するとsshキーが消えてしまうようなので以下のようにすることで、登録し直しが必要でした。

ターミナルのローカルで

$ eval \`ssh-agent `
$ ssh-add -K ~/.ssh/<キーの名前>.pem

このようにすることで、sshキーを保存しておくことができまして、無事にデプロイできました!

会社の紹介

私は現在、株式会社ダイアログという物流×ITの会社に勤務しております。
2020年10月現在、エンジニアの募集はしていませんが、他にも様々な職種を募集しているので、Wantedlyのページをご覧ください。

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

include?メソッドの使い方

この記事ではmacOS Catalina10.15.6にインストールしたRuby 2.6.5を使っています。
include?メソッドについて自分なりにまとめました。

include?メソッド

  • 引数で指定した要素が配列や文字列内に入っているか判定するメソッド
array = ["dog", "cat"]
puts array.include?("dog") # => true
puts array.include?("hoge") # => false

実際のコードでは

  • 出力例 登録したい名前を入力してください(例)YamadaTaro
  • この場合は入力した名前を受け取って「.」や「空白」があればエラー文を出力したいということですね。
def check_name(name)
  if name.include?(".")
    puts "!エラー!記号は登録できません"
  elsif name.include?(" ")
    puts "!エラー!空白は登録できません"
  else
    puts "登録が完了しました"
  end
end

puts '登録したい名前を入力してください'
name = gets
check_name(name)
  • 2行目、checkメソッドの引数nameにinclude?の引数”.”(ピリオド)があればtrueを返してエラー文が出力されます。
  • 4行目、同様に、nameにinclude?の引数” ”(空白)があればtrueを返してエラー文が出力されます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RESTが分かればRuby on Rails チュートリアルの見通しがよくなる話

この記事を読んで得られること

「いきあたりばったり」にチュートリアルをこなすのではなく、一筋の光が通った状態でチュートリアルを進めることができるようになる(かも)

想定読者はWEB周りの予備知識があまりなく
Railsチュートリアル途中か終わってすぐぐらいの人
(私がそうです)

RESTって何?

雑に言うと、webの設計思想のこと
RailsもRESTの思想に沿って設計されている

実はRailsチュートリアル2章のコラム2.2(第4版の場合)にチュートリアルを
読みこなすのに必要そうなRESTの概要が書かれていますが
よくわからないままサッと見て先に進んだ人もいるのではないでしょうか
私は進みました

が、

RESTの概念はチュートリアル中ついて回っている(というか骨子とすら言える)ので
チュートリアル中に早めになんとなくでも掴んでおいたほうが
一貫した構造や著者が考えていることが見えてきて迷子になりにくいのではないかと思います

RESTの概念はかなり抽象的なのですぐ全部理解しなくてもよいと思いますが
わかるとチュートリアル内のことだけでなくチュートリアルの外の
web世界も少しクリアに見ることができてお得です

以下、自分が感じたレベル別に解説していく

レベル1 HTTPリクエストとCRUD操作の関係の理解
レベル2 resourcesでルーティングされる内容の理解
レベル3 scaffoldで生成される謎のアクション群の理解
レベル4 RESTそのものの理解

レベル1 HTTPリクエストとCRUD操作の関係の理解

ユーザがブラウザを操作するとHTTPリクエストが送られる
Railsチュートリアルではそのリクエストを元にデータベースを操作する部分を書いたり
ブラウザ操作手順をテストに書いて動作確認することがほとんどだ

これだけわかればチュートリアル中の内容はとりあえず何とかなると思う

・8つあるHTTPリクエストのうちよく使われる4つ

HTTPリクエスト 処理
GET 取得
POST 登録
PUT 更新
DELETE 削除

 
・データベースに必要な操作

 CRUD操作  処理
READ 取得
CREATE 登録
UPDATE 更新
DELETE 削除

 
・それぞれの対応

HTTPリクエスト CRUD操作 処理
GET READ 取得
POST CREATE 登録
PUT UPDATE 更新
DELETE DELETE 削除

レベル2 resourcesでルーティングされる内容の理解

Q:「routes.rb」に「resources :users」と書くだけで
  なんで諸々よしなにルーティングしてくれるの?

routes.rb
Rails.application.routes.draw do
  resources :users
end

A: Railsはresourcesと宣言するとデフォルトで勝手に
  GETとPOSTとPUTとDELETEに基づいて気を利かせて
  URLとコントローラーのアクションを対応付けて以下を生成してくれます

URL アクション HTTPリクエスト 名前付きルート 用途
/users index GET users_path ユーザ一覧画面を表示
/users/:id show GET user_path(user) 特定ユーザの画面を表示
/users/new new GET new_user_path 新規ユーザの登録画面を表示
/users/:id/edit edit GET edit_user_path(user) ユーザの編集画面を表示
/users create POST users_path ユーザの登録アクション
/users/:id update PATCH/PUT user_path(user) ユーザの更新アクション
/users/:id destroy DELETE user_path(user) ユーザの削除アクション

レベル3 scaffoldで生成される謎のアクション群の理解

scaffoldを使うとusersコントローラの中に以下の7アクションが勝手に生成されると思います

def index
def show
def new
def edit
def create
def update
def destroy

初めの頃は勝手にいろいろ作られて何がなんだかわからなかったと思いますが
ここまでくればそれぞれの関連が見えてきたと思います
この7つなのはRailsのテンプレートだからということみたいです。
(不要なアクションは削除できるし
 必要なら自作アクションを追加することが可能)

説明が前後してしまいますが
「routes.rb」に「resources :コントローラ名」と書くと7アクションすべてのルーティングになりますが
チュートリアル13章のように:onlyオプションをつけると必要なルーティングだけを生成できます

routes.rb
Rails.application.routes.draw do
  resources :microposts, only: [:create, :destroy]
end

レベル4 RESTそのものの理解

結局RESTって?

本来のRESTの設計原則は以下の4つあるようです

  • アドレス指定可能なURIで公開されていること
  • インターフェース(HTTPメソッドの利用)の統一がされていること
  • ステートレスであること
  • 処理結果がHTTPステータスコードで通知されること

引用元:REST入門 基礎知識

Railsチュートリアルで必要なのは上記のREST原則のうち

  • インターフェース(HTTPメソッドの利用)の統一がされていること

だけです。(この記事もそこに焦点を当てています)
その他のことの詳細は引用元リンクをご参照ください

ただ、これだけわかっていれば各種サービスのAPIもRESTを意識して作られていることが
多いようなので、ほかのRESTfulなサービスとの連携がしやすいということになります

まとめ

Railsを使うならRESTfulなスタイルを採用するのが前提ということが
なんとなくわかってもらえれば幸いです

自分で作る部分もRESTに沿うし、Railsがよしなにやってくれる部分も
RESTに沿っているのでそのことを理解しながらチュートリアルを進めたほうがよさそうです

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

 投稿機能アプリv 結合コード

 

本日は、実際に投稿機能を持ったアプリケーションにおける結合コードについて
学びを深め、実践してみた。
その中で、ポイントとなる点がいくつかあったので、ポイントごとにまとめていきたいとおもう。

ポイント1:have_selector
ポイント2:Capibara
ポイント3:fill_in

image.png

 have_selectorについて

image.png

have_selectorについてはHTMLにおけるクラスや、idを指定する際に使用する。

Capibaraについて


Capibaraのgemの導入によって要素の検索を行うことが可能となる。

Capibaraのfinderによって要素の検索を可能としていることが判ったが、その検索対象は本当に様々で、
数多くの要素の検索を可能とする。
例としてはHTMLのタグであったり、cssのプロパティ、他には、Slectタグのどれを選んだのかもテスト
することができる。

また、要素の操作性能をテストすることも可能であり、例えば、clickなどの、クリックした際に反応を示すか(アニメーション?)どうかを
確認することができる。

 have_contentについて


 は基本的に、テキストに対して指定する時に使用する。

image.png

テストのコードを細かく見ていったときに、実践して判ったことは
Fill_inで指定するのはラベルのtext、id, name など属性がそれぞれ存在するなかで、選択するのはいづれかでよいということがわかった

投稿した内容のツイートの存在を確認するテストにおいては
コードの記述が、基本的にJavascriptと似ているという特徴がある。
例えば、JSでcontent_testといったようにclassを指定して、buildHTMLをおこなうように、
このテストコードでも該当のclassを指定してそこのclassにツイートが存在するかを確かめることができる。
→更にはback-ground-imageなどのようにURLを指定することで、画像のURL が存在するかどうかも確かめることが可能であるということもわかった。

これまでは正常系のテストについて確認したが、ここからは異常系のテストについてまとめていこうと思う。(異常系のテストコードの写真)

ポイント1:beforeアクションの仕組み
ポイント2:have_link
ポイント3:all
ポイント4:find_link().click
ポイント5:rails_helper.rbについて

 beforeについて

  beforeアクションはテストをそれぞれ実行する前に働かせるものであるが
  

image.png

image.png

このように@tweet1,2と変数を作った時に、FactoryBotのなかにある:userの情報を取ってくることができるのは
Factoriesのtweets.rbでassociation :userの表記によって、userとtweetのアソシエーションが組まれているからである。

もし、アソシエーションがうまく組まれていなかったりして、Userの情報がちゃんと構成されていないとテストの結果は
うまくいかなくなってしまう。

 have_link について

image.png

例としてexpect(要素).have_linkの記述によって、要素の中に当てはまるリンクを確認することができる。

 all について

image.png

allによって存在する同じ名前のclassを全て取得することができる。


これはmoreクラスの一つ目のボタンを重ねた時に編集という文字があり、
edit_tweet_pathへととぶリンクがあるかどうかを確認している。

 find_link() について

image.png

このfind_link().clickは
A要素に対してのみ使用可能である。

rails_helper.rb について

テストで使う共通のコードをまとめている。

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

 投稿機能アプリ 結合コード 実践

 

本日は、実際に投稿機能を持ったアプリケーションにおける結合コードについて
学びを深め、実践してみた。
その中で、ポイントとなる点がいくつかあったので、ポイントごとにまとめていきたいとおもう。

ポイント1:have_selector
ポイント2:Capibara
ポイント3:have_content

image.png

 have_selectorについて

image.png

have_selectorについてはHTMLにおけるクラスや、idを指定する際に使用する。

Capibaraについて


Capibaraのgemの導入によって要素の検索を行うことが可能となる。

Capibaraのfinderによって要素の検索を可能としていることが判ったが、その検索対象は本当に様々で、
数多くの要素の検索を可能とする。
例としてはHTMLのタグであったり、cssのプロパティ、他には、Slectタグのどれを選んだのかもテスト
することができる。

また、要素の操作性能をテストすることも可能であり、例えば、clickなどの、クリックした際に反応を示すか(アニメーション?)どうかを
確認することができる。

have_contentについて

image.png

 have_content
 は基本的に、テキストに対して指定する時に使用する。

実践してわかったこと

image.png

テストのコードを細かく見ていったときに、実践して判ったことは
fill_inで指定するのはラベルのtext、id, name など属性がそれぞれ存在するなかで、選択するのはいづれかでよいということがわかった

投稿した内容のツイートの存在を確認するテストにおいては
コードの記述が、基本的にJavascriptと似ているという特徴がある。
例えば、JSでcontent_testといったようにclassを指定して、buildHTMLをおこなうように、
このテストコードでも該当のclassを指定してそこのclassにツイートが存在するかを確かめることができる。
→更にはback-ground-imageなどのようにURLを指定することで、画像のURL が存在するかどうかも確かめることが可能であるということもわかった。

これまでは正常系のテストについて確認したが、ここからは異常系のテストについてまとめていこうと思う。

ポイント1:beforeアクションの仕組み
ポイント2:have_link
ポイント3:all
ポイント4:find_link().click

 beforeアクションについて

  beforeアクションはテストをそれぞれ実行する前に働かせるものであるが
  

image.png

このように@tweet1,2と変数を作った時に、FactoryBotのなかにある:userの情報を取ってくることができるのは
Factoriesのtweets.rbでassociation :userの表記によって、userとtweetのアソシエーションが組まれているからである。

もし、アソシエーションがうまく組まれていなかったりして、Userの情報がちゃんと構成されていないとテストの結果は
うまくいかなくなってしまう。

 have_link について

image.png

例としてexpect(要素).have_linkの記述によって、要素の中に当てはまるリンクを確認することができる。

 all について

image.png

allによって存在する同じ名前のclassを全て取得することができる。


これはmoreクラスの一つ目のボタンを重ねた時に編集という文字があり、
edit_tweet_pathへととぶリンクがあるかどうかを確認している。

 find_link().click について

image.png

このfind_link().clickは
A要素に対してのみ使用可能である。

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

CircleCIでEC2デプロイ時にエラー

はじめに

個人アプリにてCircleCIを導入し、
EC2にデプロイしようとした所、いくつかエラーが発生したので、解決策を記載します。

環境

  • ruby 2.6.2
  • rails 5.2.4
  • EC2

config.yml

version: 2

jobs:
    # build ジョブ: CircleCI 上で Docker コンテナを作成してテストする
    build:
        docker:
            - image: alpine
        steps:
            - checkout
            - run:
                name: Echo Test
                command: echo "CircleCI Test"
    # deploy ジョブ: EC2 に SSH 接続して、デプロイを実行する
    deploy:
        machine:
            image: circleci/classic:edge
        steps:
            - checkout
            # CircleCI に登録した秘密鍵を呼び出す
            - add_ssh_keys:
            # CircleCI に登録した環境変数を使って SSH
            - run: ssh ${USER_NAME}@${HOST_NAME} 'cd /var/www/myapp && git pull origin master'

workflows:
    version: 2
    # build_and_deploy ジョブ: 一番最初に呼ばれるジョブ
    build_and_deploy:
        # build ジョブと deploy ジョブを呼び出す
        jobs:
            - build
            - deploy:
                requires:
                    # deploy ジョブより先に build ジョブを実行しろ!
                    - build
                # master ブランチに push された場合のみ deploy ジョブを実行する
                filters:
                    branches:
                        only: master

起こった問題と解決策

①ポートが開いてないことによるエラー

ssh: connect to host ************* port 22: Connection timed out

【解決策】
EC2のセキリティグループのインバウンドを下記のように編集する。
注)セキリティ上、中間サーバーを使用するほうが好ましい

ポート範囲 ソース   
22 マイIP  xxx.xxx〜

       ↓

ポート範囲 ソース   
22 カスタム 0.0.0.0/0

②秘密鍵が合わないことによるエラー

①EC2にて下記のコマンドを実行し、pem鍵を作成(他の鍵と競合する可能性がある為、circleci-keyなどの名前にする)

ssh-keygen -m pem

②EC2にて下記のコマンドを実行し、①で作成した公開鍵(鍵名.pub)をauthorized_keysにコピー

cat ~/.ssh/circleci-key.pub >> authorized_keys

③EC2にて下記のコマンドを実行し、①で作成した秘密鍵を表示

cat ~/.ssh/circleci-key

④表示された秘密鍵をCircleCIのSSH-Keyに設定
(このとき-----BEGIN RSA PRIVATE KEY-----と-----END RSA PRIVATE KEY-----まで含める)

 最後に

私の場合、これでエラーが解消されましたので、
是非ためしてみてください。

 参考

CircleCIの使い方

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