20201019のRubyに関する記事は17件です。

deviseの導入

Railsでdeviseの導入流れ

1. Gemをインストールしてサーバーを再起動

2. コマンドを利用してdeviseの設定ファイルを作成

3. コマンドを利用してUserモデルを作成

4. 未ログイン時とログイン時でボタンの表示を変える実装

5. コントローラーにリダイレクトを設定

deviseのgemインストール

Gemfile
# 中略
gem 'devise'
ターミナル
# サーバーを起動
% rails s

コマンドを実行して設定ファイルを作成

ターミナル
# deviseの設定ファイルを作成
% rails g devise:install

コマンドを実行してUserモデルを作成

ターミナル
# deviseコマンドでUserモデルを作成
% rails g devise user

マイグレーションを実行

ターミナル
# マイグレーションを実行
% rails db:migrate

ローカルサーバーを再起動

ターミナル
# ctrl + Cでローカルサーバーを終了

# 再度ローカルサーバーを起動
% rails s

リダイレクト処理を用意

app/controllers/tweets_controller.rb
class TweetsController < ApplicationController
  before_action :set_tweet, only: [:edit, :show]
  before_action :move_to_index, except: [:index, :show]

  def index
    @tweets = Tweet.all
  end

  def new
    @tweet = Tweet.new
  end

  def create
    Tweet.create(tweet_params)
  end

  def destroy
    tweet = Tweet.find(params[:id])
    tweet.destroy
  end

  def edit
  end

  def update
    tweet = Tweet.find(params[:id])
    tweet.update(tweet_params)
  end

  def show
  end

  private
  def tweet_params
    params.require(:tweet).permit(:name, :image, :text)
  end

  def set_tweet
    @tweet = Tweet.find(params[:id])
  end

  def move_to_index
    unless user_signed_in?
      redirect_to action: :index
    end
  end
end

コマンドを実行してdevise用のビューを作成

ターミナル
rails g devise:views

usersテーブルにnicknameカラムをstring型で追加

ターミナル
# ディレクトリがpictweetであることを確認
% pwd

# usersテーブルにnicknameカラムをstring型で追加するマイグレーションファイルを作成
% rails g migration AddNicknameToUsers nickname:string

# 作成したマイグレーションを実行
% rails db:migrate
ターミナル
# ctrl + Cでローカルサーバーを終了

# 再度ローカルサーバーを起動
% rails s

application_controller.rbを編集

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])
  end
end

以上です!

deviseには元々デフォルトでemailとpasswordは内部で動いてくれているのでカラムを追加しない場合はパラメーターに記述不要です!

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

地味に大切だった命名規則。もう二度と間違えない!

はじめに

 本日の学習で出会ったエラーが、今まででいちばん意外なところでのエラーだったので、忘れないために記録しておく。

命名規則

 クラス名はアッパーキャメルケースで記述する。

アッパーキャメルケース:先頭の単語と、単語の区切りの頭の文字を大文字にする。
キャメルケース:先頭は小文字で、単語の区切りの頭の文字は大文字にする。
スネークケース:単語と単語の区切りをアンダースコア(_)で繋げる。

クラス名→アッパーキャメルケース
変数名・メソッド名→スネークケース

最後に

 本日の学習では、処理の記述を何度見返しても、違いが見つからず、単語を繋げたクラス名をスネークケースで記述してしまい、クラスを読み取らないというエラーが出てしまった。
 ちまみに、キャメルはラクダ。大文字のところが、コブってこと。アンダースコアは蛇に見えるか?

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

【Ruby】Your Ruby version is 2.6.3, but your Gemfile specified 2.5.8

はじめに

Rubyを触っていたときにタイトルのエラーが出たので記事にしました。

エラーとの遭遇

作成途中だったアプリを触っていたときに、bundle install でエラーに遭遇。

$ bundle install
-> Ruby version is 2.6.3, but your Gemfile specified 2.5.8

エラー文から、RubyのバージョンとGemfileが指定してるバージョンが違うんだろうなーと検討がつく。

対応したこと

まず、Rubyのバージョンを確認してみる。

$ ruby -v
-> ruby 2.5.8p224 (2020-03-31 revision 67882) [x86_64-darwin19]

rbenvを使用しているので、そちらでも確認

$ rbenv versions
  system
  2.1.5
  2.5.1
* 2.5.8
  2.6.3
  2.7.1

見た感じは合ってるっぽい。

今使っているRubyのパスを参照したりできるgem environmentで確認してみよう。

$ gem environment
-> RubyGems Environment:
  - RUBYGEMS VERSION: 2.7.6.2
  - RUBY VERSION: 2.5.8 (2020-03-31 patchlevel 224) [x86_64-darwin19]
  - INSTALLATION DIRECTORY: /Users/username/.rbenv/gems/2.5.0
  - USER INSTALLATION DIRECTORY: /Users/username/.gem/ruby/2.5.0
  - RUBY EXECUTABLE: /Users/username/.rbenv/versions/2.5.8/bin/ruby
  - EXECUTABLE DIRECTORY: /Users/username/.rbenv/gems/2.5.0/bin
  - SPEC CACHE DIRECTORY: /Users/username/.gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: /Users/username/.rbenv/versions/2.5.8/etc
  - RUBYGEMS PLATFORMS:
    - ruby
    - x86_64-darwin-19
  - GEM PATHS:
     - /Users/username/.rbenv/gems/2.5.0
  - GEM CONFIGURATION:
  ...(続く)

うーん、間違ってなさそう...

解決した方法

bundle の配置場所を確認してみる

$ which bundle
-> /usr/local/bin/bundle

中身を見てみる

-> % cat /usr/local/bin/bundle 

#!/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby
#
# This file was generated by RubyGems.
#
# The application 'bundler' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require 'rubygems'

version = ">= 0.a"

str = ARGV.first
if str
  str = str.b[/\A_(.*)_\z/, 1]
  if str and Gem::Version.correct?(str)
    version = str
    ARGV.shift
  end
end

...(続く)

あ、/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/rubyを参照しているぞ...

$ which ruby
/Users/username/.rbenv/shims/ruby 

参照先を/Users/username/.rbenv/shims/rubyに変更。

無事bundle installが通りました!

参考記事

https://qiita.com/h5y1m141@github/items/74029cab9706971c8dbe

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

pluckメソッドとは

今回、pluckメソッドについて学習したため、アウトプットいたします。

pluckメソッドとは?
その使い方とは?

について記述いたします。

pluckメソッドとは?

pluckメソッドとはこう書かれています。
「引数に指定したカラムの値を配列で返すメソッド。」

同様の効果のあるメソッドとしてmapメソッドが上げられますが、返り値を配列として取得する場合は、pluckメソッドを使った方がシンプルで楽です。

では実際に使ってみましょう。

使い方

usersテーブルのnameカラムに"田中", "吉田", "鈴木", "高橋"の4人が入っていたとする。
そこで、userテーブルのnameカラムだけ取得したい場合、pluckメソッドは力を発揮する

User.pluck(:name)
#すると以下のような処理がされる
SELECT `users`.`name` FROM `users`
=> ["田中", "吉田", "鈴木", "高橋"] # 返り値

このようにテーブルやデータベースに登録された情報を配列としてまとめて取得したい場合にとても便利です。

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

Kinx ライブラリ - 自動組版(Tiny Tyesetting)

はじめに

「見た目は JavaScript、頭脳(中身)は Ruby、(安定感は AC/DC)」 でお届けしているスクリプト言語 Kinx。今回は Tiny Typesetting 最新情報です。これ の続きです。

