20190819のRubyに関する記事は14件です。

初学者がRuby on Railsでポートフォリオを作成しました。

はじめに

今回の内容は就職活動中で作成しているポートフォリオの説明です。
アドバイスなどありましたらよろしくお願いいたします。

開発環境

  • Ruby 2.5.1
  • Rails 5.2.3
  • DB:Mysql5.6
  • AWS/S3
  • 少しだけVue.js

アプリ概要

・業者などに頼むほどではない作業や困りごとを得意な人に助けてもらう。
・使う機会がないスキルや自分の得意なことを活かして、困っている人を助ける。
そのような人と人が助け合うアプリがあればいいなという思いから作成しました。

接続先情報

⚠️URLはデプロイなどで接続できないタイミングがございます。その際は少し時間をおいてから接続してください。
⚠︎簡単ログインでログインした方は終わる時にログアウトもお願いいたします。

何ができるか?(機能)

Koto_Kotoは、以下のことができます。

・困りごと,スキルの作成/編集/削除

ezgif.com-video-to-gif.gif

困りごとを作成したいときは、demandボタン、スキルを提案したいときはsupplyボタンから作成することができ、目的別に分けて投稿ができます。
編集や削除は下の画像の赤丸のところからできます。
スクリーンショット 2019-08-19 21.52.53.png

・クレジット登録機能

クレジット登録機能

ezgif.com-video-to-gif (1).gif

Test用としてこちらを入力して頂ければ使用できます。

  • カード番号 4242424242424242
  • 有効期限 12/22
  • CVC番号 123
  • 名前   適当に入力してください

カードの削除も可能です。

・スキル,困りごとの助け合い機能(購入機能)

ezgif.com-video-to-gif (2).gif

カードを登録した場合のみ購入,助けることが可能です。(ポートフォリオなので、万が一購入しても、仮想的に作っているので、お支払いは発生しません。)

あと、助けるボタンを押した場合は、購入ではないので、クレジットからお支払いは発生しないような作りになっています。

・購入後のチャットのやりとり

ezgif.com-video-to-gif (3).gif

スキル購入、困りごとへの助けるボタンを押したら、チャットルームが作成される仕様になっており、お互いでやりとりが可能です。

・契約完了後の評価

ezgif.com-video-to-gif (4).gif
契約完了したら、スキル購入の場合は購入者,困りごと解決の場合は困りごと出品者がその契約内容に関して、評価する仕様になっています。その評価に応じて対象者の信頼スコア(各々が持っている評価指標。マイページの右側の円に囲まれたもの)が加算されます。信頼スコアが高ければ高いほど、その人の評価が高いことになります。

⚠︎評価画面の見た目部分は後々、モーダルで作成したいため、いじっておりません。

・ポイント機能

スクリーンショット 2019-08-18 15.13.28.png

評価されて信頼スコアが上がるだけだとモチベーションupには繋がらないと思ったので、ポイント機能を作成しました。
信頼スコアをあげればあげるほど、ポイント倍率が高くなって、ポイントをためやすくなる仕様にしています。
今後、このポイントを使用して、スキル購入の時に割引として使えるなどの機能を実装したいと考えています。

・ユーザー登録/編集/退会機能

deviseは使用せずに作成しました。(Session&Cookieの概要を学ぶため)
ユーザー登録をすると、確認メールが届くようにしており、そのメールに書かれているリンクを押して初めて、ユーザーが登録される仕様になっています。

・簡単ログイン機能

スクリーンショット 2019-08-19 22.41.08.png

就活用に簡単ログイン機能を実装しました。
ボタン一つでログインできれば、就活の際に見てもらいやすくなるのではないかと考え実装に至りました。

・スキルや困りごとのコメント機能

スキルや困りごとに対してコメントができます。
ezgif.com-video-to-gif (5).gif

・レスポンシブ対応

ezgif.com-video-to-gif (6).gif

スマートフォンが主流なので、そちらでも使いやすくするためにレスポンシブ対応にしました。

課題&追加したい機能

  • vueでのモーダル実装(評価する部分)
  • ランキング機能(頑張った人ほど目に止まる率が高くなる機能を作りたいため)
  • ポイント機能の使用(スキル購入の時に割引として使えるなど)
  • カテゴリー別一覧表示
  • Rspecテスト

最後に

記事を読んでいただきありがとうございました。
また機能を追加次第、更新していきたいと思います。

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

大学2年生のオリジナルWebアプリケーション開発4日目

今日の流れ

  1. Yarnのアップデート
  2. 基本的なログイン機構の作成

今日は時間がなかったためあまり進められませんでした。

1. Yarnのアップデート

開発中にGitHubから次のような Security Alertsが来ました。
security_alerts.png
どうやら「Yarnのバージョンが古いからセキュリティー上危険な状態だぞ」ということらしいです。ということで、Yarnのアップデート方法について調べて、解決しました。具体的な方法が気になる方は、次の記事Cloud9上でのYarnのアップデート(Windows)をご覧ください。

2. 基本的なログイン機構の作成

Railsチュートリアルの第8章にあたる部分です。個人的にRailsチュートリアルを勉強していた時に、一番頭が追い付かなかったのがこのログイン機構の作成です(特に第9章)。たださすがに3週目なのか第8章はすらすら理解できました。
ログイン機構とは別に、Bootstrapのドロップダウン機能について公式サイトやRailsチュートリアルで呼んでいると、JavaScriptの機能なのだと認識でき、Ruby、Railsしか勉強していない自分からすると、少しJavaScriptを使ったことに感動しました笑。まぁ、最終的にこのアプリケーションではどんどん使っていくつもりではありますが。

終わりに

今日は復習メインとなってしまいましたが、Yarnなど初めてきくものもあり、まだまだ知らないことだらけだと実感しました。明日は発展的なログイン機構の作成ですので、気を引き締めていきたいです。
昨日のサマソニはすごかった。

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

書籍『たのしいRuby』の練習問題を解いてみた Part.6

本題

今回は第17章の練習問題を解いていく。今回はIOクラスの内容だ。それでは早速解いてみる。
(1) テキストファイルからデータを読み込んで次の処理を行うスクリプトを作成してください。なお、ここでは空白や改行以外の文字の並びのことを単語と呼ぶことにします。
(a) テキストの行数を数える。
(b)テキストの単語数を数える
(c)テキストの文字数を数える

1_1.rb
file_name = ARGV[0]
file = File.open(file_name)
#aの結果の準備
ans=0
#b,cの結果の準備
txt = []
file.each_line do |line|
    ans+=1
    txt.push(line.split(" "))
end
file.close
#多次元配列を一次元配列にする(bの処理)
txt.flatten!
num1 = txt.size
#cの処理
word = txt.join
num2 = word.size
#aの結果
puts "このファイルは#{ans}行です"
#bの結果
puts "このファイルは#{num1}単語です"
#cの結果
puts "このファイルは#{num2}文字です"

a,b,cを一つのプログラムにして解いた。
コマンドラインから引数を受け取るようにした。まず、File.openでファイルを開く。aはeach_lineメソッドを使用し行数をカウントした。次に、bの単語だ。each_lineメソッドを使用したとき、txt配列に空白で区切った単語を格納させたので、その配列の要素の数をsizeメソッドで返させた。cの文字数は、flatten!メソッドを利用し、文字一つ一つを配列の要素に変換し、その配列の数を数えるようにした。自作wcコマンドのようなものだろうか。