ココんトコロ、こればかりやってました。はい。一先ず最初にやりたかったことはある程度できるようになりましたので、公開します。

ライブラリというより、単機能として使用できるよう KiTTy って名付けてあります(今時点では)。kxkitty.exe (Windows) と kxkitty (Linux) という実行コマンドも用意しています。

ひとまず、マニュアルをエッサホイサと作ったので、それを参照してみてください。マニュアル自体を KiTTy で作成しています(日本語と英語両方作るのは大変だった...)。ここでは日英両方載せておきます。英語はざざーっと仕上げることを優先したので、かなり自信ありません。

元のファイルはこれです。

これを KiTTy 処理すると以下のようになります。自信はないですが、英語版も載せておきましょう。

どうでしょう?

ちなみに処理速度は今のところ遅いといえば遅いのですが、私個人的にはまぁ我慢できます(私の子なので贔屓目だとは思います)。実行速度を向上できるだろう改善のアイデアはあるのですが、ちょっと時間的な余裕がないのでしばらくはこのままでしょう。あらかじめご容赦いただけるよう先に謝っておきたいと思います。すみません。

使っている技術情報などなど

サポート機能一覧

マニュアルにも載せていますが、KiTTy は組版機能として以下の機能をサポートしています。なお、カーニングは現在サポートしていません。詳しくはマニュアルを読んでみてもらえると嬉しい。

  • 基本組版機能
    • ハイフネーション・ジャスティフィケーション・行分割
    • ウィドウ/オーファン
    • マルチカラム
    • 箇条書き
    • 数式
    • イメージ
    • グラフ(チャート)
    • テーブル
    • フォント
    • 合字・特殊文字
    • プログラム・コード
    • タイトル・カバーページ・目次
    • 見出し
    • 相互参照
    • 引用
    • 脚注
  • 日本語用組版機能
    • 日本語禁則処理
    • 日本語ルビ
  • PDF 機能
    • 外部リンク
    • 相互参照リンク
    • しおり

日本語組版機能も一部サポートしています。ルビも振れます。縦書きはサポートしていません。

主要な個別技術情報

せっかくの技術ブログなので、技術情報を少々。

Knuth-Plass Line Breaking Algorithm

LaTeX で使われている行分割のアルゴリズムです。ハイフネーション処理をした後、個別の Box 単位に Glue と Penalty を挿入し、Penalty が最小になる位置で改行するようにコントロールします。

技術的な詳細は、日本語だと以下が参考になるでしょう。

また、実装は、以下(BSD-2-Clause License)を修正して利用させていただきました。見た目は JavaScript の本領発揮です。

数式

LaTeX を目指す(目指してはいませんが)なら数式が必要です。そこで、JavaScript には KaTeX とか MathJax とかあるので、ここでも 見た目は JavaScript の特長を生かして進めようと思いましたが、細部(フォントとか CSS が必要とか)が違い過ぎて 無理でした。なので、ここでは Duktape + KaTeX で実装しました。が、しかし、レンダリングで躓き、結局最終的には Phantomjs ベースで画像化します。Duktape は必要だったのか、という気もしますが、Duktape は他でも使いようがあるかもしれないので、まぁこのままでいいかな、と実装はステイにしました(修正する時間もあまりなく)。

なお、今時点で Phantomjs を使うのは微妙、という声もちらほらググると出てきますが、動いているので良しとします。node.js とか Chrome とか使わずに単一コマンドでできるのでライブラリ内に閉じて良いと思ってますが、他の手段でも「そう(単一コマンドだけで閉じる感じに)できますよ」という情報があれば下さい。

Chart.js

Phantomjs を内蔵したので、色々できるのでは、と最初にチャレンジしたのがうまくいきました。文書内に自由にチャートをかけるのは非常に便利な気がします。というか便利ですよね。

ちなみに、気をよくして Mermaid.js を組み込もうとして失敗しています(UMLとか書けるといいなー)。そのうち再チャレンジするかもしれません。

その他

その他も紹介できそうなものは色々ありそうですが、時間的制約から本日はここまで。

インストール方法

インストール方法もマニュアルに載っていますが、紹介しておきます。元が Markdown なので、基本コピーな感じでいけますね(ちょっと修正が必要ですが)。

インストールは以下の 2 ステップを実施します。

  1. Kinx のインストール
  2. KiTTy 追加モジュールのインストール

ちなみに、Kinx コアモジュールは 8.5~9M 程度ですが、KiTTy 追加モジュールは(フォントとかも含まれていて)74M くらいあります。ここ(リリースページ) の Assets を見ると分かります。パッケージマネージャーを作るのは大変なので、全部コアに入れない方法を模索しました。パッケージマネージャー相当は今後用意したいですが、今はこの方法で。

Linux

Linux では以下のようにモジュールをダウンロードします。
v0.15.2 は KiTTy ライブラリが正式に追加されたバージョンです。
最新バージョンを使用する場合は書き換えてください。
ワークディレクトリを作成し、移動してください。

$ mkdir temp
$ cd temp

最初に kinx モジュールをダウンロードし展開し、
次に KiTTy パッケージをダウンロードして展開します。

$ curl -L \
    https://github.com/Kray-G/kinx/releases/download/v0.15.2/package_linux-amd64.tar.gz \
    --output package_linux-amd64.tar.gz
$ tar -xvf package_linux-amd64.tar.gz
$ curl -L \
    https://github.com/Kray-G/kinx/releases/download/v0.15.2/package_kitty.zip \
    --output package_kitty.zip
$ unzip package_kitty.zip

展開するとバージョン番号のフォルダができますので、
移動して install.sh コマンドを実行します。

$ cd v0.15.2
$ sudo ./install.sh

これでインストールは完了です。
実行フィルの位置1を確認してみましょう。

$ which kxkitty
/usr/bin/kxkitty

Windows

Windows では Release ページ から最新のパッケージ(以下 2 点)をダウンロードします。

  • package_win64.zip
  • package_kitty.zip

それぞれ展開し、package_kitty.zip の中身を lib フォルダ配下にコピーします2

その際、lib 配下に fonts、phantomjs フォルダが配置されるようにしてください。
圧縮ファイル内のファイル構成が必ずしもそうなっていない可能性があります。

ビルド

通常、ビルドから実施する必要はありません。
既にビルドされた実行モジュールが提供されており、手順にしたがってインストールを実施することで本システムを利用することができます。
あえてビルドから実行したい、といった場合は以下の手順によってビルドを実施できます。

Linux

Github よりクローンし、make します。

$ git clone https://github.com/Kray-G/kinx.git
$ cd kinx
$ make

インストールします。

$ git clone https://github.com/Kray-G/kinx.git
$ cd kinx
$ sudo make install
$ sudo make kitty-install

Windows

Github よりクローンし、make します。

$ git clone https://github.com/Kray-G/kinx.git
$ cd kinx
$ make.cmd

特に現在はインストール用のコマンドを用意していませんが、
ビルドした環境で使用可能です。
ビルドした環境でご使用ください。

hello, world

次の文書を作成し、helloworld.md ファイルとして保存します。

% Hello Kinx Tiny Typesetting
% Your name
% October 7, 2020

<param style="ArticleA4"/>

# Greeting
hello, world

以下のように kxkitty コマンドを実行することで、helloworld.pdf が作成されます。

$ kxkitty helloworld.md

なお、現在はサンプル程度の記載が必要ですが、
もう少しシンプルなサンプルを提示できるよう改善する予定です。

おわりに

多少なりとも「まぁまぁいいんじゃない?」と思いましたら、GitHub スターくれると嬉しいです(いつも同じこと言ってますが)。また、これまで色々と応援してくださっている方々にもあらためて感謝します。ちょっと更新が遅くなり気味な近頃ですが、ちょっとずつ進めていきたいと思いますので、GitHub 上で Issue なり Pull Request なりいただけると大変有難く思います。

では、今後ともよろしくお願いいたします。


  1. マニュアルだと kinx の場所を探してますね。こちらであるべきでしょう。そのうち直します。 

  2. 現時点でインストーラは用意できていませんが、将来的に Windows インストーラを用意する予定です。 

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

【Ruby on Rails】RSpecでのモデルテスト

開発環境

ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina

前提

【Ruby on Rails】RSpec導入まで
こちらが出来ている前提で進めます。

modelのテスト準備

・バリデーションの設定

今回はタイトルカラムがあるかどうかと文字数のテストします。

app/models/post.rb
class Post < ApplicationRecord
  belongs_to :user
  validates :title, presence: true, length: {maximum: 20}
end

・ファイルの作成


spec配下にmodelsフォルダとfactoriesフォルダを作成し、
テストしたいモデルのファイルも作成します。
今回はpostモデルをテストします。
またユーザーがログインしている状態でしか投稿できないようにするために、
useモデルも作成します。
ファイル構成は下記の状態です。
 
spec/models/post_spec.rb
 →テストしたい内容を記述します

spec/factories/post.rb
spec/factories/user.rb
 →ダミーデータを作成します


FactoryBotを使えるようにします。
使用するとuser = create(:user) のようにDB登録やモデルのビルドができるため便利です。
spec配下にsupportフォルダとfactory_bot.rbファイルを作成し、下記のように記述します。

spec/support/factory_bot.rb
RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end

その後、下記を追加します。

spec/rails_helper.rb
# This file is copied to spec/ when you run 'rails generate rspec:install'
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
require 'support/factory_bot' # <ーーー 追加

...

実際のコード

まずはダミーデータを作成します。

spec/factories/user.rb
FactoryBot.define do
  factory :user do
    email { Faker::Internet.email }
    phone_number { 12345678909 }
    password { 'password' }
    password_confirmation { 'password' }
  end
end
spec/factories/post.rb
FactoryBot.define do
  factory :post do
    body { Faker::Lorem.characters(number:20) }
    user
  end
end

次にテストコードを記述します。

spec/models/post_spec.rb
require 'rails_helper'

RSpec.describe 'Postモデルのテスト', type: :model do
  describe 'バリデーションのテスト' do
    # factoriesで作成したダミーデータを使用します。
    let(:user) { FactoryBot.create(:user) }
    let!(:post) { build(:post, user_id: user.id) }

    # test_postを作成し、空欄での登録ができるか確認します。
    subject { test_post.valid? }
    let(:test_post) { post }


    context 'titleカラム' do
      it '空欄でないこと' do
        test_post.title = ''
        is_expected.to eq false;
      end
      it '20文字以下であること' do
        post.title = Faker::Lorem.characters(number:21)
        expect(post.valid?).to eq false;
      end
    end
  end
  describe 'アソシエーションのテスト' do
    context 'customerモデルとの関係' do
      it 'N:1となっている' do
        expect(Post.reflect_on_association(:user).macro).to eq :belongs_to
      end
    end

    # has_manyの関係性で記述するのもありです。
    # context 'PostCommentモデルとの関係' do
      # it '1:Nとなっている' do
        # expect(Post.reflect_on_association(:post_comments).macro).to eq :has_many
      # end
    # end
  end
end

その後、ターミナルで下記を実行してください。

$ rspec spec/models

テストを通過すると

Finished in 0.52408 seconds (files took 2.11 seconds to load)
3 examples, 0 failures

このように表示されるためテスト内容が正しいことを表しています。

逆にテストを通過しない場合、このような形でどこでエラーが起きているかわかるので、
テストコードが間違っているのか、バリデーションが間違っているかなどがわかるようになります。

Failures:

  1) Postモデルのテスト バリデーションのテスト titleカラム 20文字以下であること
     Failure/Error: let!(:post) { build(:post) }

     NoMethodError:
       undefined method `build' for #<RSpec::ExampleGroups::Post::Nested::Title:0x000000000619e938>
     # ./spec/models/post_spec.rb:9:in `block (3 levels) in <top (required)>'

  2) Postモデルのテスト バリデーションのテスト titleカラム 空欄でないこと
     Failure/Error: let!(:post) { build(:post) }

     NoMethodError:
       undefined method `build' for #<RSpec::ExampleGroups::Post::Nested::Title:0x0000000007491518>
     # ./spec/models/post_spec.rb:9:in `block (3 levels) in <top (required)>'
Finished in 0.07992 seconds (files took 2.41 seconds to load)
2 examples, 2 failures

Failed examples:

rspec ./spec/models/post_spec.rb:11 # Postモデルのテスト バリデーションのテスト titleカラム 20文字以下であること
rspec ./spec/models/post_spec.rb:15 # Postモデルのテスト バリデーションのテスト titleカラム 空欄でないこと

また下部にあるrspec ./spec/models/post_spec.rb:11を使い、
下記のように個別にテスト内容を確認することも出来ます。

ターミナル
$ rspec spec/models/post_spec.rb:11

まとめ

今回は
1,空白での登録を防ぐバリデーション presence: true
2,文字数制限のバリデーション length: {maximum: 20}
3,リレーションの関係性の確認 belongs_to :user

上記をテストしましたが、この他にも色々テスト方法があるため、
興味のある方は調べてみてください。

またtwitterではQiitaにはアップしていない技術や考え方もアップしていますので、
よければフォローして頂けると嬉しいです。
詳しくはこちら https://twitter.com/japwork

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

Rails 新規アプリケーション作成の基本

新規アプリケーション作成の基本

今回はruby on railsで新規アプリケーションを立ち上げる際の基本をまとめておこうと思います。

前提としてrailsのバージョンは6.0.0でデータベースはMySQLというツールを用います。

新規アプリの準備

# ディレクトリの移動
% cd ~/アプリを作成したいディレクトリ名

# 新規アプリを作成(chochikuというアプリ名)、-dオプションでMySQLの使用を明示して作成
% rails _6.0.0_ new chochiku -d mysql

# 作成したchochikuのディレクトリに移動
% cd chochiku

以上のコードをターミナルに打つことで新規アプリケーションが立ち上がります。

データベースの作成

コマンドを利用してアプリのデータベースを作成しますが、その前にデータベースに関する設定を少しする必要があります。

データベースに関する設定はdatabase.ymlに記述します。

database.ymlのdefaultの下のencoding: utf8mb4という記述を
encoding: utf8に変更します

そして以下のコマンドを実行すればデータベースの作成を行います
※必ず自分の作るアプリのディレクトリでコマンドを実行してください!

% rails db:create

モデルの作成

railsのアプリケーションにはデータベースとやりとりをするモデルが必要になります。

# Expenseモデルを作成
% rails g model expense

テーブルの作成

マイグレーションファイルの編集

上記のモデルを作成した時、同時にマイグレーションファイルがdb/migrateというディレクトリに生成されます。
このマイグレーションファイルを編集してテーブルに保存する情報を決定します。

class CreateExpenses < ActiveRecord::Migration[6.0]
  def change
    create_table :expenses do |t|
      t.string :name
      t.integer :shuppi
      t.timestamps
    end
  end
end

例えばt.string :nameというコードはstring型でnameというカラムをテーブルに追加しているということです。

マイグレーションの実行

マイグレーションファイルを編集しただけではテーブルについて変更を加えたことにはなりません。そこでマイグレーションの実行をする必要があります。
以下のコマンドを実行することでマイグレーションを実行することができます。