(2) テキストファイルからデータを読み込んで次の条件に従って上書きするスクリプトを作成してください。
(a)ファイルの中の行を逆順に並べ替える
(b)ファイルの中の最初の1行だけを残して残りを削除する
(c)ファイルの中の最後の1行だけを残して残りを削除する

2_a.rb
file_name = ARGV[0]
file = File.open(file_name,"r+")

rev_arry = []
file.each_line do |line|
    rev_arry << line
end
#
rev_arry.reverse!
file.truncate(0)
file.puts rev_arry.join()

file.close

1行ずつ配列の要素として格納。それを逆さにして、頭から入れ直すようにしました。ちなみに、truncateを使いファイルの中身は空にしました。

2_b.rb
file_name = ARGV[0]
file = File.open(file_name,"r+")

arry = []
file.each_line do |line|
    arry << line
end

file.truncate(0)
file.puts arry[0]

file.close

ほぼ先ほどと同じ処理です。違うとしたら、配列の一番最初の要素だけをファイルに書き込んだことくらいです。

2_c.rb
file_name = ARGV[0]
file = File.open(file_name,"r+")

arry = []
file.each_line do |line|
    arry << line
end

file.truncate(0)
file.puts arry[-1]

file.close

b問題とほぼ同じ、こちらは配列の末尾を書き込むようにしました。

(3) Unixで使われる"tail"コマンドと似たことが出来るメソッドtailsを定義しなさい。なお、tailメソッドは2つの引数を受け取ります(tail(行数,ファイル名))

3_1.rb
def tail(num,file)
    f = open(file)
    arry = []
    f.each_line do |line|
        arry << line
    end
    a = -1 * num.to_i
    result = arry[a..-1]
    result.each{|i| p i.chomp}
end

2_cの問題を少しイジった感じです。2_cは末尾のみだったのでそれを必要な行の要素から末尾まで返すようにしました。

(4) Fileオブジェクトへの出力が何バイトまでバッファリングされるか調べるスクリプトを作成してください。

3_1.r
file_name = "Test.txt"
file = File.open(file_name,"w")

10000.times do |i|
    file.write("X")
    size = File.size(file_name)
        if size == i and i>0
        break
    end
    p "#{i+1}回目:#{size}"
end
#実行結果:1回目:0
#      2回目:0
#        省略
#         8192回目:8192

Test.txtというファイルに"X"という文字を増やし続けるようなプログラムにしました。すると、8192回目でTest.txtに書き込まれたことを確認することが出来ました。

最後に

今回はIOクラスについて学習した。使う機会はあるものの、使いこなせていない現状があるので上手く使えるようになりたい。

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

gem installに失敗するときの対処法(Mac)

はじめに

gem install {パッケージ} で様々なエラーが発生して苦戦したので、エラーの内容と解決策を共有します。

環境

  • OS:macOS Mojave 10.14.3
  • Ruby:2.6.3
  • RubyGems:3.0.3

Failed to load {.gemrcのパス} because it doesn't contain valid YAML hash エラー

不具合内容

gem install {パッケージ} で以下のエラーが発生する。

$ gem install {パッケージ}
Failed to load /Users/{ユーザー名}/.gemrc because it doesn't contain valid YAML hash

原因

空の .gemrc ファイルが存在するため。

解決策

空の .gemrc ファイルを削除する。

$ rm ~/.gemrc

Permission denied エラー

不具合内容

gem install {パッケージ} で以下のエラーが発生する。

$ gem install {パッケージ}
ERROR:  While executing gem ... (Errno::EACCES)
    Permission denied @ dir_s_mkdir - /Users/{ユーザー名}/.gem/specs

原因

.gem フォルダの所有者が root になっているため。
なぜ root になったかは不明。

$ cd ~
$ ls -la
…
drwxr-xr-x   3 root        {グループ}     96  8 19 18:59  .gem
…

解決策

.gem フォルダの所有者を自分に変更する。

$ sudo chown -R {ユーザー名} ~/.gem

参考リンク

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

Railsのイベントで初心者ながらすごいなと思ったまとめ

先日Ruby/Railsのイベントに行ったので印象的だったことを簡単にはなりますがまとめました。
Railsは初めて触ったので認識が誤っている点があればご指摘ください...!

scaffoldコマンド

MVCモデルに沿ったファイルの雛形を作ってくれる。
CRUD機能(Create, Read, Update, Delete)を簡単かつ一気に実装できるコマンド

$ rails generate scaffold モデル名 カラム名: 

一気にいろいろできるので処理が止まるまで少々待ちましょう。
基本的な機能は揃っていますがカスタマイズしたい場合などはscaffoldではなく、ひとつひとつ作るのがいいですとのことでした。
scaffoldを失敗してしまったと気づいたときはこちら

※scaffoldしたあとはマイグレーションファイルが作成されるので、テーブルを作成したことをDBに認識させるために rails db:migrate とサーバーを再起動しないとうまく読み込めなくなるので注意が必要
scaffold コマンドで設計図(migrationファイル)ができる
rails db:migrate で設計図(migrationファイル)の通りにDBが作成される、ということでした。
こちらを参考にさせていただきました。
@scivola さんにご指摘いただいたので確認しまして修正しました。ありがとうございました!

現在定義されているルートの確認

①ターミナルに表示する方法

rails routes

 →laravelの php artisan route:list と似た感じで、ターミナルに表示されます

②サーバーに表示する方法

localhost:3000/rails/info/routes

 →個人的にはこちらのほうが見やすかったです

gem

ライブラリやアプリケーションのパッケージで自分で実装すると時間がかかる機能も簡単にできるようになります。
ページネーション、画像を指定のサイズで作成など‥
gemの一種のBundlerをいれることで、Gemfileというファイルにパッケージ名、バージョンを記述してgem同士の互換性を保ちながらパッケージの種類やバージョンを管理してくれます。
Ruby gems

ちょっとしたコードのテスト

直感的で使いやすく、ちょっとしたコードの確認ができます。見やすいし、初心者にはありがたい
TryRuby

番外編:ターミナルからVScodeを起動する方法

 1. command + shift + p
 2. shell を入力
 3. shell command:install 'code' command in PATH を選択
 4. ターミナルで code .
 参考にさせていただきました
 macにもともとあるターミナルからVScodeが立ち上がるのですが、その発想なかったな〜と何度か試してしまいました。おもしろい!

まとめ

laravelとルーティングの書き方が似ていたので想像しやすい部分もあったり、初めてでも便利なコマンドがたくさんあり面白かったです。
たくさんの地域コミュニティがあったり、なんとメンターさんが一人ひとりについてくれたり(!)、アットホームでわからないことを聞きやすい雰囲気が印象的で参加してよかったなぁと思いました。

Rails Girls ガイド
初心者のひとは環境設定に躓くような気がしているのですが、全てわかりやすくのっているので簡単にできました:slight_smile:

 

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

[Ruby] ?‍?‍?‍? を 1 文字とみなす方法

方法

書記素クラスタ (grapheme cluster) の単位で数える。そうすると、僕らが自然だと思う単位で文字を数えることができる。

Ruby での方法

数える

'?‍?‍?‍?'.length
#=> 7

'?‍?‍?‍?'.scan(/\X/).length
#=> 1

# String#each_grapheme_cluster と Enumerable#count を使うと
# 途中で Array オブジェクトを生成せずに文字を数えることができる。
'?‍?‍?‍?'.each_grapheme_cluster.count
#=> 1

ループする

'?‍?‍?‍?'.chars
#=> ["?", "‍", "?", "‍", "?", "‍", "?"]

'?‍?‍?‍?'.grapheme_clusters
#=> ["?‍?‍?‍?"]

'?‍?‍?‍?'.each_char { |chr| puts(format('U+%04X', chr.ord)) }
# U+1F468
# U+200D
# U+1F469
# U+200D
# U+1F466
# U+200D
# U+1F466

'?‍?‍?‍?'.each_grapheme_cluster { |chr| puts(format('U+%04X', chr.ord)) }
# U+1F468

参考

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

Ruby on Railsに触れてみる

はじめに

普段はPHP&JSで開発を行っているのですが、夏休みに入り時間的余裕ができたので、以前から気になっていたRuby on railsに触れたいと思います。
本記事ではUbuntu19.04上で開発環境を整えることをやっていきます。

インストール

今回インストールするものは以下です!

  • rbenv
  • ruby-build

rbenv

Rubyのバージョン管理をしてくれるやつです。pythonで言うpyenvですね。
次のコマンドでインストール

ターミナル
# apt install rbenv
# rbenv -v ←入ったかどうかバージョンを見て確認!

Ruby-build

rbenvのinstallコマンドを提供しているプラグインらしいです。
これが古いと新し目のバージョンがinstall listにないので気をつけてください。
さっきのコマンド実行時にインストールを一緒にしてくれているのですが、2.4.*のバージョンまでしかlistに出てこなかったので、以下のコマンドで新しくしてください。

ターミナル
# git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-buil

早速Rubyをインストール

ターミナル
# rbenv install -l  ←インストールできるバージョンを表示
----(略)----
  2.6.0-rc2
  2.6.0
  2.6.1
  2.6.2
  2.6.3
  2.7.0-dev
  2.7.0-preview1
----(略)-----
# rbenv install 2.6.0  ←2.6.0をインストール
# rbenv versions ←インストールしたバージョンを確認
* system (set by /root/.rbenv/version)
  2.6.0
# rbenv global 2.6.0 ←システムで使用するRubyを2.6.0に設定
# ruby -v ←バージョンの確認
ruby 2.5.5p157 (2019-03-15 revision 67260) [x86_64-linux-gnu]

・・・変わってないだと!?

Rubyのバージョンがしっかり変わらない問題

調べたらPATHがしっかり通っていませんでした。
ubuntuなら以下のコマンドを実行してbash_profileを編集すれば直ります!

ターミナル
# vi ~/.bash_profile
--以下のものを追記------
export PATH="~/.rbenv/shims:/usr/local/bin:$PATH"
eval "$(rbenv init -)"
----------------------
# source ~/.bash_profile ←変更を適用
# rbenv global 2.6.0
# ruby -v
ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-linux]

これで、しっかり変わりました!

railsをインストール

ターミナル
# apt-get install build-essential liblzma-dev patch ruby-dev zlib1g-dev
# gem install rails
# rails --version
Rails 5.2.2

これでRailsのインストールが終了しました。

とりあえずプロジェクトを作成する

インストールできたので適当なサンプルプロジェクトを作ってみます。
とりあえずデスクトップに作っていきます。