% rails db:migrate

まとめ

以上でアプリの一つのモデルとそのモデルに紐づくテーブルを作ることができました。
実際にはこれからこのモデルに紐づくコントローラーやルーティング、ビューを作っていくことでアプリを作ることになります。
新規アプリ作成の基本としてはとりあえずここまでですm

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

保存された状態で同じ画面に遷移したい

【概要】

1.結論

2.どのようにコーディングしたか

3.開発環境

補足

1.結論

redirect_to "/XXXX/#{@@@@@.XXXX.id}"とコーディングする!


2.どのようにコーディングしたか

  def create
    @comment = Comment.new(comment_params)
    if @comment.valid?
      @comment.save
      redirect_to "/reports/#{@comment.report.id}"
    end

reportという投稿に、さらにその投稿にコメントを付け加えることができるアプリです。その際に、reportの投稿にコメントを付け加え終わった後にrootで最初の画面に戻っても良いと思います。しかし、ちゃんとコメントが残っているかの確認も含めてコメントを投稿する画面に戻したいのでこのようなコーディングになりました。

3.開発環境

Mac catalina 10.15.4
Vscode
Ruby 2.6.5
Rails 6.0.3.3

補足

redirect_to report_path(id: current_user)
#devise gemを使用。

としても一応エラーは起きませんが、current_userなので、1番目に登録したのであれば/reports/1という風になってしまい、2番目に投稿したreportとは違う1番目のreportに戻されるので注意が必要です。

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

三項演算子について

アプリケーションを作成するにあたり三項演算子について学んだので備忘録として残しておきます。

三項演算子とは

「if ~ else ~」を一文で書きたいときに使う演算子

例) (結果は同じ)

①if〜elseで記述
if hoge == 3
  "true"
else
  "false"
end
②三項演算子を利用
hoge == 3 ? 'true' : 'false'

条件1 ? 条件1が正しいとき : 条件1が正しくないときで使用する

便利そうではあるが式が複雑になるとわかりづらくなりそうなため、うまく使い分けることが大切ではないだろうか。
Rubyのリファレンスには条件演算子で載っておりrailsドキュメントには三項演算子で載っている。
調べてみたところ違いはなさそう。

参考記事

https://wa3.i-3-i.info/word11653.html

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

[プログラミング大全] §1はじめてのプログラミング

目的

 「プログラミングを学ぼう!!」と意気込んだものの、
プログラミングって難しそうだし、英語も読めないし、PC操作自体苦手だし、
昔に挫折したし、というあなたに向けて、
この記事を読み・PCを動かすだけで「なんだ!プログラミングって面白いじゃん!」
って思ってもらうのが目的です。

プログラミング大全というタイトルで連載化していきたいと考えています。

開発環境

  • Mac:macOS10.15.7(メインPC)
  • ブラウザ:Google Chrome
  • テキストエディタ:VSCode(Visual Studio Code)

プログラミングとは?

 コンピューターが読むことのできるデータをプログラム
プログラムを作成、記述していく作業のことをプログラミングと呼ぶ。

プログラムを行うときに使用する言語をプログラミング言語と呼ぶ。

プログラミング言語で書かれ、
人間が理解できる状態のテキストやファイルをソースコードと呼ぶ。
*単に「ソース」、「コード」と呼ぶこともある。

Rubyとは何か?

 Rubyとはプログラミング言語の1つです。
Webアプリケーション作成において使われることが多いです。
Ruby公式サイト

 具体的な開発例としては
クックパッド、食べログ、Twitter、huluなどが挙げられます。

 Rubyの特徴としては、小さなプログラムから大きなアプリまで手軽に作れます。
また、文法が直感的にわかりやすく、日本語の参考記事が多いことから、
「プログラミングってどの言語から学習すればいいの?」
と聞かれたら「Ruby」と答える方がも多いです。

プログラミングの流れ

1. プログラムをテキストエディタに記述して保存する。
2. PCに、記述したプログラムを実行する様に命令を出す。

 ここで重要なのはプログラムは保存して、実行しなければいけないことです。
実行しなければ、ただのメモと同じです。書いたものをPCに読み込ませることで
初めてプログラムが実行されます。

ではでは、プログラミングを学んでいく前にPC以外に必要なものを準備していきましょう!

プログラミングに必要なものの準備

ブラウザとテキストエディタを準備しましょう!

Google Chromeのインストール

こちらの公式サイトからインストール。
後々のためにGoogleアカウントを作成することをおすすめします!

VSCode(Visual Studio Code)のインストール

こちらの公式サイトからインストール。

 この2つのソフトに関しては使用頻度が高いのでインストールが完了したら、
自分が使いやすい位置に配置しておくことをお勧めします。

以上です!
今回は座学がメインでしたが、
次回からは、プログラミングに向けて具体的にPCを動かしていきたいと思います。

備考

───────────────────────────────
■著者おすすめの本
───────────────────────────────

「プロになるためのWeb技術入門」

「転職の思考法」

「ハイパワーマーケティング」

「嫌われる勇気」

「アウトプット大全」

───────────────────────────────
■著者おすすめの映画
───────────────────────────────

「マイ・インターン」

「シン・ゴジラ」

「ドラゴンボール超 ブロリー」

「School of Roc」

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

pryでparamsの中身を確認する

背景

記事詳細を表示する際に、ユーザー名を表示したかったが、どこに格納されているのかわからず、paramsの中身を調べることにした。その過程のログを残しておく。

やり方

gemをインストール (gem 'pry-rails')

bundle install

調べたい該当箇所に、binding.pryを入力。

rails s

該当箇所をブラウザでぽちぽち。ターミナルに、入力した箇所で止まったログが表示される。