ターミナル
# rails new foo
# cd foo
# rails s
(略)
ker/configuration.rb:91:in `rescue in load': Webpacker configuration file not found /home/hara/デスクトップ/foo/config/webpacker.yml. Please run rails webpacker:install Error: No such file or directory @ rb_sysopen - /home/hara/デスクトップ/foo/config/webpacker.yml (RuntimeError)

なんかエラーコード吐かれた・・・

webpackerの設定が見つからないらしいので、そこらへんの情報を検索し以下のコードを実行したら直りました。

ターミナル
yarnをインストール
# curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
# echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
# sudo apt-get update && sudo apt-get install yarn

作ったプロジェクトフォルダー内で
# rails webpacker:install

終わったあと
# rails s
=> Booting Puma
=> Rails 6.0.0 application starting in development
=> Run 'rails server --help' for more startup options
Puma starting in single mode...
* Version 3.12.1 (ruby 2.6.0-p0), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
Use Ctrl-C to stop

これでサーバが起動したのでlocalhost:3000 にアクセス
下のような画面が出れば無事Ruby on Railsを使う準備ができました。
FireShot Capture 001 - Ruby on Rails - localhost.png

とりあえずこれからなにかWebサービスを作ってみていろいろ試します〜〜

参考にさせていただいた記事・サイト

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

Rails6 のちょい足しな新機能を試す66(query with large number編)

はじめに

Rails 6 に追加されそうな新機能を試す第66段。 今回は、 query with large number 編です。
Rails 6 では、 検索条件の値が Integer などの型の範囲外の値であっても検索できるようになりました。

Ruby 2.6.3, Rails 6.0.0.rc1, Rails 5.2.3 で確認しました。Rails 6.0.0.rc1 は gem install rails --prerelease でインストールできます。

(Rails 6.0.0 がリリースされましたが、確認当時は Rails 6.0.0.rc1 がリリースされた時でした。悪しからず。)

$ rails --version
Rails 6.0.0.rc1

今回は、 User モデルに :bigint を指定した age を追加して、 age の範囲外の値を検索条件にして検索してみます。

プロジェクトを作る

rails new rails6_0_0rc1
cd rails6_0_0rc1

model を作る

User モデルを作ります。
name の他に :bigint を指定した age を追加します。

bin/rails g model User name age:bigint

seed データを作る

1件だけですが、 seed データを作成します。

db/seeds.rb
User.create(name: 'Taro', age: 1)

User モデルを修正する

User モデルに scope を5つ作ります。

ここで条件に age の値の範囲に含まれない大きな値と小さな値を指定します。

app/models/user.rb
class User < ApplicationRecord
  LARGE = 9223372036854775808
  SMALL = -9223372036854775809
  scope :age_in_large, -> { where(age: [1..LARGE]) }
  scope :age_eq_large, -> { where(age: LARGE) }
  scope :age_not_eq_large, -> { where.not(age: LARGE) }
  scope :age_in_small, -> { where(age: [SMALL..1]) }
  scope :age_in_small_large, -> { where(age: [SMALL..LARGE]) }
end

seed データを登録します。

$ bin/rails db:create db:migrate db:seed

rails console で確認する

rails console で確認してみます。

irb(main):001:0> User.age_in_large
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."age" >= $1 LIMIT $2  [["age", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, name: "Taro", age: 1, created_at: "2019-07-26 21:21:06", updated_at: "2019-07-26 21:21:06">]>
irb(main):002:0> User.age_eq_large
  User Load (0.5ms)  SELECT "users".* FROM "users" WHERE 1=0 LIMIT $1  [["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
irb(main):003:0> User.age_not_eq_large
  User Load (0.5ms)  SELECT "users".* FROM "users" WHERE 1=1 LIMIT $1  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, name: "Taro", age: 1, created_at: "2019-07-26 21:21:06", updated_at: "2019-07-26 21:21:06">]>
irb(main):004:0> User.age_in_small
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."age" <= $1 LIMIT $2  [["age", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, name: "Taro", age: 1, created_at: "2019-07-26 21:21:06", updated_at: "2019-07-26 21:21:06">]>
irb(main):005:0> User.age_in_small_large
  User Load (0.8ms)  SELECT "users".* FROM "users" WHERE 1=1 LIMIT $1  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, name: "Taro", age: 1, created_at: "2019-07-26 21:21:06", updated_at: "2019-07-26 21:21:06">]>

ここで、実際に発行されているSQLに注目してください。SQL自体には、 -9223372036854775809 や 9223372036854775808 は登場しません。
これは、 age の値として、 -9223372036854775809 や 9223372036854775808 は、あり得ない範囲外の値なので、検索条件に含まなくても良いためです。
工夫されてますね。 User.age_not_eq_large の条件の where 1=1 など、なるほどと思ってしまいます。

Rails 5では

検索条件の値が、 age の範囲に収まらないため、 RangeError になってしまいます。

irb(main):001:0> User.age_eq_large
Traceback (most recent call last):
ActiveModel::RangeError (9223372036854775808 is out of range for ActiveModel::Type::Integer with limit 8 bytes)
irb(main):002:0> User.age_not_eq_large
Traceback (most recent call last):
ActiveModel::RangeError (9223372036854775808 is out of range for ActiveModel::Type::Integer with limit 8 bytes)
irb(main):003:0> User.age_in_large
Traceback (most recent call last):
ActiveModel::RangeError (9223372036854775808 is out of range for ActiveModel::Type::Integer with limit 8 bytes)
irb(main):004:0> User.age_in_small
Traceback (most recent call last):
ActiveModel::RangeError (-9223372036854775809 is out of range for ActiveModel::Type::Integer with limit 8 bytes)
irb(main):005:0> User.age_in_small_large
Traceback (most recent call last):
ActiveModel::RangeError (-9223372036854775809 is out of range for ActiveModel::Type::Integer with limit 8 bytes)

試したソース

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

参考情報

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

Rails deviseの画面をカスタマイズ

はじめに

deviseの準備はできましたが、カスタマイズもしてみたいと思いました。
今回はdeviseのログイン画面をそれっぽくカスタマイズします。

ビューをカスタマイズする

ビューをカスタマイズするには

Rails deviseの準備でも記述したように、deviseのカスタマイズ用のビューを生成する必要があります。

今回はログイン画面をカスタマイズしますので、生成された「app/views/devise/sessions/new.html.erb」をカスタマイズします。

修正前の画面

修正前の画面は次のようになります。
deviseのデフォルトのログイン画面です。

sign_in_000.png

ブラウザはChromeとなります。

修正後のコード

「app/views/devise/sessions/new.html.erb」を次のように修正します。

app/views/devise/sessions/new.html.erb
<div class="box">
  <div class="box-inner">
    <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
      <h1>ログイン</h1>
      <div class="box-email">
        <%= f.label :email, "Eメール" %><br />
        <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
      </div>
      <div class="box-password">
        <div class="a-row">
          <div class="column-left">
            <%= f.label :password, "パスワード" %>
          </div>
          <div class="column-right">
            <%= link_to "パスワードを忘れた場合", new_user_password_path %>
          </div>
        </div>
        <%= f.password_field :password, autocomplete: "current-password" %>
      </div>
      <div class="box-login">
        <%= f.submit "ログイン" %>
        <div class="legal-text">
          続行することで、Hogezonの
          <%= link_to "利用規約", "#" %>
          および
          <%= link_to "プライバシー規約", "#" %>
          に同意するものとみなされます。
        </div>
        <% if devise_mapping.rememberable? %>
          <div class="remember">
            <%= f.check_box :remember_me %>
            <%= f.label :remember, "ログインしたままにする" %>
          </div>
        <% end %>
      </div>
    <% end %>

    <div class="box-newusr">
      <p><span>------------</span> Hogezonの新しいお客様ですか? <span>------------</span></p>
      <%= link_to "Hogezonアカウントを作成", new_user_registration_path %>
    </div>
  </div>
</div>

利用規約とプライバシー規約は未実装です。
雰囲気だけ出してます。

CSSファイルを追加します。

app/assets/stylesheets/signup.css
* {
  margin: 0px;
  padding: 0px;
  text-decoration: none;
}
.box {
  width: 350px;
  height: 450px;
  margin: 60px auto 0;
  border-radius: 4px;
  border: 1px #ddd solid;
}

.box-inner {
  padding: 20px 26px;
}

h1 {
  font-weight: 400;
  font-size: 28px;
  line-height: 1.2;
  margin-bottom: 10px;
  padding-bottom: 4px;
  color: #111111;
}

.box-email {
  margin-bottom: 13px;
}

.box-password {
  margin-bottom: 22px;
}

.box-email label, .box-password label {
  font-weight: 700;
  font-size: 13px;
  padding-left: 2px;
  padding-bottom: 2px;
}

.box-email input[type="email"], .box-password input[type="password"] {
  border-style: none;
  box-sizing: border-box;
  width: 100%;
  height: 31px;
  border: 1px solid #a6a6a6;
  box-shadow: 0 1px 0 rgba(0,0,0,.07) inset;
  border-radius: 3px;
  padding: 0 7px;
}

.column-left {
  float: left;
}

.column-right {
  float: right;
}

.box-password a {
  font-size: 13px;
}

.box-login {
  margin-bottom: 26px;
}

.box-login input[type="submit"] {
  border-style: none;
  width: 100%;
  height: 31px;
  background: linear-gradient(to bottom,#f7dfa5,#f0c14b);
  border-radius: 3px;
  border: 1px #a88734 solid;
}

.box-login input[type="submit"]:hover {
  cursor: pointer;
  background: #f0c14b;
}

.legal-text {
  margin-top: 18px;
  font-size: 12px;
}

.remember {
  font-size: 13px;
  margin-top: 18px;
  padding-left: 3px;
}

.box-newusr p {
  text-align: center;
  font-size: 12px;
  color: #767676;
  margin-bottom: 14px;
}

.box-newusr p span {
  text-decoration: line-through;
  text-decoration-color: #e7e7e7;
}

.box-newusr a {
  display: block;
  width: 100%;
  height: 31px;
  font-size: 13px;
  color: #111;
  line-height: 31px;
  text-align: center;
  background: linear-gradient(to bottom,#f7f8fa,#e7e9ec);
  border-radius: 3px;
  border: 1px #a2a6ac solid;
}

.box-newusr a:hover {
  background: #e7e9ec;
}

修正後の画面

ログイン画面がカスタマイズされました。

sign_in_001.png

おわりに

「Hogezonの新しいお客様ですか?」の部分の横線がうまく表現できず、手を抜いて実装してしまいました。
deviseのビューをカスタマイズできたということで、よしとします。

間違っている箇所とかがありましたら、教えていただけると助かります。

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

永久保存版!?伊藤さん式・Railsアプリのアップグレード手順

はじめに

Railsアプリケーションを長く運用していると避けて通れないのがRailsのバージョンアップです。

古いバージョンのRailsは順次サポートの対象から外れていく(=不具合修正やセキュリティ対応がされなくなる)ため、バージョンアップをせずに運用するわけにはいきません。

そこでこの記事では僕・伊藤淳一がRailsアプリのバージョンをアップグレード(アップデート)する手順を紹介します。

この手順はこれまで何度もRailsアプリケーションをアップグレードしてきた僕の知見が詰まった、いわば「秘伝のタレ」的なアップグレード手順です。

想定するRailsアプリケーション

この記事で想定しているのは以下のようなRailsアプリケーションです。

  • 開発者1人でもなんとか面倒が見れるレベルの規模(=アップグレードは1人で作業する想定)
  • 趣味で作っているのではなく、外部のユーザーがいるRailsアプリ(=不具合が発生すると困る人が出てくるサービス)

また、この記事でいうアップグレードとは、マイナーアップグレード(例:5.1系から5.2系)とメジャーアップグレード(例:5.2系から6.0系)のことです。

手順の概要

この記事は長いので、先に手順の概要を示しておきます。

  • Rails以外のgemを最新にする
  • Rubyのバージョンを最新にする
  • Railsをバージョンアップする
  • rails app:updateタスクを実行する
  • rails crails sでRailsが正常に起動することを確認する
  • 自動テストと手動テストで動作確認する
  • 問題が無さそうならサーバーにデプロイする

ざっくり言うとこんな感じになります。
それでは以下が本文です。

1. 公式のアップグレードガイドに目を通す

Railsガイドにはアップグレードの方法を説明している項があります。
アップグレードする際の主な注意点もバージョンごとに載っているので、まずはこのページに目を通します。

Rails アップグレードガイド - Rails ガイド

日本語訳が追いついていないケースもあるので、英語版にも目を通しておく方がよいでしょう。

Upgrading Ruby on Rails — Ruby on Rails Guides

2. テストが全部パスすることを確認する

実際のアップグレード作業を開始する前に、RSpecやMinitestで書いたテストコードを実行し、全部テストがパスすることを確認します。

bundle exec rspec

カバレッジにも注目し、必要に応じてテストを書き足す

テストが全部パスしていても、カバレッジが低いとテスト不足のため、アップグレード版をリリースした後にシステムエラーが発生、ということが起きかねません。

Simplecovのようなgemを使って、どのファイルがどれくらいテストされているか確認しておきましょう。

そして、「このロジックをテストコードでテストしていないのは怖い」という箇所が見つかったら、アップグレードする前にテストを書いておきましょう。

テストコードを書くのは面倒かもしれませんが、このあとのステップで何度もテストを実行します。
急がば回れの精神でテストを書きましょう。
トータルで見ればその工数は必ずペイできるはずです。

3. 開発用ブランチを作成する

いつでもバージョンアップ前のコードベースに戻せるよう、開発用ブランチを作成しておきます。

# 例:Rails 6に移行するための開発用ブランチを作成する
git checkout -b rails-6-0-migration

4. Rails以外のgemをバージョンアップする

Rails本体のバージョンを先に上げてしまうと、DeviseやCarrierwaveのような周辺のgemが最新のRailsに対応しておらず、思いがけないエラーが起きるかもしれません。

そもそも、古いgemが大量に混じっていると、bundle update railsを実行したときにバージョン番号の解決がうまくいかず、bundle updateが正常に完了できない、ということもよく起きます。

なので、先にRails以外のgemを可能な限り最新版にバージョンアップしていきます。
具体的な手順は以下のとおりです。

4-a. 最新ではないgemを探す

bundle outdatedというコマンドを使うと、Railsアプリ内で最新バージョンを使っていないgemの一覧が得られます。
さらに、bundle_outdated_formatterというgemを使うと、bundle outdatedの結果を見やすく整形することができます。

参考:bundle outdatedコマンドの出力を汎用的な形式に変換するgemを作りました - Qiita

# bundle_outdated_formatterの出力例
bundle outdated | bof --format markdown

| gem | newest | installed | requested | groups |
| --- | --- | --- | --- | --- |
| bootstrap-sass | 3.4.1 | 3.4.0 | | default |
| capybara | 3.28.0 | 3.12.0 | | test |
| childprocess | 2.0.0 | 0.9.0 | | |
| chromedriver-helper | 2.1.1 | 2.1.0 | | test |
| coffee-rails | 5.0.0 | 4.2.2 | | default |
| dotenv | 2.7.5 | 2.5.0 | | |
| dotenv-rails | 2.7.5 | 2.5.0 | | development, test |

上の出力例をマークダウンのテーブルとして表示した場合↓

gem newest installed requested groups
bootstrap-sass 3.4.1 3.4.0 default
capybara 3.28.0 3.12.0 test
childprocess 2.0.0 0.9.0
chromedriver-helper 2.1.1 2.1.0 test
coffee-rails 5.0.0 4.2.2 default
dotenv 2.7.5 2.5.0
dotenv-rails 2.7.5 2.5.0 development, test

この結果を見ながら、どのgemがどれくらい最新バージョンから古くなっているのかを分析します。

コラム:原則としてGemfileにバージョンは指定しない

特別な理由がない限り、Gemfileにはgemのバージョンを指定しないようにします。

Gemfile
# NG: バージョンを指定する
gem 'devise', '~> 4.5.0'

# OK: バージョンを指定しない
gem 'devise'

バージョンを指定しない方が、このあとで全部のgemを一気に最新版にアップデートしやすくなるためです。

バージョンを指定する明確な理由がある場合はその理由をコメントとして書いておきます。
以下はその記述例です。

Gemfile
# 4.6以上にするとxxxでエラーが発生する。以下のissueが解決したら最新版を使う
# https://github.com/plataformatec/devise/issues/9999999
gem 'devise', '~> 4.5.0'

4-b. developmentとtestグループのgemを先にアップデートする

アプリケーションの動きに影響を与える可能性が低い、developmentグループとtestグループのgemから先にアップデートします。
以下のコマンドを使うとグループ単位で一気にgemをアップデートできます。

bundle update -g development -g test

アップデートしたらテストが全部パスすることを確認します。

4-c. トラブルが起きやすそうなgemを1つずつアップデートする

bundle outdatedの結果を見て、メジャーバージョン番号が変わっているgemや、自分の経験上アップデート時にトラブルが発生しやすいgemを1つずつ慎重にアップデートします。

アップデートを実行する前にリポジトリのCHANGELOGを確認して、トラブルを引き起こしそうな(=後方互換性が大きく失われるような)変更履歴がないかどうか、チェックすることも重要です。

例:DeviseのCHANGELOG
https://github.com/plataformatec/devise/blob/master/CHANGELOG.md

CHANGELOGを確認したら、gemを1つずつアップデートしていきます。

# 例:deviseだけをアップデートする
bundle update devise

gemをアップデートしたら、テストを実行したり、実際に画面を操作したりして、今まで通り使えているかどうかを確認します。

このようにして、トラブルが起きやすそうなgemを1つずつアップデートしていきます。

4-d. その他のgemをまとめてアップデートする

トラブルが起きやすそうなgemのアップデートが一通り終わったら、その他のgemをまとめてアップデートします。

# その他のgemをまとめてアップデートする
bundle update

なお、この作業を行う前に、Railsのバージョンが固定されていることを確認しておいてください。
(Railsだけは、まだバージョンを変えたくないため)

Gemfile
# Railsは特定のバージョンに固定されていること
gem 'rails', '5.2.1'

その他のgemをアップデートしたら、テストを実行したり、実際に画面を操作したりして、今まで通り使えているかどうかを確認します。

特に、何らかの理由でテストを自動化できていないロジック(たとえば、テストを書きづらい複雑なドラッグアンドドロップ機能など)は、手動テストを忘れずに行ってください。

最後に、もう一度bundle updatedを実行して、ほぼすべてのgemが最新バージョンにアップデートされたことを確認します。
(gemをひとつ残らず最新にするのは無理だと思うので、そこにはこだわらないようにしましょう)

コラム:gemは普段からこまめにバージョンアップしよう

gemのバージョンアップ作業は実際にやってみると、かなり骨が折れると思います。
古いバージョンのgemが多ければ多いほど、この作業のしんどさが増えるので、日頃からこまめにgemを最新版にアップデートしていくことをお勧めします。

また、そもそもの話ですが、Gemfileに記述するgemを増やしすぎない(=gemを追加するときは、その必要性を慎重に吟味する)ということも大事だと思います。

5. Rubyのバージョンを最新にする

Railsアプリで使用しているRubyのバージョンが古い場合は、このタイミングで最新にしておくと良いかもしれません。
Rubyは後方互換性をかなり重視しているので、バージョンを上げてもトラブルが起きる可能性は低いはずです。
ですが、それでもゼロとは言えないので、Rubyのバージョンを上げたらテストがすべてパスすることを確認してください。

# rbenvで最新のRubyを使うようにする
# (rbenvとRuby 2.6.3のインストールはすでに終わっている前提)
rbenv local 2.6.3

# gemを再インストール
bundle install

# テストがパスすることを確認
bundle exec rspec

なお、新しいRailsは古いバージョンのRubyでは実行できません。
たとえばRails 6はRuby 2.5.0以上が必須です。

バージョンごとのRailsとRubyの対応関係はRailsガイドを参照してください。

Rails アップグレードガイド - Rails ガイド

6. Railsを最新のパッチバージョンに上げる

Railsのマイナーバージョン、またはメジャーバージョンを上げる前に、パッチバージョンを最新に上げます。
たとえば、Rails 5.2.1をRails 6.0に上げる前に、Rails 5.2.3に上げる、という感じです(Rails 5.2.3は本記事執筆時点でのRails 5.2系の最新バージョン)。

Gemfile
 # Railsのパッチバージョンを最新まで上げる
-gem 'rails', '5.2.1'
+gem 'rails', '5.2.3'
bundle update rails

パッチバージョンを上げたら、テストがすべてパスすることを確認します。
テストの実行中に警告メッセージが出ていたら、この時点で警告をなくす修正を行います。

なお、Railsのバージョン履歴は、rubygems.orgで確認できます。

https://rubygems.org/gems/rails/versions

7. Railsのメジャーバージョン、またはマイナーバージョンを上げる

さて、いよいよRailsのバージョンを上げるときがやってきました。
周辺のgemが最新版になっていれば、比較的すんなりbundle updateが完了するはずです。

Gemfile
 # Railsのメジャーバージョンを上げる
-gem 'rails', '5.2.3'
+gem 'rails', '6.0.0'
# 新しいバージョンのRailsをインストール
bundle update

ただし、バージョンを上げる際は間のバージョンをスキップせずに、1つずつアップグレードしてください。(例:5.0から6.0ではなく、5.1、5.2、6.0と順にアップグレードする)

また、上の例では"6.0.0"になっていますが(本記事執筆時点では6.0.0が最新であるため)、0より新しいパッチバージョンが出ていれば最新のパッチバージョンを指定します。

Gemfile
# 0より新しいパッチバージョンが出ていれば最新のパッチバージョンを指定する
gem 'rails', '6.0.2'

bundle updateが終わっても今回はまだテストを実行せず、先に以下の作業を行います。

8. rails app:updateタスクを実行する

次にrails app:updateタスクを実行します。
このタスクを実行すると、新しいバージョンで必要になる新しいファイル作成や、既存ファイルの変更を対話形式で行うことができます。

# 実行例は https://railsguides.jp/upgrading_ruby_on_rails.html より引用
$ rails app:update
   identical  config/boot.rb
       exist  config
    conflict  config/routes.rb
Overwrite /myapp/config/routes.rb? (enter "h" for help) [Ynaqdh]
       force  config/routes.rb
    conflict  config/application.rb
Overwrite /myapp/config/application.rb? (enter "h" for help) [Ynaqdh]
       force  config/application.rb
    conflict  config/environment.rb
...

上書き更新されるファイルは次のように対応方法を質問されるので、 Y/n/a/q/d/hのいずれかのキーを入力します。

Overwrite /myapp/config/application.rb? (enter "h" for help) [Ynaqdh]

各キーの意味は次の通りです。

Y - Yes。上書き実行
n - No。上書きしない
a - All。このファイル以降の全ファイルを上書き
q - Quit。処理中断
d - Diff。新旧ファイルのdiffを表示
h - Help。入力する各キーの意味を表示

僕はd = diffを確認した上で、Yかnを入力することが多いです。
(でも、routes.rb以外はほとんどYを入力しているかもしれない)

必要に応じて上書きされた設定を元に戻す

Yで上書き実行すると、それまで使っていた重要な設定が失わることがあります。
その場合はgitのdiffをチェックしながら、上書きされて消えてしまった設定を自力で戻していきます。

config/environments/production.rb
 # 例:上書き更新でコメントアウトされたforce_sslの設定を元に戻す
-# config.force_ssl = true
+config.force_ssl = true

ちなみにRubyMineを使うと、GUI上で視覚的にdiffの確認とコードの修正(ロールバック)ができるのでとても便利です。

9. railsdiff.orgを参考にして、新しく追加されたgem等を確認する

app:updateコマンドを実行しても、Gemfileのようにまったく更新されないファイルもあります。
ですが、rails newした直後のGemfileを比較すると、デフォルトでインストールされるgemの種類やバージョンには違いがあります。
Railsのバージョンを上げたのであれば、こういった部分も新しいRailsに合わせておく方が安心です。

そういうときに便利なのが http://railsdiff.org です。
このサイトではRailsの各バージョンごとに、rails newした直後のファイルのdiffを確認することができます。

たとえば以下のURLを開くとRails5.1.7と5.2.3のdiffを確認できます。

http://railsdiff.org/5.1.7/5.2.3

Gemfileを見るとbootsnapのような新しいgemがいくつか追加されているので、この情報を見ながら自力で差分を埋めていきます。

Gemfile
 # 例:Rails 5.2からはGemfileにbootsnap gemが追加されているので、自分のアプリにもbootsnapを追加しておく
+# Reduces boot times through caching; required in config/boot.rb
+gem 'bootsnap', '>= 1.1.0', require: false

他のファイルに対しても、必要に応じて自力で差分を埋めていきましょう。

10. 動作確認を行う

そろそろ新しいバージョンのRailsを起動する準備が整いました。
ですが、いきなりテストを動かしても意味不明なエラーが出て面食らうこともよくあります。
なので、僕は次のような順番で動作確認を行います。

10-a. rails cが起動するか?

最初はrails crails console)が起動することを確認します。
この時点でエラーが出て起動に失敗する場合は、エラーメッセージをよく読んでエラーを修正します。

rails consoleが起動し、User.countのような簡単なコードが実行できればOKです。

10-b. rails sが起動するか?

次はrails srails server)が起動することを確認します。
サーバーの立ち上げ時や、サイトアクセス時にエラーが発生する場合は、エラーメッセージをよく読んでエラーを修正します。

画面のデザイン崩れがなく、いくつかの画面が正常に開くようになればOKです。

10-c. 全部テストがパスするか?警告も出ないか?

ここまでくればテストコードも問題なく実行できるはずなので、テストを実行してみましょう。

パスしなかったテストがあれば、原因を調べて修正してください。

また、テストはパスしていても、ターミナルに警告文が表示されていることもよくあります。
"DEPRECATION WARNING"のような文字が出力されていないか、テスト実行後のターミナルを確認してください。

警告文には警告の原因やコードの修正方法、詳細な説明ページのURL、警告が発生したコード行等が載っていることも多いので、英語が苦手な人もまずは英文をじっくり読むことが解決への近道になります。

10-d. load_defaultsやnew_framework_defaults_x_x.rbを設定する

Railsのバージョンが上がると、従来の挙動とは異なる、新しい挙動が導入される場合があります。
バージョンアップ後はすべて新しい挙動に合わせられるのが理想的ですが、場合によっては一部の挙動を古いRailsに合わせないといけないかもしれません。

こうした挙動の変更はload_defaultsnew_framework_defaults_x_x.rbで行います。

load_defaultsnew_framework_defaults_x_x.rbの関係については以下の記事で詳しく説明しているので、こちらを読んで適切に設定を変更してください。

config.load_defaultsとnew_framework_defaults_x_x.rbの関係を詳しく調べてみた - Qiita

10-e. 自分の手と目でテストする

自動テストが全部パスしていても100%安心はできません。
テストはパスしていても微妙に画面の表示が崩れているケースもあるので、自分の手と目でも動作確認しておきましょう。

また、画面のデザイン崩れだけでなく、自動テストで担保できていない複雑な機能も手動でテストする必要があります。

この作業が完了すれば、ローカル環境での動作確認はおしまいです。

11. ステージング環境にデプロイして動作確認する

次に、ステージング環境(本番環境と同じ構成のテスト環境)にRailsアプリをデプロイします。

ローカルではちゃんと動いていても、デプロイしたらサーバーの起動に失敗した、なんていうこともたまにあります。
その場合はエラーログを見ながら、問題を修正してください。

ステージング環境でアプリケーションが動き始めたら、手動テストを行います。
Amazon S3へのファイル保存や外部APIとの連携機能など、ローカル環境では動作確認しづらい機能があれば、必ずここで動作確認しておきます。

動作確認は1日で終わらせるのではなく、できれば数日間動かしてみて、何か問題が起きないか確認する方が望ましいです。

12. プルリクエストを作成し、コードレビューしてもらう

ステージング環境でも動作確認ができたら、本番リリースに向けてプルリクエストを作成し、他のメンバーにコードレビューしてもらいましょう。

もしかすると、コードの修正漏れを指摘されたり、経験者ならではのアドバイスをもらえたりするかもしれません。

13. 本番環境にデプロイして動作確認する

いよいよ最後のステップです。
プルリクエストをマージし、バージョンアップしたRailsアプリを本番環境にデプロイします。

ステージング環境と本番環境がまったく同じ構成であればトラブルが発生する可能性は低いですが、念のため、可能な範囲で手動テストしておきましょう。

バージョンを上げたことに起因するトラブルが突然起きる可能性もあるので、リリース後、数日間はログやサーバーのリソース状況等を注意して監視してください。

まとめ

お疲れ様でした。Railsアプリケーションをアップグレードする手順は以上になります。

アップグレード作業の大変さ(作業開始から完了までにかかる工数)は、アプリケーションの規模やテストのカバレッジ率、gemのアップデートをサボっていた期間の長さ等によって大きく変わってきます。
ですが、運用を続ける限りは「大変そうだから、アップグレードを見送る」という選択肢はまずありません。
技術的負債が雪だるま式に膨らむ前に、早め早めにバージョンを上げていきましょう!

宣伝:テストが苦手な方は「Everyday Rails - RSpecによるRailsテスト入門」をどうぞ!

この手順を最後まで読まれた方はよくわかると思いますが、Railsのアップグレード作業には自動テストが必要不可欠です。
「テストを書くのが苦手」「どうやってテストを書けばいいのかわからない」という方はぜひ、僕が翻訳した電子書籍「Everyday Rails - RSpecによるRailsテスト入門」を読んでみてください。
RSpecや自動テストは初めて、という方でもわかるよう、Railsアプリケーションのテストの書き方を詳しく、丁寧に説明します。

「Everyday Rails - RSpecによるRailsテスト入門」は、以下のLeanpubのサイトから購入可能です。

https://leanpub.com/everydayrailsrspec-jp
hero.png

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

【最新サービス試用⑧】「単純明快・安全・高速」なURL短縮ツール「urlify.dev」をRubyで利用して、簡単短縮作業。

  • 日々輩出される素晴らしき最新サービスを素早く試して、不鮮明な先見性を堂々と誇示する記事第八弾。
  • 「余暇を増やして、サービス乱発試用にあてたい」という未来妄想を省けば、時間が増えることに気づこうとしない私。
  • 今回は、シンプルかつ便利な短縮URLツール「urlify.dev」をRubyで利用することにしよう。

試用サービス名

urlify.dev

概要

  • 無料かつ登録不要の短縮URLサービス。
  • シンプルかつ匿名性が高いため、「気軽・便利・安全」に利用できる。
  • 優れたAPIも提供しているため、プログラムやコマンドでの利用も可能。
  • ツールサイト

特徴

匿名性の高さ

  • 他ツールと違い、IPや登録ページ等のユーザー関連情報をログとして保存しないようになっている。

シンプル

  • 必要最低限の機能や出力のため、短縮機能として、シンプルで気軽に利用できる。

速度

  • 高速アクセスを実現しているAPIを提供しているため、手軽な短縮作業が可能。

提供セットの豊富さ

  • Webサービスでの短縮の際に、URLだけでなく下記の生成物や機能等を提供している。
    • QRコード
    • TwitterやFacebook等の各種SNS連携機能
    • API利用時のPHPチート(参考)コード

結果

  • 下記のように、「urlifyのAPIで結果を取得する処理」を記述したRubyファイルとURLを指定して、コマンドで実行すれば、簡単に短縮URLを返してくれる。

test.png

環境

  • Mac OS X 10.13.4
  • ruby 2.3.3
    • ※Rubyを利用するため、未導入の場合はこちらを参考にする。

手順

  • ※urlifyのサイトで紹介されているAPI利用の参考コードは、PHPでの記述のため、今回はRubyを利用した方法を試用していく。

Rubyファイルの作成

  • Rubyが利用できる状態であることを確認して、下記のコマンドをうち、作業フォルダ・ファイルを作成する。
# Rubyバージョン確認
$ ruby -v
# 作業フォルダ・ファイル作成作成
$ mkdir ~/short_script
$ touch ~/short_script/shorten.rb
# 作業フォルダへの移動
$ cd ~/short_script
  • Rubyファイルの作成後、ファイルの中身を下記にする。
~/short_script/shorten.rb
# 必要モジュール読み込み
require 'json'
require 'uri'
require 'net/http'

# コマンド引数で渡されるURL格納
url =ARGV[0]
# URL変換
encode_url = URI.encode(url)
# urlifyのAPIとしてのURLオブジェクト生成
short_url = URI.parse("https://urlify.dev/api/?url=#{encode_url}&method=json")
# API利用で取得したJSONデータを格納。
json = Net::HTTP.get(short_url)
# 取得JSON解析後、結果格納
result = JSON.parse(json)

# 結果出力
puts (result['short'].nil?) ? '短縮不可能' : "短縮前 : #{result['long']}\n短縮後 : #{result['short']}"

コマンド実行

  • 上記の手順でRubyファイルを記述後、ターミナルへ戻り、下記のようにファイル名と対象URLを指定して、Rubyファイルを実行する。
# 作業フォルダへの移動
$ cd ~/short_script
# Rubyファイル・対象URLを指定して実行
$ ruby shorten.rb https://qiita.com/t_o_d/items/d3799294a6a935f78f8f
  • 実行後、成功していれば結果として返ってくる短縮後のURLにアクセスして、きちんと表示されることを確認。

  • 表示されていれば完了。

まとめ

  • 今回は短縮作業ということで、このサービス利用の必要性を疑うような、短いURLでの利用も純粋に行いながら、記事を書く。
  • 「単純明快・安全」という謳い文句が量産すれば、正直信仰人間である私の激変生活は更に加速。
  • 「次回も謳い文句ありきのサービス試用になるだろう」という未来確定思考と、折り合いをつけながらツール調査を開始。

参考

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

Ruby 繰り返し文

繰り返し文にいくつか方法があったのでメモします。

1.each

words = ["saekom", "misawa", "saecocco"]

words.each do |word|
     puts word
end

【結果】
saekom
misawa
saecocco

2.times do

1.

omikuji = ["大吉", "中吉", "凶"]
3.times do |num|
    puts omikuji[num]
end

【結果】
大吉
中吉

||はブロック変数で、
doからendの中でしか使えないもの。
普通の変数と同じように、名前を自由につけることができる。

2.

omikuji = ["大吉", "中吉", "凶"]
3.times do
    puts omikuji.sample
end

【結果】
中吉
大吉
中吉
(=> ランダムに3回表示される)

3.while

1.

a = 0
while(a < 100)
    puts a
    a += 10
end

【結果】
0
10
20
30
40
50
60
70
80
90

2.

omikuji = ["大吉", "中吉", "凶"]

result = omikuji.sample
while(result != "大吉")
    puts result
    result = omikuji.sample
end
puts result

【結果】
=> 大吉が出続けるまでおみくじを引き続けるプログラム

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

【Ruby入門】 繰り返し文

繰り返し文にいくつか方法があったのでメモします。

1.each

words = ["saekom", "misawa", "saecocco"]

words.each do |word|
     puts word
end

【結果】
saekom
misawa
saecocco

2.times do

1.

omikuji = ["大吉", "中吉", "凶"]
3.times do |num|
    puts omikuji[num]
end

【結果】
大吉
中吉

||はブロック変数で、
doからendの中でしか使えないもの。
普通の変数と同じように、名前を自由につけることができる。

2.

omikuji = ["大吉", "中吉", "凶"]
3.times do
    puts omikuji.sample
end

【結果】
中吉
大吉
中吉
(=> ランダムに3回表示される)

3.while

1.

a = 0
while(a < 100)
    puts a
    a += 10
end

【結果】
0
10
20
30
40
50
60
70
80
90

2.

omikuji = ["大吉", "中吉", "凶"]

result = omikuji.sample
while(result != "大吉")
    puts result
    result = omikuji.sample
end
puts result

【結果】
=> 大吉が出続けるまでおみくじを引き続けるプログラム

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

ISUCONにRubyで挑戦するときに役立つStackProf Web navigatorの使い方

ISUCON9の予選が近づいてきましたね。

私自身、昨年のISUCON8にはGo言語で出場したのですが、今年はチームメンバーの都合上Rubyで出場することになりそうです。

ISUCONではきちんとプロファイリングして根拠のあるチューニングを行うようにしているのですが、Rubyでは何を使ってプロファイリングすべきかわからなかったので調べてみました。
(ちなみに、Go言語だとpprofを使っていればそれなりに解析ができていました)

結果、stackprofが使えそうということがわかりました。
加えて、stackprof-webnavを併用することでWebブラウザから解析結果を閲覧できるようになることもわかりました。
これはISUCONにおいてチームメンバーとプロファイリング結果を共有する際に便利です。

Stackprof_navigator.png

Stackprof_navigator.png

Stackprof_navigator.png

例題として Y!SUCON のソースコードを使わせていただきました。
いつもありがとうございます。

インストール

Gemを追加する。

/var/www/webapp/ruby/Gemfile
gem 'stackprof'
gem 'stackprof-webnav'
$ bundle install

stackprofをmiddlewareとしてrackに組み込む。

/var/www/webapp/ruby/isuwitter.rb
require 'digest/sha1'
require 'json'
require 'net/http'

require 'sinatra/base'
require 'sinatra/json'
require 'mysql2-cs-bind'
# ここから追記
require 'stackprof'
# ここまで追記

module Isuwitter
  class WebApp < Sinatra::Base
    # ここから追記
    use StackProf::Middleware, enabled: true,
                               mode: :cpu,
                               interval: 1000,
                               save_every: 5
    # ここまで追記
    use Rack::Session::Cookie, key: 'isu_session', secret: 'kioicho'
    set :public_folder, File.expand_path('../../public', __FILE__)
    // 中略
  end
end

stackprofのdumpファイルを格納するためtmpディレクトリを作成しておきます。

$ mkdir /var/www/webapp/ruby/tmp
$ chmod 777 /var/www/webapp/ruby/tmp # 他ユーザによる書き込みを許可

プロファイリングする

上記のようにコードを仕込んだあと、アプリを再起動します。
Y!SUCONの場合はsystemdで再起動できるようになっています。

$ sudo systemctl restart isucon-ruby-isuwitter

この状態でベンチマークを実行します。(もしくは調査したいページを開きます)

Y_SUCON_Portal_と_Stackprof_navigator.png

これにてプロファイリングは完了です。

ブラウザ経由でレポートを閲覧する

stackprof-webnavを実行することで、ブラウザ経由でレポートを閲覧できます。

$ stackprof-webnav -f tmp/stackprof-cpu-*.dump

ただし、これだと localhost:9292 でしかlistenしていないので、別ホストからページを開くことができません。
このため、nginxでリバースプロキシするよう設定します。

/etc/nginx/nginx.conf
user nobody;
worker_processes 1;

events {
  worker_connections 1024;
}

http {
  include mime.types;
  default_type application/octet-stream;
  sendfile on;
  keepalive_timeout 65;

  server {
    listen 80;
    root /var/www/webapp/public;

    location / {
      proxy_set_header Host $host;
      proxy_pass http://localhost:8080;
    }
  }
  # ここから追記
  server {
    listen 19292;
    root /var/www/webapp/public;

    location / {
      proxy_set_header Host $host;
      proxy_pass http://localhost:9292;
    }
  }
  # ここまで追記
}

confを修正したらnginxを再起動するのを忘れずに。

$ sudo systemctl restart nginx
$ stackprof-webnav -f tmp/stackprof-cpu-*.dump

ブラウザを開き、http:(サーバのIPアドレス):19292/overview にアクセスするとstackprofの結果を閲覧できます。

Stackprof_navigator.png

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