そして、[1] pry(#)>
と表示されるから、そこに知りたい文字列を入力。

qiita.controller.rb
    12: def show
    13:   #一つの投稿のみを取得したい。
    14:   @post = Post.find(params[:id])
 => 15:   binding.pry
    16: end

試しに上から順に、
id
params[:id]
@post.content
@post.user
と入力してみた!

[1] pry(#<PostsController>)> id
NameError: undefined local variable or method `id' for #<PostsController:0x00007f9f26ea4828>
from (pry):1:in `show'

[2] pry(#<PostsController>)> params[:id]
=> "1"

[3] pry(#<PostsController>)> @post.content
=> "Temporibus vel ratione aperiam alias aut libero reiciendis voluptatem quo autem rerum doloribus adipisci a voluptas modi illo qui ipsum aliquid voluptatum nventore at esse maiores ut omnis accusantium animi ducimus qui autem architecto excepturi itaque ex minus facere soluta inventore molestias id unde vero sunt aliquam quia dolorum quae placeat deserunt aspernatur qui suscipit quod dolorem maxime nulla id molestiae incidunt aut beatae aut voluptate aliquid dicta velit sit sint eum possimus nihil non voluptatem provident enim assumenda consequatur fugiat."

[4] pry(#<PostsController>)> @post.user
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ↳ (pry):4:in `show'
=> #<User:0x00007f9f26c77b68
 id: 1,
 name: "swifty_kazu",
 email: "hogehogehoge",
 created_at: Fri, 16 Oct 2020 02:53:43 UTC +00:00,
 updated_at: Fri, 16 Oct 2020 02:53:43 UTC +00:00,
 password_digest: [FILTERED],
 admin: true>

[5] pry(#<PostsController>)> @post.user.name
=> "swifty_kazu"

[6] pry(#<PostsController>)> 

exit!で抜け出せる

参考記事
https://qiita.com/tomoharutt/items/6b12af3dc5eb8dfb9801
https://pikawaka.com/rails/params#params%E3%81%AE%E4%B8%AD%E8%BA%AB%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%97%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86
https://qiita.com/k0kubun/items/b118e9ccaef8707c4d9f

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

Gem ~ active_model_serializers ~

公式

https://github.com/rails-api/active_model_serializers/tree/v0.10.6/docs

Serializer の作成

be rails g serializer api::v1::articles_preview_serializer

作成されたファイル

app/serializers/api/v1/articles_preview_serializers.rb

class Api::V1::ArticlesPreviewSerializer < ActiveModel::Serializer
  # 出力したい値を指定
  attributes :id, :title, :updated_at
end

id, title, updated_at を出力するよう指定。

コントローラ

app/controllers/api/v1/articles_controllers.rb

module Api::V1
  class ArticlesController < BaseApiController
    def index
      articles = Article.all.order(updated_at: "DESC")
            # レスポンスの値が複数の場合、 each_serializer を使用する。
      render json: articles, each_serializer: Api::V1::ArticlesPreviewSerializer
    end
  end
end

serializer と同じ階層構造にすること。

作成した article を updated_at 順に昇順にするよう指定。

同階層に base_api_controllers.rb

class Api::V1::BaseApiController < ApplicationController
end

Request spec

とりあえずダミーデータを作成して参照する。

spec/requests/api/v1/article_request_spec.rb

require 'rails_helper'

RSpec.describe "Api::V1::Articles", type: :request do
  describe " GET /api/v1/article " do
    subject { get(api_v1_articles_path) }

    before { create(:article, updated_at: 3.days.ago ) }
    before { create(:article) }
    before { create(:article, updated_at: 1.days.ago ) }
    it "記事の一覧が取得できる" do
      subject
    end
  end
end

Request spec についてはまた後日。

実行結果

[1] pry(#<RSpec::ExampleGroups::ApiV1Articles::GETApiV1Article>)> res = JSON.parse(response.body)
=> [{"id"=>56, "title"=>"Consequuntur quia corporis perspiciatis.", "updated_at"=>"2020-10-17T22:19:32.120Z"},
 {"id"=>57, "title"=>"Molestiae tempore recusandae qui.", "updated_at"=>"2020-10-16T22:19:32.122Z"},
 {"id"=>55, "title"=>"Consectetur nam odio voluptatibus.", "updated_at"=>"2020-10-14T22:19:31.192Z"}]

UserSerializer の追加

class Api::V1::UserSerializer < ActiveModel::Serializer
  # 出力したい値を指定
  attributes :id, :name, :email
end

ArticlesPreviewSerializer の修正

class Api::V1::ArticlesPreviewSerializer < ActiveModel::Serializer
  # 出力したい値を指定
  attributes :id, :title, :updated_at
  belongs_to :user, serializer: Api::V1::UserSerializer
end

実行結果

[1] pry(#<RSpec::ExampleGroups::ApiV1Articles::GETApiV1Article>)> res = JSON.parse(response.body)
=> [{"id"=>59,
  "title"=>"Esse facere cum rerum.",
  "updated_at"=>"2020-10-19T00:06:27.375Z",
  "user"=>{"id"=>69, "name"=>"Eduardo Kohler Haley", "email"=>"2_janella@renner-dach.org"}},
 {"id"=>60,
  "title"=>"Cumque aut repudiandae numquam.",
  "updated_at"=>"2020-10-18T00:06:27.377Z",
  "user"=>{"id"=>70, "name"=>"Collen Stark Brakus", "email"=>"3_hung@wintheiser.org"}},
 {"id"=>58,
  "title"=>"Corporis molestiae dolor odit.",
  "updated_at"=>"2020-10-16T00:06:26.556Z",
  "user"=>{"id"=>68, "name"=>"Fr. Pauline Sporer Greenfelder", "email"=>"1_wendy@goldner.net"}}]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CircleCIマン が GitHub Actions を導入するまで

普段は CircleCI でCI/CDを構築していた自分が何もわからない状態から GitHub Actions をどうやって導入したかを紹介しようと思います

自作のRubyのコマンドラインツールにCIを導入した時の話になります

自作のRubyのコマンドラインツールについて

qiita_command という Qiitaのトレンド情報(Daily, Weekly, Monthly)をコマンドラインで簡単に見れるツールです

sample

GitHub Actionsの初回導入

とりあえず簡素な状態でGitHub Actionsが動く状態まで持っていきます

テンプレートの選択

まず始めに Actions をクリックし RubySet up this workflow をクリックします

リポジトリの内容にあったWorkflowsテンプレートを表示してくれるので良さそうなものを選択し導入します

00_get_started_with_github_actions

Workflowsのファイルをリポジトリに追加

当たり前だがCircleCIとymlファイルの中身が違う
見てもよくわからない……

とりあえず、 RSpecが実行される ように Run tests の部分を変更する

変更前

    - name: Run tests
      run: bundle exec rake

変更後

    - name: Run tests
      run: bundle exec rspec

リポジトリに .github/workflows 配下にGitHub Actionsのファイルが出来上がることがわかります

00_edit_new_file

最後に Start commit をクリックして Commit new file をクリックしてリポジトリにコミットします

01_first_commit

実行結果を確認する

再度、 Actions をクリックし Workflows の一覧から先程作成したWorkflowsのコミットの Create ruby.yml をクリックします

00_created_workflows

左側の test をクリックし詳細を確認します

01_before_click_test

CIが実行中の場合です

02_click_test

CIが完了すると以下のような画面になります

03_test_complted

以上で簡単に RSpec を実行するだけの CI を実装することができました

workflows ファイルの中身を確認してみる

name、jobs について

name が上に表示され、 jobs の内容が name 配下に表示されます

jobs は複数追加することができます

00_workflows_name_check

on について

GitHub Actions が実行されるトリガーを設定することができます(いろいろなイベントに対して トリガー を実行できる)

下の例だと main ブランチでpush、pull request が行われた時に実行されるように設定されています

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

CircleCIでもブランチによるCIの制御を行うことができるが push や pull request で制御を行うことができない
CircleCIだと以下のようになる

workflows:
  build-deploy:
    jobs:
      - build_server_pdfs:
          filters:
            branches:
              only: main

01_workflows_on

runs-on について

ここで実行する環境を指定します

ubuntu の最新バージョンになります

runs-on: ubuntu-latest

CircleCIで言うところの下記のような記述の一部と同じになります

GithubAcitonsではOS寄りな環境設定になりますが CircleCI では言語に寄っていることが多い気がします
Docker Image の circleci/ruby:2.6.0 が何で作られているかによってOSが決まります

executors:
  base:
    docker:
      - image: circleci/ruby:2.6.0

02_workflows_runs-on

uses について

uses を使用することにより、再利用可能なコードを宣言することができる

with を使用して設定を追加することができる

  • actions/checkout@v2はリポジトリをチェックアウトしてくれる
  • ruby/setup-rubyはビルド済みのRubyをダウンロードしPATHに追加して Ruby を使えるようにしてくれる
steps:
- uses: actions/checkout@v2
- name: Set up Ruby
  uses: ruby/setup-ruby@ec106b438a1ff6ff109590de34ddc62c540232e0
  with:
    ruby-version: 2.6

CircleCI で言うところの CircleCI Orbs に近い気がします

orbs:
  slack: circleci/slack@3.4.2



workflows:
  version: 2.1
  main:
    jobs:
      - slack/approval-notification:
          message: ':circleci-pass: Slackへメッセージを送付します'

03_workflows_uses

run について

これは CircleCI と同じでコマンドを実行できます

- name: Install dependencies
  run: bundle install
- name: Run tests
  run: bundle exec rspec

04_workflows_run

コマンドの実行履歴で name で設定した部分が GitHub Actions に表示されます

05_workflows_run_name

自分の思い通りにGitHub Actionsを設定する

とりあえずGitHub Actionsというものを雰囲気分かってもらえたと思います

最小構成で実装することができたが他のプロジェクトではどのように設定しているのだろうか……

先人の知恵をお借りする

BestGems.org という Ruby gems のダウンロードランキングを確認することができるサイトから総ダウンロード数TOP10のプロジェクトを参考にしてみたいと思います

00_bestgems

ランキング 名前 GitHub Actions使用有無
1 rspec-expectations
2 rspec-core
3 rspec-mocks
4 diff-lcs
5 rspec-support
6 rspec
7 bundler
8 multi_json
9 rack
10 rake

※ランキングは 2020年10月16日のものです

diff-lcsbundlerrackrake を参考にして作成していきたいと思います

ファイル構成を確認する

プロジェクトごとファイル構成を確認する

diff-lcs

ci.yml は複数のOS、複数のRubyのバージョンでのテストを実行しているようだ

diff-lcs
 └ .github
     └ workflows
         └ ci.yml

bundler

主にテストをOSごと実行する Workflow に Linter を実行する Workflow に分けているようだ

bundler
 └ .github
     └ workflows
         ├ jruby.yml
         ├ ubuntu-bundler3.yml
         ├ ubuntu-lint.yml
         ├ ubuntu.yml
         └ windows.yml

rack

development.yml は複数のOS、複数のRubyのバージョンでのテストを実行しているようだ

rack
 └ .github
     └ workflows
         └ development.yml

rake

主にテストをOSごと、複数のRubyバージョンでのテストを実行しているようだ

rake
 └ .github
     └ workflows
         ├ macos.yml
         ├ test.yml
         └ windows.yml

ファイルの中身を参考にする

ファイルの中身を確認し参考になりそうな部分を確認してみる

rake/.github/workflows/test.yml

下記のようにすると

runs-on: ${{ matrix.os }}
strategy:
  matrix:
    os: [ 'ubuntu-latest', 'macos-latest', 'windows-latest' ]
    ruby: [ 2.6, 2.5, 2.4, 2.3, 2.2, jruby, jruby-head, truffleruby, ruby-head ]



steps:
- uses: ruby/setup-ruby@v1
  with:
    ruby-version: ${{ matrix.ruby }}

OSとRubyのバージョンを配列で宣言して1つのファイルでCIを実行することができるようだ

name: ubuntu

on: [push, pull_request]

jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ 'ubuntu-latest', 'macos-latest', 'windows-latest' ]
        ruby: [ 2.6, 2.5, 2.4, 2.3, 2.2, jruby, jruby-head, truffleruby, ruby-head ]
        exclude:
          - os: windows-latest
            ruby: truffleruby
          - os: windows-latest
            ruby: jruby-head
          - os: windows-latest
            ruby: jruby
    steps:
    - uses: actions/checkout@v2
    - uses: ruby/setup-ruby@v1
      with:
        ruby-version: ${{ matrix.ruby }}
    - name: Install dependencies
      run: gem install minitest
    - name: Run test
      run: ruby -Ilib exe/rake

diff-lcs/.github/workflows/ci.yml

下記のようにすると

runs-on: ${{ matrix.os }}-latest

runs-onの指定の時 -latest で宣言するとOSの指定をOS名だけで宣言することができるらしい
つまりOS名とバージョンの指定を分離することができる

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby

name: CI

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  test:
    strategy:
      matrix:
        os:
          - ubuntu
          - macos
          - windows
        ruby:
          - 2.5
          - 2.6
          - 2.7
          - head
          - debug
          - mingw
          - mswin
          - jruby
          - jruby-head
          - truffleruby
          - truffleruby-head
        exclude:
          - os: macos
            ruby: mingw
          - os: macos
            ruby: mswin
          - os: ubuntu
            ruby: mingw
          - os: ubuntu
            ruby: mswin
          - os: windows
            ruby: debug
          - os: windows
            ruby: truffleruby
          - os: windows
            ruby: truffleruby-head
    runs-on: ${{ matrix.os }}-latest
    continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' || matrix.os == 'windows' }}
    steps:
      - uses: actions/checkout@v2
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ matrix.ruby }}
          bundler-cache: true
      - name: Install dependencies
        run: bundle install
      - name: Run tests
        run: bundle exec ruby -S rake

workflows のファイルを編集する

上記情報を元にファイルを編集していく

複数OS、複数Rubyバージョンで実行できるようにする

  • workflows 名を CI に変更
  • OSを ubuntu、macos で実行できるようにする
  • Rubyのバージョンを 2.7、2.6 で実行できるようにする
  • uses で使用している ruby/setup-ruby のバージョンを v1 にする
name: CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  ci:
    strategy:
      matrix:
        os: [ubuntu, macos]
        ruby: [2.7, 2.6]
    runs-on: ${{ matrix.os }}-latest
    steps:
      - uses: actions/checkout@v2
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ matrix.ruby }}
      - name: Install dependencies
        run: bundle install
      - name: Run tests
        run: bundle exec rspec

ブランチでの絞り込みをなくす

  • push と pull_request のイベント時に実行されるよう on 句を変更する
on: [push, pull_request] 


on句を上記の書き方に変更する
name: CI

on: [push, pull_request]

jobs:
  ci:
    strategy:
      matrix:
        os: [ubuntu, macos]
        ruby: [2.7, 2.6]
    runs-on: ${{ matrix.os }}-latest
    steps:
      - uses: actions/checkout@v2
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ matrix.ruby }}
      - name: Install dependencies
        run: bundle install
      - name: Run tests
        run: bundle exec rspec


静的解析ツールを実行する

  • RuboCopが実行されるようにする
- name: Run Rubocop
  run:  bundle exec rubocop


上記設定を追加する
name: CI

on: [push, pull_request]

jobs:
  ci:
    strategy:
      matrix:
        os: [ubuntu, macos]
        ruby: [2.7, 2.6]
    runs-on: ${{ matrix.os }}-latest
    steps:
      - uses: actions/checkout@v2
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ matrix.ruby }}
      - name: Install dependencies
        run: bundle install
      - name: Run Rubocop
        run:  bundle exec rubocop
      - name: Run tests
        run: bundle exec rspec


テストのカバレッジ結果を見れるようにする

CircleCIだと store_artifacts を使用するとアーティファクトのアップロードができるようになります

同じことをGitHub Actionsでもできるようにします

公式のドキュメントの以下の記事を参考にテストのカバレッジをアーティファクトとしてアップロードされるようにしようと思います

記事を参考に下記の設定を追加します

- name: Archive code coverage results
  uses: actions/upload-artifact@v2
  with:
    name: code-coverage-report
    path: coverage


設定追加後
name: CI

on: [push, pull_request]

jobs:
  ci:
    strategy:
      matrix:
        os: [ubuntu, macos]
        ruby: [2.7, 2.6]
    runs-on: ${{ matrix.os }}-latest
    steps:
      - uses: actions/checkout@v2
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ matrix.ruby }}
      - name: Install dependencies
        run: bundle install
      - name: Run Rubocop
        run:  bundle exec rubocop
      - name: Run tests
        run: bundle exec rspec
      - name: Archive code coverage results
        uses: actions/upload-artifact@v2
        with:
          name: code-coverage-report
          path: coverage


Slack通知を実装する

CircleCI の場合は Orb を使用することでSlack通知を行うことができるようになる

GitHub Actionsでは同じように uses を使用して行うことができるようだ
幾つかSlack通知が行えるものがあるようだが今回はドキュメントもしっかりとある action-slack を使用して実装する

ドキュメントを参考に以下を追加する

- name: Github Actions notify to Slack
  uses: 8398a7/action-slack@v3
  with:
    status: ${{ job.status }}
    fields: repo,message,commit,author,action,eventName,ref,workflow,job,took
    mention: 'here'
    if_mention: failure
  env:
    GITHUB_TOKEN: ${{ github.token }}
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
    MATRIX_CONTEXT: ${{ toJson(matrix) }}
  if: always()

 
このままでは以下の部分が設定されてないので読み取ることができない

secrets.SLACK_WEBHOOK_URL

以下の公式の記事を参考にSlackの WEBHOOK_URL をリポジトリに設定します
CircleCI の環境変数を設定することと同じことをしています

下記の画面みたいな表示になっていれば SLACK_WEBHOOK_URL 設定は大丈夫です

00_complete_slack_webhook_url


上記設定が完了したら設定を追加します
name: ci

on: [push, pull_request]

jobs:
  ci:
    strategy:
      matrix:
        os: [ubuntu, macos]
        ruby: [2.7, 2.6]
    runs-on: ${{ matrix.os }}-latest
    steps:
      - uses: actions/checkout@v2
      - name: set up ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ matrix.ruby }}
      - name: install dependencies
        run: bundle install
      - name: run rubocop
        run:  bundle exec rubocop
      - name: run tests
        run: bundle exec rspec
      - name: archive code coverage results
        uses: actions/upload-artifact@v2
        with:
          name: code-coverage-report
          path: coverage
      - name: github actions notify to slack
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          fields: repo,message,commit,author,action,eventname,ref,workflow,job,took
          mention: 'here'
          if_mention: failure
        env:
          github_token: ${{ github.token }}
          slack_webhook_url: ${{ secrets.slack_webhook_url }}
          matrix_context: ${{ tojson(matrix) }}
        if: always()


実際に実行する

上記で編集した workflows のファイルを push することで GitHub Actions が実行されるようになります

詳細を確認していく

OS、RubyのバージョンごとCIが実行されるようになっています

00_run_start 

完了すると Artifacts にテストのカバレッジ結果が zip で圧縮されてダウンロードできるようになっています

CircleCIと違って画面から結果を確認することはできません

01_complete_run 

また1つのCIが完了するごとにSlackに完了通知が飛びます

02_notify_slack 

これで一通りやりたかったことができるようになりました!

応用編:Gemの自動アップデート用のプルリクをGitHub Actionsで自動化する

応用編として、Gemの自動アップデート用のプルリクを自動で作成する workflows を作ろうと思います

SSH で GitHub Actions に入る

CIを作成していく段階で個人的に必須な SSH で接続する機能は CircleCI では当たり前だが GitHub Actions ではどうするのか……

公式では用意されていないようなので uses を使用して行うことができる

下記の記事を参考にするとよい

スケジュールで実行するにはどうしたよいのか?

CircleCI だとトリガーを使用することでスケジュールされたCIを実行することができる

GitHub Actions では on.schedule を使用することで実現できそうです

CircleCI でも GitHub Actions のどちらも cron 形式でスケジュールを設定することができます
crontab guru のサイトを参考にしてスケジュールを設定するとよいでしょう

こんな感じで設定する

on:
  schedule:
    # * はYAMLに置ける特殊文字なので、この文字列は引用符で囲まなければならない
    - cron:  '*/15 * * * *'

schedule の詳しい仕様については公式のドキュメントを参考にすること

CircleCI と同じで GitHub Actions も cron は UTC で設定する必要があります

手順を考える

以下の手順をCIで実行することができれば実現できそうである

  • ① Gitの設定を行う(メールアドレス、ユーザー名)
  • ② Gem Update 用のブランチを作成する
  • ③ bundle update を行う
  • ④ commit して push する
  • ⑤ プルリクエストを自動で作成する
  • ⑥ Slackに完了通知を行う

実装する

上記で考えた手順を元に実際に実装していく

手順以外の実装

毎月の1日の9時に実行されるようにする

cron 式で設定した以外は先程、作成したものとほぼ同じである


設定内容
name: GemUpdate

on:
  schedule:
    - cron: '0 0 1 * *'

jobs:
  create-gem-update:
    strategy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: 2.7
      - name: Install dependencies
        run: bundle install


① Gitの設定を行う(メールアドレス、ユーザー名)

git checkout ができているので git はおそらくインストールされている前提ですすめる

インストールされているかなど調査する時は直接 ssh で接続して確認すると良い

複数行の時はCircleCIと同じく | を使用するようだ

- name: Settings Git
  run: |
    git config --global user.email ${{ secrets.MAIL_ADDRESS }}
    git config --global user.name "dodonki1223"

secrets.MAIL_ADDRESS こちらの設定は SLACK_WEBHOOK_URL と同じように設定します

この場合はメールアドレス直打ちでもいいような気がする

② Gem Update 用のブランチを作成する

ブランチを名前を付けて切り替えるコマンドです

gem_update_20201001 みたいな形がブランチ名になります

git checkout -b "gem_update_`date +%Y%m%d`"

③ bundle update を行う

前の段階で bundle install を行っているので update を行うだけです

bundle update

④ commit して push する

ファイルをコミットして先程作成したブランチに push します

git add .
git commit -m ':wrench: Gem Update'
git push origin "gem_update_`date +%Y%m%d`"

⑤ プルリクエストを自動で作成する

hubコマンドを使用してプルリクエストを作成する
最近、GitHub CLI がリリースされたので hubコマンドの代わりに GitHub CLI を使用するでもよいかもしれません

hub pull-request -b master -m "? Gem Update `date +%Y-%m-%d`"

②〜⑤を組み立てる

基本的には②〜⑤をそのまま繋げるだけで大丈夫なのですが下記の記述が追加で必要です

env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

上記記述に関しては hubコマンドのリポジトリに Readme に GitHub Actions で使用する時のサンプル例に書かれている例になります

- name: Create gem update pull request
  run: |
    git checkout -b "gem_update_`date +%Y%m%d`"
    bundle update
    git add .
    git commit -m ':wrench: Gem Update'
    git push origin "gem_update_`date +%Y%m%d`"
    hub pull-request -b master -m "? Gem Update `date +%Y-%m-%d`"
  env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

コマンドを組み上げる時は基本的には実際に ssh でログインして実際の環境で使用できるか確認しながらすすめるとよいです

コマンドのインストールが必要かどうかなども ssh でログインしながら確かめると良いです

⑥ Slackに完了通知を行う

こちらは先程、作成したもので既に行っているので特に説明はしません

- name: Github Actions notify to Slack
  uses: 8398a7/action-slack@v3
  with:
    status: ${{ job.status }}
    fields: repo,message,commit,author,action,eventName,ref,workflow,job,took
    mention: 'here'
    if_mention: failure
  env:
    GITHUB_TOKEN: ${{ github.token }}
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
  if: always()

完成品

実際に作成したもので最終形は以下になります


完成品
name: GemUpdate

on:
  schedule:
    - cron: '0 0 1 * *'

jobs:
  create-gem-update:
    strategy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: 2.7
      - name: Install dependencies
        run: bundle install
      - name: Settings Git
        run: |
          git config --global user.email ${{ secrets.MAIL_ADDRESS }}
          git config --global user.name "dodonki1223"
      - name: Create gem update pull request
        run: |
          git checkout -b "gem_update_`date +%Y%m%d`"
          bundle update
          git add .
          git commit -m ':wrench: Gem Update'
          git push origin "gem_update_`date +%Y%m%d`"
          hub pull-request -b master -m "? Gem Update `date +%Y-%m-%d`"
        env:
            GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Github Actions notify to Slack
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          fields: repo,message,commit,author,action,eventName,ref,workflow,job,took
          mention: 'here'
          if_mention: failure
        env:
          GITHUB_TOKEN: ${{ github.token }}
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
        if: always()


注意事項

on.schedule は下記の時だけ実行されます

デフォルトまたはベースブランチの直近のコミットで実行されます

これに気づかないといくらやってもスケジュールが実行されずハマることになります……自分は実行されずにすごく困ったらこれが原因でした

CircleCIとGitHub Actions の違うところ

自分が感じた CircleCI と GitHub Actions の違いをまとめようと思います

GitHub Actionsは遅い時がある

GitHub Actionsを使っていて気になったのだがなぜかすごく遅い時がある
CircleCIだとだいたい終了時間が同じ感覚を受けるがGitHub Actionsはやたらと遅い時がある

使用されるサーバーのスペックガチャにより早かったり、遅かったりするのかも知れない……

いろいろなトリガーが用意されている

CircleCI と違っていろいろな webhookイベントをトリガーに実行できるようだ
詳しくはドキュメントを参考にすると良い

ファイルの構成がスッキリする

CircleCIと違ってファイルの分割ができるため、行数を少なくすることができる

最後に

ずっとGitHub Actionsが難しそうで逃げていましたが実際にやってみるとすぐに実装することができました

先人の知恵をお借りしたことにより自分の中で思ったよりも早く理解することができたのだと思います

これからもGitHub Actions を使っていきましょう!!

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

消し損ねたマイグレーションファイルを完全に消す

謎のマイグレーションファイルがあって気持ち悪いので消し方を調べてスッキリしたことを書いていこうと思います。

現在のマイグレーションファイルの状況

rails db:migrate:status

マイグレーションファイルを確かに消したはずなのに

20200929181946.png

こんな感じでNO FILEが残ってる。

NO FILEはマイグレーションファイルは消したはずなのにコンピューター上に残ってしまっているということです。気持ち悪いので消します。

rails db:rollback
  • これでstatusの部分がupからdownになります。(編集できるということ)
  • この空のファイルを名前をつけて復活させる

touchコマンド

touch db/migrate/20200929050736_hoge.rb

aa.png
これによってhogeというマイグレーションファイルが復活します。しかしこのファイルには何も書かれていないので適当に記述します。以下の文を丸々追加

class Hoge < ActiveRecord::Migration[6.0]
  def change
  end
end

rails db:migrateを実行する

rails db:migrate

ここまできたら消す準備OK。しかしステータスがupのままなので消すためにはdownにする必要がある。

rails db:rollback

iiii.png

downになりました。ここで消すコマンド

rm -rf db/migrate/20200929050736_Hoge.rb

もう一度rails db:migrate:statusで確認してみましょう

これで消し損ねたファイルを完全に消すことができました。

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

オフライン環境構築 Ruby編

オフライン環境構築 目次へ

gem

オンラインで以下のコマンドを実行し、gemファイルをダウンロードする。

ogem-get.sh
name=$1
version=$2
wget https://rubygems.org/downloads/$name-$version.gem

オフラインでgemファイルをロードするときは以下のコマンドを実行する。

ogem-load.sh
name=$1
version=$2
gem install -l $name-$version.gem

参考サイト: https://blog.tgr.wtf/%E3%80%90ruby%E3%80%91gem%E3%82%92%E3%82%AA%E3%83%95%E3%83%A9%E3%82%A4%E3%83%B3%E3%81%A7%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95-346.html

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

画像をぼかす方法(超簡単)

簡単!背景画像をぼかす方法

144f999b1a92884d6f066877ca4bb31e.jpg

CSSに一言だけ付け足せばOK!

index.html.erb
<%= image_tag "star.webp", class:"bgimage" %>

上記のclass名はお好みで!次はCSS!!

○○.css
.bgimage{
  filter: blur(5px);
  width: 100%;
}

上記の通りfilter: blur(5px);を追加すればOK!

5pxとなっていますが、1にするにも10にするにもぼかしの濃さを調整できますのでお好みで!

widthは100%にしておくと画面幅がぴったりになると思うのでこちらも忘れずに!

現場からは以上です!

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

【RSpec】mailer(パスワードのリセット処理)のテストを書いたときにはまった点

最近RSpecにも割と慣れてきて油断しているところに、見たこともないエラーが出てきて少し詰まったのでここで共有したいと思います。
リクエストスペックでmailer(パスワードのリセット処理)のテストを書いたときの話です!

エラー内容

 Failure/Error: expect(mail.body.encoded).to match user.reset_token

       expected "\r\n----==_mimepart_5b18de57c36e0_75293fd69de666b8448c9\r\nContent-Type: text/plain;\r\n charset=UTF...\nL2E+CgogIDwvYm9keT4KPC9odG1sPgo=\r\n\r\n----==_mimepart_5b18de57c36e0_75293fd69de666b8448c9--\r\n" to match "HAY"
       Diff:
       @@ -1,2 +1,32 @@
       -HAY
       +
       +----==_mimepart_5b18de57c36e0_75293fd69de666b8448c9
       +Content-Type: text/plain;
       + charset=UTF-8
       +Content-Transfer-Encoding: base64
       +
       +SEFZCuOBggoK
       +
       +----==_mimepart_5b18de57c36e0_75293fd69de666b8448c9
       +Content-Type: text/html;
       + charset=UTF-8
       +Content-Transfer-Encoding: base64
       +
       +PCFET0NUWVBFIGh0bWw+CjxodG1sPgogIDxoZWFkPgogICAgPG1ldGEgaHR0
       (省略)
       +L2E+CgogIDwvYm9keT4KPC9odG1sPgo=
       +
       +----==_mimepart_5b18de57c36e0_75293fd69de666b8448c9--

こんな感じのエラーが出てきました。
どうやらRSpecでメール本文のエンコード処理が正しくできていないせいで、期待している値と一致せずにテストに失敗しているようです。

解決策

パスワードのリセットトークンを作る時、Base64を使ってエンコードしているので、それを元に戻して比較するとうまくいきました。(デコード)

password_resets_request_spec.rb
RSpec.describe UserMailer, type: :mailer do
  let(:user) { FactoryBot.create(:user, email: 'mailer_tester@example.com') }

  describe "パスワードリセット処理" do
    let(:mail) { UserMailer.password_reset(user) }
    # Base64 encodeをデコードして比較できるようにする
    let(:mail_body) { mail.body.encoded.split(/\r\n/).map{|i| Base64.decode64(i)}.join }

    it "ヘッダーが正しく表示されること" do
      user.reset_token = User.new_token
      expect(mail.to).to eq ["mailer_tester@example.com"]
      expect(mail.from).to eq ["noreply@protuku.com"]
      expect(mail.subject).to eq "パスワードの再設定"
    end

    # メールプレビューのテスト
    it "メール文が正しく表示されること" do
      user.reset_token = User.new_token
      expect(mail_body).to match user.reset_token
      expect(mail_body).to match CGI.escape(user.email)
    end
  end
end

最後まで読んでいただきありがとうございます!

実は、この情報にたどり着くのに少し手間取ったため、記事にしました。

同じようなところで困っている方のお力になれれば幸いです!
ご指摘などあればコメントいただけますと嬉しいです。

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