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

railsアプリでホームのビューを指定する[root]

rootについて

railsのアプリでメイン画面を指定したい時があるかと思います。
そんな時にroutes.rbにrootを指定するだけで簡単に指定できます。

config/routes.rb
root to: "コントローラー名#アクション名"

これでメイン画面を指定できます。

例を書いてみます。
posts_controllerのindexアクションのビューをメイン画面に指定したいときは、

config/routes.rb
root to: "posts#index"

と記載します。

この場合、posts_controllerにindexアクションを書かなくても、app/views/posts/index.html.erbさえあればビューとして表示することが可能です。

最後までご覧いただきありがとうございます。

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

【Rails】Railsチュートリアルでの学び

【Rails】Railsチュートリアルでの学び

文字数の制限をするバリデーションをかける

***.rb
class *** < ApplicationRecord
  validates :カラム名,length: { maximum: 140 },presence: true
end

空欄のまま投稿するのを制限するバリデーションをかける

***.rb
class *** < ApplicationRecord
  validates :カラム名,presence: true
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AtCoder Beginner Contest 168

3回目の挑戦。

A問題

case文を使うための例題、なのだが全部書き下ろしてパス

abc168a.rb
n = gets.chomp.to_s[-1,1]
#puts n
#puts n[-1,1]
if n=="3"
    puts "bon"
else
    if  n== "0"
    puts "pon"
    else
        if n== "1"
        puts "pon"
        else
            if n== "6"
                puts "pon"
            else
                if n=="8"
                    puts "pon"
                else
                    puts "hon"
                end
            end
        end
    end
end

B問題

出力を場合分けするより、長い場合は切り取って末尾に3点ドット付け足した方がスマートですね。

abc168b.rb
k = gets.chomp.to_i
s = gets.chomp.to_s
if s.length <= k
    puts s
else
    print s[0..k-1]
    print "..."
end 

C問題

2針とも先端の座標が求まるので、2点間の距離を直接計算。
各数値を整数のまま扱ってテストケースの半分AC半分WAとなったので、しばらく考えてfloatに変換してAC.
解説にあったように余弦定理で解くと三角関数3個分計算量減るけど、ループないからこれでも良いかな?

abc168c.rb
imput = gets.chomp.split(" ").map!{|item| item.to_i}
a = imput[0].to_f
b = imput[1].to_f
h = imput[2].to_f
m = imput[3].to_f

hang = Math::PI*(30*h + m/2)/180
mang = Math::PI*m*6/180

hy = Math.sin(hang)*a
hx = Math.cos(hang)*a
my = Math.sin(mang)*b
mx = Math.cos(mang)*b
puts Math.sqrt((hy-my)**2 + (hx-mx)**2)

この辺りで60分超えてD問題読んで解けそうにないので断念。
D/E/Fに挑むにはアルゴリズムの例題解いて身に付けるしかないか。
今回のA問題のように力技依存しないように定番過去問の数こなす必要ありそう。

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

ブラウザではじめるRubyゲームプログラミング:Nyle-canvas(DXRubyスタイル)入門

概要

この記事は中学高校生向けプログラミング教室の教材として作ったものを一部改変したものです。

ブラウザだけでRubyのゲームプログラミングがすぐに始められる、Nyle-canvasの使い方を学んでいきます。

rb_dx07_editor.png

rb_dx07.png

そして、応用として「ブロック崩し」などのゲームを自分で作っていくことを目指します。

技術解説

Nyle-canvasとは

Nyle-canvas は、ブラウザ上で動くRubyエディタ・実行環境一体型の統合開発環境です。これは、最近ではScratchなどさまざまなプログラミング言語での開発にも採用されている方式です。

その一番の特長は、パソコンやタブレットのブラウザ(Chromeなど)とネット環境があれば、簡単にRubyのプログラミングを始めることにあります。

Nyle-canvasの特長

  • Rubyのインストール不要
  • エディタ、ターミナルソフト(「コマンドプロンプト」、「PowerShell」、「ターミナル」など)不要
  • さまざまなOSで動作(WindowsやmacOS、Linux、Android、iPadOS、iOSなど)
  • タブレット端末でも動作可能(外付けキーボード、マウス推奨)
  • プログラムはOSに依存せず動作
  • 保存操作なしで、直ちに実行可能
  • 画像データも一体で管理
  • DXRuby互換の書式で記述可能

Nyle-canvasの動作環境

  • ブラウザ(Chromeなど)
  • インターネット接続

従来、プログラミングを始める前に必要だった煩雑な準備が不要で、すぐにプログラミングが始められます。また、ブラウザが動く環境であれば、パソコンだけでなく、タブレット(iPadなど)などさまざまなマシン上で動作します。そして、書いたプログラムは保存操作なしで直ちに実行可能で、プログラミングした結果の確認が素早く何度でも簡単にできるようになります。さらに、プログラムファイルや画像データの管理や、複数のソフトの切替え操作からも解放されます。

以上に加え、Nyle-canvasは、Rubyの2Dゲームライブラリとしてよく使われているDXRubyとほぼ同じ記述で動かせるのも魅力です。そのため、DXRubyで書かれたプログラム資産の活用や、Mac上でDXRubyの書き方でゲーム開発をしたいという要望にも応えてくれます。

なお、Nyle-canvasは、第12回フクオカRuby大賞(2019年度)優秀賞受賞作品です。
http://www.digitalfukuoka.jp/topics/144?locale=ja

Nyle-canvas(DXRubyスタイル)

Nyle-canvasの記述スタイルの内、DXRuby互換のDXRubyスタイルを採用します

バージョン

Nyle-canvas(DXRubyスタイル);dev1(2020/3/15リリース)

実行環境

  • ブラウザ;
    Google Chrome(バージョン 81.0.4044.138,64 ビット,macOS版)

  • 実行OS;
    macOS(Catalina 10.15.4)

その他、Safari/macOS,Chrome/Windows10 でも適宜動作確認

ホームページ

参考サイト

DXRubyスタイルのオリジナルであるDXRubyのページです。

  • Ruby用2Dゲームライブラリ DXRuby:使い方の初歩 - Qiita

https://qiita.com/noanoa07/items/bced6519d9b53685b651

 この記事の元になった、DXRubyの入門記事です。

https://yhara.github.io/dxopal/index.html

 こちらもブラウザで動くDXRuby(互換)ライブラリです。

ソースコード

https://github.com/noanoa07/nyle-canvas-intro

ライセンス

本解説文および解説内のRubyソースコードはともにパブリックドメイン
(Nyle-canvas本体のソースコードは、MITライセンス)

プログラム解説

1. Nyle-canvasの使い方

初めに、Nyle-canvasの基本的な使い方を体験してみます。

1-1. Nyle-canvasエディタ

Nyle-canvasは、ブラウザで以下のサイトにアクセスすることで、プログラム編集画面(エディタ)が表示されます。

なお、ここではブラウザとしてGoogle Chromeを使って説明していきます。(実行環境はmacOS。)

https://spoolkitamura.github.io/nyle-canvas/dev1/nyle-canvas.html?style=dx

Nyle-canvas_editor.png

1-2. エディタ画面の解説

エディタ画面にはあらかじめ基本のプログラムが表示されています。
また、画面左上には各種ボタンが並んでいます。
右から、
- ▶︎ ボタン;プログラム実行
- ↓ ボタン;プログラム保存(ダウンロード)
- Tボタン;フォント(文字サイズ)設定
- ?ボタン;ヘルプ(リファレンス)画面へ

1-3. プログラムの実行

あらかじめ基本のプログラムが表示されているので、とりあえず ▶︎ボタンを押してプログラムを実行してみます。

rb_dx00.rb
# 初期設定用のコード (your setup code here)
Window.width   = 640
Window.height  = 480
Window.bgcolor = DX::C_BLACK

Window.loop do
  # 画面描画用のコード (your draw code here)

end

rb_dx00.png

すると、ブラウザの新しいタブが開き、黒い四角形が表示されます。これが、基本のウィンドウ画面になります。

1-4. プログラムの保存

このプログラムを保存してみます。↓ボタンを押すと、ダイアログが出て、OKを押すと、プログラムがダウンロードされます。ダウンロード先は、ブラウザの設定によりますが、「ダウンロード」フォルダになることが多いようです。

Nyle-canvas_editor_2.png

このように、ダウンロードフォルダに日付と時刻を元にした名前が付けられたファイルが保存されています。

download_folder.png

ここで、保存されたプログラムファイルが、HTMLファイルなのに注意してください。
このファイルには、Rubyのプログラム部分だけでなく、ブラウザで実行するためのデータ、さらには画像データなどもすべて含まれています。

HTMLファイルの中身がどうなっているか見たいと思ったら、エディタで開くと中身が確認できます。

rb_dx00.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Nyle-canvas</title>
<!-- Nyle-canvas editor v0.7.0 -->
</head>
<body>
<script type="text/javascript" src="https://cdn.opalrb.com/opal/0.11.4/opal.min.js" onload="Opal.load('opal')"></script>
<script type="text/javascript" src="https://cdn.opalrb.com/opal/0.11.4/opal-parser.min.js" onload="Opal.load('opal-parser')"></script>
<script type="text/javascript" src="https://cdn.opalrb.com/opal/0.11.4/native.min.js" onload="Opal.load('native')"></script>
<script type="text/javascript" src="https://spoolkitamura.github.io/nyle-canvas/dev1/nyle-canvas.js"></script>
<script type="text/javascript">
</script>
<script type="text/ruby">
# 初期設定用のコード (your setup code here)
Window.width   = 640
Window.height  = 480
Window.bgcolor = DX::C_BLACK

Window.loop do
  # 画面描画用のコード (your draw code here)

end
</script>
</body>
</html>

このように、HTMLファイルの中にRubyプログラムが埋め込まれているのが分かります。

また、ファイルとしてはHTMLファイルなので、直接ダブルクリックするか、ブラウザの任意のウィンドウにドラッグ&ドロップすると、Rubyのプログラムが実行されます。

1-5. 保存したプログラムの名前の変更

保存されたプログラムフォルダの名前は、普通のファイル名変更のやり方で自分の好きな名前に変更できます。

download_folder_2.png

1-6. プログラムの読み込み

保存してあるプログラムの内容を見たり、編集するには、プログラムファイル(HTMLファイル)をブラウザのNyle-canvasエディタ画面にドラッグ&ドロップします。

Nyle-canvas_editor_3.png

すると、ダイアログが開いて、「ドロップされたファイルを読み込みますか?」と聞いてくるので、OKを押すと読み込まれます。

ちなみに、読み込んだファイルを再度保存すると、同じ名前で上書き保存されそうですが、実際は上書きはされず、xxxx(1).htmlのような違う名前で区別されて保存されます。(細かい挙動は、実行環境に依存します。)

Nyle-canvas_editor_4.png

download_folder_3.png

1-7. プログラムの新規作成

プログラムを新規作成したくなったら、ブラウザのNyle-canvasエディタ画面を再読み込みすると、最初の状態に戻ります。
再読み込みは、ブラウザ上部の「↻」ボタンを押すか、メニュー>ファイル>表示>ページを再読み込み を選ぶとできます。

reload.png

1-8. コンソールの開き方

エラーメッセージやputsの結果は、ブラウザのコンソールに出力されます。まずは、コンソールを表示させてみましょう。

Chromeでの開き方は;(実行画面で)

  • macOSの場合; メニュー>表示>開発/管理>Javascriptコンソール を選択。

(ショートカットは、Command + Option + J)

console.png

  • Windowsの場合; メニュー> その他のツール>デベロッパーツール> 開いたデベロッパーツールの中の「Console」を選択。

(ショートカットは、Ctrl + Shift + J)

windows_conlose.png

あるいは、macOS、Windowsとも;

F12(あるいは fn + F12)キーを押すか、

画面上の任意の場所で 右クリック(2本指クリックなど)>検証>開いたデベロッパーツールの中の「Console」を選択。

menu_console.png

参考)コンソールの表示位置の変え方

Chromeのコンソール(デベロッパーツール)の表示される位置は、設定によって下側だったり、右側だったりします。

好みのレイアウトに変えるには、右端の(赤く囲った)縦3点「︙」ボタンをクリックすると、メニューが現れるので、「Dock side」のアイコンの中から選びます。

console_layout.png

console_layout2.png

ここでは、右側に表示されました。
console_layout_right.png

1-9. コンソールの使い道

A) エラーメッセージの確認

プログラムを実行させてエラーが起きた時に、エラーメッセージを見ることができます。

この実行画面では、エラーにより真っ白な画面になってしまいました。
error.png

コンソールが開いた画面がこちらです。
ここでは、赤い行にエラーメッセージが表示されています。
error_console.png

ただし、このエラーメッセージはなかなか分かりにくいことがあります。(内部で、Ruby→JavascriptパーサOpalを通してJavascript実行されているため。)
今後の機能改善に期待したいところです。

少なくとも、”今、エラーが出ているか?” という確認や、エラーのヒントとして十分役に立ちます。

B) puts や p の出力を見る

コンソールは、puts や p の出力先にもなっています。

rb_dx00a.rb
# 初期設定用のコード (your setup code here)
Window.width   = 640
Window.height  = 480
Window.bgcolor = DX::C_BLACK

puts "Hello!"                  # ◆追加
p "こんにちは!"         # ◆追加

Window.loop do
  # 画面描画用のコード (your draw code here)

end

このプログラムを実行すると、コンソールに Hello!、"こんにちは!" と出力されるのが分かります。

hello.png

1-10. ヘルプ(リファレンス)

Nyle-canvasエディタ画面左上の「?」ボタンを押すとヘルプ(リファレンス)画面が開きます。

→ [Nyle-canvas] APIリファレンス (DXRubyスタイル)
https://spoolkitamura.github.io/nyle-canvas/dev1/site/_man_api_dx/index.html

Nyle-canvas_help.png

Nyle-canvasのAPIが簡潔にまとめられているので、困ったときにはどんどん活用してください。

1-11. 全角文字に注意

Nyle-canvasだけではありませんが、ほとんどのプログラミング言語では全角の文字は命令として使えません。特に、全角のスペース(空白文字)が入っていると、エラーになっても見つけにくいので要注意です。

1-12. 便利機能

Nyle-canvasエディタには、プログラム作成に便利な機能が備わっています。
キーボードショートで呼び出します。
- 検索:command + F(macOS)、ctrl + F(Windows)
- 置換:command + option + F(macOS)、ctrl + H(Windows)

1-13. Nyle-canvasでのプログラミングのやり方

Nyle-canvasでは、編集したプログラムを保存しないでも、すぐに実行することできます。そのため、“ちょっと書き直したら、ちょっと動かしてみる” というやり方が向いています。

以下の練習でもそのやり方でやってみましょう。

2. Nyle-canvasの練習

2-0. ウィンドウを出す

1-3.で体験した通り、Nyle-canvasエディタ画面を開くと、あらかじめ基本のコードがすでに書かれています。

(書き換えている場合は、「1-7.プログラムの新規作成」の通りに、画面を再読み込みしてください。)

以下、Rubyのプログラム部分だけを載せていきます。

rb_dx00.rb
# 初期設定用のコード (your setup code here)
Window.width   = 640
Window.height  = 480
Window.bgcolor = DX::C_BLACK

Window.loop do
  # 画面描画用のコード (your draw code here)

end

初期設定では、横640、縦480、黒色のウィンドウが開きます。

座標は、左上が原点(0, 0)、横(x)は右方向に増加、縦(y)は下方向に増加です。

Window.loop do 〜 end の間に書いたコードは、1秒間に60回繰り返し実行されます。

→ DXRubyリファレンス:チュートリアル 1. 基本の形
http://mirichi.github.io/dxruby-doc/tutorial/basic.html

rb_dx00.png

2-1. 初期設定を修正

初期設定にinclude DXと書くことで、色定数の
DX::C_BLACKC_BLACKと、よりDXRubyと互換性が高くなるので追加します。

これ以降のプログラムでも、include DXはすべて書いておくことにします。

rb_dx01.rb
# 初期設定用のコード (your setup code here)
include DX                  # ◆追加
Window.width   = 640
Window.height  = 480
Window.bgcolor = C_BLACK    # ◇変更

Window.loop do
  # 画面描画用のコード (your draw code here)

end

rb_dx01.png

2-2. ウィンドウの大きさを変える

ウィンドウの大きさを変えるには、Window.width =Window.height =を使います。

プログラムの内、最初の1回だけ実行されて以後変える必要のないものは、Window.loop do 〜 end より前に書いておきます。

rb_dx02.rb
# 初期設定用のコード (your setup code here)
include DX
Window.width   = 200       # ◇変更
Window.height  = 150       # ◇変更
Window.bgcolor = C_BLACK

Window.loop do
  # 画面描画用のコード (your draw code here)

end

rb_dx02.png

2-3. ウィンドウの背景の色を変える

ウィンドウの背景の色を変えるには、Window.bgcolor =を使います。

色の指定は、Nyle-canvasエディタのヘルプボタンを押して表示される、 「APIリファレンス」の「色に関する情報」を見てください。

(2-2.で、初期設定にinclude DX を加えたので、DX::は省略できます。)

rb_dx03.rb
# 初期設定用のコード (your setup code here)
include DX
Window.width   = 640       # ◇変更(戻す)
Window.height  = 480       # ◇変更(戻す)
Window.bgcolor = C_CYAN    # ◇変更

Window.loop do
  # 画面描画用のコード (your draw code here)

end

rb_dx03.png

2-4. 画面に文字を出す

画面に文字を出すには、

font = Font.new(文字サイズ) で文字サイズ(とフォント名)を指定しておいて、

Window.draw_font(x位置, y位置, "文字列", フォント, {:color => 色})

で表示します。

rb_dx04.rb
# 初期設定用のコード (your setup code here)
include DX
Window.width   = 640
Window.height  = 480
Window.bgcolor = C_BLACK    # ◇変更(戻す)

font = Font.new(32)         # ◆追加

Window.loop do
  Window.draw_font(200, 100, "ブロック崩し", font, {:color => C_GREEN})   # ◆追加
end

rb_dx04.png

2-5. キー入力をとらえる

キー入力はInput.key_down?(キーコード定数)を使います。

キーコード定数については、「APIリファレンス」の「キーコードに関する情報」を見てください。

include DX が書いてあれば、DX::は省略できます。)

rb_dx05.rb
# 初期設定用のコード (your setup code here)
include DX
Window.width   = 640
Window.height  = 480
Window.bgcolor = C_BLACK

font = Font.new(32)

Window.loop do
  Window.draw_font(150, 100, "A のキーを押してください", font, {:color => C_GREEN})  # ◇変更

  if Input.key_down?(K_A)                                        # ◆追加
    Window.draw_font(300, 250, "A", font, {:color => C_WHITE})   # ◆追加
  end                                                            # ◆追加
end

rb_dx05.png

Aのキーを押すと、画面にAと表示されます。
rb_dx05a.png

2-6. 図形の表示

ウィンドウに基本的な図形を表示します。

表示できるのは、線、直線、四角、円です。表示するには、それぞれ以下の命令を使います。
- 点        :Window.draw_pixel
- 直線       :Window.draw_line
- 四角       :Window.draw_box
- 四角(塗りつぶし):Window.draw_box_fill
- 円        :Window.draw_circle
- 円(塗りつぶし) :Window.draw_circle_fill

画像を読み込んだり、動かしたり、いろいろと操作するには、これとは別に Imageクラスが用意されています。

rb_dx06.rb
# 初期設定用のコード (your setup code here)
include DX
Window.width   = 640
Window.height  = 480
Window.bgcolor = C_BLACK


Window.loop do
  Window.draw_box_fill(100, 100, 540, 380, C_YELLOW)   # ◇変更
end

rb_dx06.png

2-7. 画像の読み込み

Nyle-Canvasでは、画像ファイルの取り扱い方が DXRubyとは少し異なります。

まず、使いたい画像ファイルをエディタ画面に直接ドラッグ&ドロップしていきます。すると、画像ファイルはNyle-canvas内にコピーされ、エディタ画面下側に画像ファイルの一覧として表示されるようになります。

(ちなみに、いらなくなった画像ファイルは、一覧の右側の「取り消し」ボタンを押すと、一覧からなくなります。)

試しに、src/imageフォルダにあるapple.pngファイルをエディタ画面にドラッグ&ドロップしてみます。

rb_dx07_editor.png
画像ファイルapple.pngがコピーされ、一覧に表示されました。

このように、画像ファイルとプログラムを一体で管理するのが、Nyle-canvasの大きな特徴です。

次に、プログラムから画像ファイル読み込んで使うには、Image.load(画像ファイル)を使います。画像ファイル名の前に場所を示すパス名などは不要です。

読み込んだ画像は、Imageクラスになります。

Imageクラスの表示は、Window.draw(x座標, y座標, イメージ)を使います。なお、座標の基準はイメージの左上になります。

rb_dx07.rb
# 初期設定用のコード (your setup code here)
include DX
Window.width   = 640
Window.height  = 480
Window.bgcolor = C_BLACK

apple = Image.load('apple.png')   # ◆追加

Window.loop do
  Window.draw(100, 100, apple)    # ◆追加
end

rb_dx07.png

参考)画像を含んだプログラムを保存すると、画像はどうなる?

保存したプログラムのHTMLファイルをエディタで開いてみます。
(一部省略)

rb_dx07.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Nyle-canvas</title>
<!-- Nyle-canvas editor v0.7.0 -->
</head>
<body>
<script>
 (省略)
</script>
<script type="text/javascript">
Store.createImage('apple.png', 100, 100, 'data:image/png;base64,iVBORw0KGgoAAAANSU....(途中省略)....ElFTkSuQmCC')
</script>
<script type="text/ruby">
# 初期設定用のコード (your setup code here)
include DX
Window.width   = 640
Window.height  = 480
Window.bgcolor = C_BLACK

apple = Image.load('apple.png')   # ◆追加

Window.loop do
  Window.draw(100, 100, apple)    # ◆追加
end
</script>
</body>
</html>

このように、'apple.png', 100, 100, 'data:image/png;base64,iVBOR.... の部分で、apple.png の画像データはBase64でエンコードされて一緒に保存されていることが分かります。

そのため、プログラムで使う画像データの管理に気を使うことなく、プログラミングに集中できる仕組みになっているのです。

2-8. 画像の背景色の透明化

イメージでset_color_key(色)を使うと、指定した色を透明にできます。

註)

2020/3/15リリースのdev1ではこの機能は未実装になっています。

【注意】
内部処理がまだ実装されていないため、このメソッドを実行しても指定色は透明化されません。
その代わりに、Image.loadおよび Image.load_tilesメソッド内で暫定的に白色を自動的に透明にするようになっています。
(リファレンスより)

そのため、今のところset_color_key(C_WHITE)を実行する必要はありませんが、将来のバージョンアップ時に対応するために記述しておきます。

ちなみに、このapple.pngは、背景が白色なので、自動的に透明化されています。

rb_dx08.rb
# 初期設定用のコード (your setup code here)
include DX
Window.width   = 640
Window.height  = 480
Window.bgcolor = C_BLACK

apple = Image.load('apple.png')
apple.set_color_key(C_WHITE)      # ◆追加

Window.loop do
  Window.draw(100, 100, apple)
end

rb_dx08.png

2-9. 画像の拡大・縮小

イメージを拡大・縮小して表示したい時は、Window.draw_scale(x位置, y位置, イメージ, 横の拡大率, 縦の拡大率)を使います。

rb_dx09.rb
## 初期設定用のコード (your setup code here)
include DX
Window.width   = 640
Window.height  = 480
Window.bgcolor = C_BLACK

apple = Image.load('apple.png')
apple.set_color_key(C_WHITE)

Window.loop do
  Window.draw_scale(100, 100, apple, 0.5, 0.5)    # ◇変更
end

rb_dx09.png

2-10. カーソルキーで移動

カーソルキーが押されると、左右方向はInput.x、上下方向はInput.y-1, 0, 1 に変化します。

これを利用することで、画面上を移動させることができます。

rb_dx10.rb
# 初期設定用のコード (your setup code here)
include DX
Window.width   = 640
Window.height  = 480
Window.bgcolor = C_BLACK

apple = Image.load('apple.png')
apple.set_color_key(C_WHITE)
x = 200                       # ◆追加
y = 200                       # ◆追加

Window.loop do
  x = x + Input.x             # ◆追加
  y = y + Input.y             # ◆追加

  Window.draw(x, y, apple)    # ◇変更
end

rb_dx10.png

2-11. カーソルキーで移動(別の書き方)

ball.x = ball.x + Input.x を別の書き方である、

ball.x += Input.x に書き換えてみます。同じ意味ですが、こちらの方が文字数が少なくて済むので、間違いが減らせるかも。

rb_dx11.rb
# 初期設定用のコード (your setup code here)
include DX
Window.width   = 640
Window.height  = 480
Window.bgcolor = C_BLACK

apple = Image.load('apple.png')
apple.set_color_key(C_WHITE)
x = 200
y = 200

Window.loop do
  x += Input.x               # ◇変更
  y += Input.y               # ◇変更

  Window.draw(x, y, apple)
end

rb_dx11.png

2-12. マウスに合わせて移動

マウスのx座標、y座標はそれぞれInput.mouse_xInput.mouse_yで取得できます。

なお、座標の基準はイメージの場合、左上になります。

rb_dx12.rb
# 初期設定用のコード (your setup code here)
include DX
Window.width   = 640
Window.height  = 480
Window.bgcolor = C_BLACK

apple = Image.load('apple.png')
apple.set_color_key(C_WHITE)


Window.loop do
  x = Input.mouse_x               # ◇変更
  y = Input.mouse_y               # ◇変更

  Window.draw(x, y, apple)
end

rb_dx12.png

以上で、Nyle-canvasの練習は一通り終わりです。

応用問題

Nyle-canvasの使い方に慣れたところで、「ブロック崩し」を作ってみましょう!

block.png

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

Railsのエラー undefined method `image_name' for nil:NilClass の対処

発生した問題

Progate学習のアウトプットのため学習したアプリを同じように作成。
投稿一覧画面に投稿者とその投稿者の画像を表示させる内容。

見本通り入力したところ、undefined method 'image_name' for nil:NilClassのエラー
が。

試したこと

・post.rb、views/posts/index.html.erb、関連部分のメソッド、srcの値等の入力ミスがないか確認→問題なし

解決方法

ググったり色々試した結果、rails db:migrateしたらなおりました。

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

【rails】新しいバージョンのRuby on Rails環境を用意した。

アプリケーションを作るため、新しいバージョンのRuby on Railsが必要になり、ローカル環境に用意した。
(既存アプリに影響を与えないことを条件とした)

Ruby Rails
必要なバージョン 2.7.1 6.0.3
既存のバージョン 2.5.1 5.0.7.2

参考

https://qiita.com/pharma_tech3/items/2ab578eb5b07ff0ca296

環境構築方法

rails 6.0.3の導入
terminal
$ gem install rails -v 6.0.3
$ rails _6.0.3_ new linebot -d mysql
       ...
* bin/rake: Spring inserted
* bin/rails: Spring inserted
       rails  webpacker:install
sh: node: command not found
sh: nodejs: command not found
Node.js not installed. Please download and install Node.js https://nodejs.org/en/download/

途中でwebpackage install が実行されたときに、node.jsがないとのメッセージが出ている。

node.jsをインストールする。

terminal
$ brew install node

$ node -v   
v14.2.0

再度rails webpacker:installを実行する。

terminal
$ rails webpacker:install
Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/

今度は、yarnがインストールされていないからダウンロードしてインストールしてね。とのこと

terminal
$ brew install yarn

$ yarn -v
1.22.4

yarnがインストールされた。

terminal
$ rails webpacker:install
   ...
✨  Done in 6.92s.
Webpacker successfully installed ? ?

Webpackerのインストールが成功した。

terminal
$ cd linebot
$ rails -v
Rails 6.0.3

railsの新しいバージョンが使えるようになった。

新しいプロジェクトを作成する。

terminal
$ rails _6.0.3_ new linebot -d mysql

$ cd linebot
Ruby 2.7.1の導入

Ruby 2.7.1をインストールするコマンドを実行する。

terminal
$ rbenv install 2.7.1
ruby-build: definition not found: 2.7.1

See all available versions with `rbenv install --list'.

If the version you need is missing, try upgrading ruby-build:

  brew update && brew upgrade ruby-build

brew updatebrew upgrade ruby-build を実行してね。とのこと

インストール可能なリストを確認する。

terminal
$ rbenv install -l
   ...
2.6.4
2.6.5
2.7.0-dev
2.7.0-preview1
2.7.0-preview2
2.7.0-preview3
2.7.0-rc1
2.7.0-rc2
jruby-1.5.6
jruby-1.6.3
   ...

インストール可能なリストの中に、2.7.1がない。

terminal
$ brew update            
Already up-to-date.
terminal
$ brew upgrade ruby-build
==> Upgrading 1 outdated package:
ruby-build 20191223 -> 20200401
...
==> Caveats
==> ruby-build
ruby-build installs a non-Homebrew OpenSSL for each Ruby version installed and these are never upgraded.

To link Rubies to Homebrew's OpenSSL 1.1 (which is upgraded) add the following
to your ~/.zshrc:
  export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@1.1)"

Note: this may interfere with building old versions of Ruby (e.g <2.4) that use
OpenSSL <1.1.

インストール可能なリストの中に、2.7.1出現した。

terminal
$ rbenv install -l
   ...
2.7.0-preview3
2.7.0-rc1
2.7.0-rc2
2.7.0
2.7.1
2.8.0-dev
jruby-1.5.6
jruby-1.6.3
   ...

バージョンを指定してインストールする。

terminal
$ rbenv install 2.7.1    
Downloading openssl-1.1.1d.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/1e3a91bc1f9dfce01af26026f856e064eab4c8ee0a8f457b5ae30b40b8b711f2
Installing openssl-1.1.1d...
Installed openssl-1.1.1d to /Users/Taiti/.rbenv/versions/2.7.1

Downloading ruby-2.7.1.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.1.tar.bz2
Installing ruby-2.7.1...
ruby-build: using readline from homebrew
Installed ruby-2.7.1 to /Users/Taiti/.rbenv/versions/2.7.1

プロジェクトフォルダ内のみ、バージョン2.7.1を適用する。

$ rbenv local 2.7.1
$ rbenv rehash
$ ruby -v          
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-darwin19]

完了

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

railsアプリをherokuでデプロイする方法(Mysqlでも確実にデプロイできます)

本記事について

railsアプリをherokuでデプロイする方法を調べていたのですが、開発環境(developmentやtest環境)でRailsアプリに最初からついているDB(SQLite3)を使用している事を前提に書かれた記事が多く、混乱してしまったので、DBにMysqlを採用している方に向けて記事を書いていこうと思います。

※変更内容の意味を理解していればどのDBを使っていようが同じ手順だと気づくのですが、初心者の僕は混乱して躓いてしまったので、同じ様な方が少しでも楽に理解できる様に執筆しています。

環境

  • Ruby 2.5.1
  • Rails 5.0.7.2
  • git 2.25.2
  • heroku/7.41.1 darwin-x64 node-v12.16.2

事前に準備して欲しいもの

  • Railsで作成したアプリ(下記二つの条件を満たしているもの)
    • Gitで管理している
    • ローカル環境でエラーが出ていない(デプロイ中にエラーが出た場合、デプロイ時に起こったエラーかローカル環境でのエラーが関係しているのか分からなくなってしまうので、それを防ぐ為)
  • herokuのユーザー登録
  • heroku-cil(herokuの機能を自分のPCに紐付けるもの→herokuのコマンドをPCで使える様にする)のインストール

今回はherokuについての記事なので、Gitについての説明は割愛させて頂きます。

デプロイ作業を始める前に

デプロイ作業を始める前に、デプロイしたいRailsアプリのコードを一部編集する必要があります。
編集するのは以下の三箇所です。

  • Gemfile(各環境で使うDBの設定を変更する)
  • config/datebase.yml(実際に本番環境で使うDBを接続する記述を追加する)
  • config/environments/production.rb(本番環境でのプリコンパイルをオンにする)

編集する内容について一つずつ理由とともに解説していきますので、変更する場所だけ確認できたら読み進めて貰って大丈夫です。

Gemfileの設定

削除するコードが一箇所、追記するコードが二つあります。

  • 削除する箇所
Gemfile
gem 'mysql2'
  • 追記する箇所
Gemfile
group :development, :test do
  gem 'mysql2'
end

※group :development, :test do ~ end内に他にもgemが書いてあったと思いますが、消さないでください。

Gemfile
group :production do
  gem 'pg'
end

 何をしてんだ?

herokuではPostgreSQL(pg)というDBをデフォルトで使う様に設定されています。
普通に作っている方は、全ての環境下でmysqlを使う様に表記していると思うので、その表記を削除し、開発環境、テスト環境下のみでmysqlを使える様にgroup :development, :test do ~ end内にgem 'mysql2'の表記を追加しています。
また、本番環境でPostgreSQL(pg)が使える様にgroup :production do ~ end内にgem 'pg'を表記しています。

config/datebase.ymlの設定

追記するコードが一つあります。

config/datebase.yml
production:
  <<: *default
  adapter: postgresql
  encoding: unicode
  pool: 5 

※production:内にあった元々の記述は全て削除して、上記の様に書き換えて下さい。

 何をしてんだ?

先ほどgemを追加し、機能をインストールするための準備は整えたのですが、実際にDBと接続する記述はまだ完了していません。どのDBに接続するのか?という設定をする箇所がconfig/database.ymlです。
※開発環境、テスト環境で使用するDBの設定もここに書かれています。

追加したコードの意味は以下の様になります。

adapter: postgresql - postgreSQLのデータベースに接続。
encoding: unicode - unicodeという文字コードを使用。
pool: 5 - DBに接続できる上限の数を指定。

DBに接続する為の設定をしたんだ!ってことが分かればOKです。

config/environments/production.rbの設定

追記するコードが一つあります。

config/environments/production.rb
#デフォルトでfalseとなっている以下の箇所をtrueに変更
  config.assets.compile = true

 何をしてんだ?

Railsは本番環境でのプリコンパイルがデフォルトでオフになっています。
assetsを圧縮して少しでも軽くする為だそうです。
assets以下のフォルダから動的にコンパイルしながらページを読み込む為にtrueに変更しています。
難しく書きましたが、本番環境でも画像を読み込んでくれよ~って表記にしただけです。

いよいよデプロイ作業開始

これでデプロイをする前の事前準備が終わったので、いよいよデプロイ作業に移ります。
デプロイまでの流れは以下の通りです。

  1. herokuにログイン
  2. 公開されるRailsアプリのurlを決める
  3. pushしてデプロイ
  4. 本番環境でマイグレーションをする

AWSとかと比べて超絶簡単なので気負いせずにさくっと終わらせましょう!

1.herokuにログイン

ターミナル
$heroku login

上記コマンドでherokuにログインします。
コマンド入力に成功すると(なんか格ゲーみたい)herokuに登録したEmailとpasswordの入力を求められるので、ゆっくり正確に入力しましょう。
入力に成功すると下記の様にターミナルに表示されます。
(as ~ は自分のメールアドレスです。)

ターミナル
Logged in as ~~~~~@icloud.com

公開されるRailsアプリのurlを決める

https://nameless-atoll-34353.herokuapp.com/

上記のURLは僕が初めて作った個人アプリなんですが、これでいうところのnameless-atoll-34353の部分を自身で決めることができます。
heroku createだけでも問題はないのですが、僕みたいになんのアプリか分からない変なURLになるのでしっかり設定しておきましょう!

ターミナル
$heroku create 好きな文字列

pushしてデプロイ

以下のコマンドを打つだけです。楽勝です。
この時、gitのmasterで管理されているコードがpushされるので、brunch生やして作業している方は一旦masterにpushしましょう。

ターミナル
$git push heroku master

こんな感じで進んでいたら順調です。

ターミナル
Enumerating objects: 148, done.
Counting objects: 100% (148/148), done.
Delta compression using up to 4 threads
Compressing objects: 100% (125/125), done.
Writing objects: 100% (148/148), 39.65 KiB | 2.09 MiB/s, done.
Total 148 (delta 24), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Ruby app detected
remote: -----> Installing bundler 2.0.2
remote: -----> Removing BUNDLED WITH version in the Gemfile.lock
remote: -----> Compiling Ruby/Rails
remote: -----> Using Ruby version: ruby-2.6.6
remote: -----> Installing dependencies using bundler 2.0.2
remote:        Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
remote:        The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`.
remote:        Fetching gem metadata from https://rubygems.org/............

下記のコードの5行目に書かれているのが、今回デプロイしたアプリのURLです。
8行目のは全然関係ないです。僕はそれで悩んでました。

ターミナル
remote: -----> Compressing...
remote:        Done: 58.8M
remote: -----> Launching...
remote:        Released v4
remote:        https://nameless-atoll-34353.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/nameless-atoll-34353.git
 * [new branch]      master -> master

これで終わりと思いきや、、まだ本番環境にDBが作成されてないので、マイグレーションをしなきゃいけません。

それで終わりだよん。

4. 本番環境でマイグレーションをする

以下のコマンドでマイグレーションしてください。

ターミナル
$heroku run rails db:migrate

heroku runをつけるとrailsのコマンドをherokuを動かしているときにも使える様になります。

はい。終わりです。先ほどのURLを貼っつけて、正常に見れるか確認しましょう。

見れた方、お疲れ様でした。

見れてない方、調べても分からない方は僕のTwitterにでも相談しにきて下さい。
いつでも答えますよ?(@rurukasan0212 )

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

初投稿

これから書き方から学んで投稿していきます。
コードを書くときは自分のアウトプット用として、いずれ誰かの助けになるようなものまで書いていけるようになりたい。

更新頻度を落とさないように習慣化を目指します!

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

RubyでOAuth認証を使ってWeb APIへPOST HTTPリクエストの送信

RubyでHTTPリクエストを送信する

今回は一番ベーシックなnet/httpを使用したサンプルを挙げるが、RubyのHTTPクライアントは複数ある。

サンプルコード

リクエストパラメータについて、
GETの場合はパラメータをクエリストリングに含めるが、
POSTの場合はリクエストボディに含めるという点にてちょっとハマった。

後で書き直す。

require 'uri'
require 'net/http'
require 'openssl'
require 'base64'

## 1. Oauth認証によるアクセストークンの取得
# client_idと client_secretを使用
client_id = ENV['API_CLIENT_ID']
client_secret = ENV['API_CLIENT_SECRET']
credential = Base64.strict_encode64(client_id + ':' + client_secret)
uri = URI.parse('https://example.oauth2/token')

# アクセストークンを取得するHTTPリクエストの作成
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
# 以下は使用するWeb APIの仕様により異なる。
request_header = {
  'Authorization': "Basic #{credential}",
  'Content-Type': 'application/x-www-form-urlencoded'
}
request = Net::HTTP::Post.new(uri.request_uri, request_header)
request.body = 'grant_type=client_credentials'

# リクエストの送信・レスポンスからアクセストークンの取得
response = https.request(request)
response_body = JSON.parse(response.body)
access_token = response_body['access_token']

## 2. Web APIへHTTPリクエストの送信
# アクセストークンを使用するHTTPリクエストの作成
endpoint_uri = URI.parse('https://example.api.com' + '/v1/hoge/huga')
https = Net::HTTP.new(endpoint_uri.host, endpoint_uri.port)
https.use_ssl = true
# 以下は使用するWeb APIの仕様により異なる。
request_header = {
  'Authorization': "Bearer #{access_token}",
  'Content-Type': 'application/x-www-form-urlencoded',
  'Accept': 'application/json'
}
request = Net::HTTP::Post.new(endpoint_uri.request_uri, request_header)
data = { api_key: "abcd1234", name: "test", email: "example@foo.com" }
request.body = URI.encode_www_form(data)

# リクエストの送信・レスポンスの取得
response = https.request(request)

参考

利用するWeb APIの仕様やサンプルコードがあればそれもちゃんと読みましょう。

net/http以外のRubyでHTTPを扱うライブラリ

faraday

oauth2

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

SCSS記法チートシート

この内容について

この内容は、私が運営しているサイトに、より見やすく掲載しているので、よければそちらもご活用ください。
【Sass】SCSS記法チートシート

SCSS記法とは

SCSS記法とはSassの書き方の1つで、SassにはSCSS記法とSASS記法があり、SCSS記法の方がCSSと互換性があるので使われることが多い。
拡張子は「.scss」にする。

Sassとは

「Syntactically Awesome StyleSheet」の略で、CSSを効率的に記述できるように設計・開発されたRuby製のCSSメタ言語のこと

基本的な書き方

SCSS
div{
  p{
    color: red;
  }
}

ネスト構造系

ネスト構造

入れ子構造(HTMLのような形)に記述


See the Pen
Sass_scss_nest
by engineerhikaru (@engineerhikaru)
on CodePen.


親セレクタ参照

親セレクタの名称を参照し記述


See the Pen
Sass_scss_parent-reference
by engineerhikaru (@engineerhikaru)
on CodePen.


ネームスペースネスト

CSSでネームスペースで記述しているもの(font-familyなど)をネスト構造で記述


See the Pen
Sass_scss_namespace-nest
by engineerhikaru (@engineerhikaru)
on CodePen.


変数系

変数

よく使う値を変数でまとめる


See the Pen
Sass_scss_variable
by engineerhikaru (@engineerhikaru)
on CodePen.


配列変数

よく使う値を配列変数でまとめる


See the Pen
Sass_scss_array-variable
by engineerhikaru (@engineerhikaru)
on CodePen.


グループ変数

よく使うスタイルをまとめる


See the Pen
Sass_scss_group-variable
by engineerhikaru (@engineerhikaru)
on CodePen.


継承系

インポート

分割したSCSSファイルをインポートする

SCSS
// basic.scssというSCSSファイルを読み込む場合
@import "basic";

継承

他の場所で使用したスタイルを継承する


See the Pen
Sass_scss_extend
by engineerhikaru (@engineerhikaru)
on CodePen.


文法

条件分岐

条件によってスタイルを変更する


See the Pen
Sass_scss_if-else
by engineerhikaru (@engineerhikaru)
on CodePen.


繰り返し

スタイルを繰り返す


See the Pen
Sass_scss_for
by engineerhikaru (@engineerhikaru)
on CodePen.


繰り返し(配列変数)

配列変数を使用した繰り返し


See the Pen
Sass_scss_foreach
by engineerhikaru (@engineerhikaru)
on CodePen.


演算・色

四則演算

スタイルの中で演算


See the Pen
Sass_scss_calculation
by engineerhikaru (@engineerhikaru)
on CodePen.


文字列結合

スタイルの中で文字列結合


See the Pen
Sass_scss_concatenation
by engineerhikaru (@engineerhikaru)
on CodePen.


明度の調整

ベースの色の明度を調整


See the Pen
Sass_scss_brightness
by engineerhikaru (@engineerhikaru)
on CodePen.


彩度の調整

ベースの色の彩度を調整


See the Pen
vYNVVjr
by engineerhikaru (@engineerhikaru)
on CodePen.


透明度の調整

ベースの色の透明度を調整


See the Pen
Sass_scss_transparency
by engineerhikaru (@engineerhikaru)
on CodePen.


色相の調整

ベースの色の色相を調整


See the Pen
Sass_scss_hue
by engineerhikaru (@engineerhikaru)
on CodePen.


色の補色&反転

ベースの色の補色or反転にする


See the Pen
Sass_scss_inversion
by engineerhikaru (@engineerhikaru)
on CodePen.


色を混ぜる

ベースの色(2つ)を混ぜる


See the Pen
Sass_scss_color-mix
by engineerhikaru (@engineerhikaru)
on CodePen.


その他

コメントアウト

SCSS
// 1行コメント
/* 
  複数行コメント(コンパイル後も残る)
*/

引用符の付け外し

文字列の引用符("")の付け外し


See the Pen
Sass_scss_quote
by engineerhikaru (@engineerhikaru)
on CodePen.


大文字&小文字化

文字列の大文字or小文字化


See the Pen
Sass_scss_upper-case
by engineerhikaru (@engineerhikaru)
on CodePen.


絶対値を返す

数値の絶対値を返す


See the Pen
Sass_scss_abs
by engineerhikaru (@engineerhikaru)
on CodePen.


切り上げを返す

数値の切り上げを返す


See the Pen
Sass_scss_ceil
by engineerhikaru (@engineerhikaru)
on CodePen.


切り捨てを返す

数値の切り捨てを返す


See the Pen
Sass_scss_floor
by engineerhikaru (@engineerhikaru)
on CodePen.


四捨五入を返す

数値の四捨五入を返す


See the Pen
Sass_scss_round
by engineerhikaru (@engineerhikaru)
on CodePen.


この内容について

この内容は、私が運営しているサイトに、より見やすく掲載しているので、よければそちらもご活用ください。
【Sass】SCSS記法チートシート

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

Rubyでhash[:a][:b][:c] = 0 したら、キーが存在しなくても再帰的に拡張して欲しい

TL;DR

unixの mkdir -p みたいなことをRubyのハッシュでもやりたい

hash = Hash.new {|h,k| h[k] = h.class.new(&h.default_proc) }
hash[:a][:b][:c] = 'Good!!'
p hash # {:a=>{:b=>{:c=>"Good!!"}}}

解説

Hash.newについて

Hash.new は、ハッシュ自身とキーを受け取り、キーの内容が存在しない場合のデフォルト値をブロックで定義することができます。

hash1 = Hash.new { |h, k| 0 }

hash1[:a] = 100
p hash1[:a] # 100
p hash1[:b] # 0

上記は単純に、キーが見つからなかった場合は0を戻すハッシュを定義しています。 :a は設定されているのでハッシュの内容を参照し、 :b は存在しないのでブロックが実行され0が戻るという状態です。

ハッシュにデフォルト値を設定する

キーが見つからなかった場合のみブロックが実行されるという特性を利用すると、以下のようにハッシュ自体にデフォルト値を適用することができます。

hash2 = Hash.new { |h, k| h[k] = 0 }

hash2[:a] += 100
hash2[:b] += 200

p hash2 # {:a=>100, :b=>200}

以下は :a :b ともに未定義の状態から、 += を使って加算処理を行っていますが、 hash2[:a] hash2[:b] を評価した時点でデフォルト値の0がハッシュ自体に設定されるため、見事に100と200が設定された状態になります。

ハッシュをデフォルト値で拡張させる

さらに応用して、キーがネストしている状態でもハッシュを掘れるようにします。

hash3 = Hash.new { |h,k| h[k] = {} }

hash3[:a][:b] = 100
p hash3 # {:a=>{:b=>100}

hash3[:a]を参照した時点でブロックが実行され、hash3[:a] = {} が適用されたあとのハッシュが返ってきます。これに対して[:b] = 100 が実行されるので、最終的にネストされた状態のハッシュができあがります。

しかしこのままだと、ネストが3重になると失敗してしまいます。

hash3 = Hash.new { |h,k| h[k] = {} }

hash3[:a][:b][:c] = 100 # undefined method `[]=' for nil:NilClass (NoMethodError)

というのも、 hash3[:a] によってデフォルト値が設定されていますが、これはただの {} であり、これ自体にはデフォルト値の設定が定義されていません。

そのため、 hash3[:a][:b] はデフォルト値のないただのハッシュなので、 hash3[:a][:b][:c] を参照しようとするとエラーが発生してしまうわけです。

ハッシュをデフォルト値で再帰的に拡張させる

前項の hash3[:a][:b] はデフォルト値を持たない通常のハッシュになってしまいましたが、これにも同様のデフォルト値が設定されていてほしいものです。

安直に書くと以下になります。

hash4 = Hash.new { |h,k| h[k] = Hash.new { |h,k| h[k] = {} } }

hash4[:a][:b][:c] = 100
p hash4 # {:a=>{:b=>{:c=>100}}}

三重ネストでも対応することが出来ました。しかし当然四重ネストには対応できません。地獄です。

hash4 = Hash.new { |h,k| h[k] = Hash.new { |h,k| h[k] = {} } }

hash4[:a][:b][:c][:d] = 100 # undefined method `[]=' for nil:NilClass (NoMethodError)

ネストがどれだけ深かろうと、再帰的にしっかりとデフォルト値を定義したハッシュをデフォルト値にしたいわけです。

そこで使えるのが Hash#default_proc です。default_procはハッシュに設定されたデフォルト値定義のブロックをprocオブジェクトで取得できます。

proccallメソッドで実行できるので、以下を見るとイメージが湧くと思います。

hash5 = Hash.new { |k, v| 'default value'}

p hash5.default_proc.call(nil, nil) # "default value"

そしてブロックは、&proc の形で渡すことができるので、以下のように書くことができます。

hash6 = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
hash6[:a][:b][:c][:d] = 100

p hash6 # hash6[:a][:b][:c][:d] = 100

腹落ちしましたでしょうか?

hash6自分自身のデフォルト値の定義を適用したHashを、自分自身のデフォルト値 にしています。
これによって、ネストが何重になろうと、常にデフォルト値の定義が引き継がれるわけでした。

備考

書ききってから気づいたけど、同じような話を解説付きでしてる記事がチラホラあった。
まぁ自分の学んだ内容を整理するって意味で投稿しておきます。

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

【httpclient】でのリクエストからcontrollerまでの流れについて確認とリファクタリング

はじめに

以前、JQueryのautocomplete、ajax、そしてhttpclientを使いオートコンプリートを実装したが、内容についてぼんやりとしか把握できていなかった。リファクタリングを行いつつ、内容を確認していく。

まず、外部APIにアクセスしている部分は、クラスに切り出し、libディレクトリに入れる。
lib/api_suggest.rb

require 'httpclient'
require 'json'

class ApiSuggest
  API_KEY = Rails.application.credentials.api[:API_KEY]
  API_URI = Rails.application.credentials.api[:API_URI]

  def self.suggest(keyword, max_num)
    uri = API_URI
    headers = {
      Authorization: "Bearer #{API_KEY}",
    }
    params = {
      keyword: keyword,
      max_num: max_num,
    }

    client = HTTPClient.new
    req = client.get(uri, body: params, header: headers)
    req
  end
end

リファクタリング前は、

    client = HTTPClient.new
    req = client.get(uri, body: params, header: headers)
    res = JSON.parse(req.body)
    res

と、JSON.parse(req.body)を行っていたが、
リファクタリング後は、

req = client.get(uri, body: params, header: headers)

client.getした結果をであるreq部分をそのままコントローラーに返し、

コントローラー側では、
app/controllers/suggests_controller.rb

require 'api_suggest'
class SuggestsController < ApplicationController
  SUGGEST_MAX_COUNT = 5
  def search
    @suggests = ApiSuggest.suggest(params[:keyword], SUGGEST_MAX_COUNT)

    render body: @suggests.body, status: @suggests.code
  end
end

7行目の、renderで、

render body: @suggests.body, status: @suggests.code

各パラメータに入れる事でJSON.parseする必要がなくなった。

そして、そのパラメータが、
app/assets/javascripts/suggest.js

$("#form").autocomplete ({
  source: function (req, res) {
    $.ajax({
      url: '/suggest',
      type: 'GET',
      cache: false,
      dataType: "json",
      data: { keyword: req.term },
  n    success: function (data) {
        res(data);
      },
      error: function (xhr, ts, err) {
 n       res(xhr, ts, err);
      }
    });
  }
});

ajaxのsuccess以下に返されるという流れになっている。

全体の流れを確認

ajaxのオプションで指定している
url: '/suggest'にリクエストが送られ、
ルーティングで

get 'suggest',    to: 'suggests#search'

app/controllers/suggests_controller.rbのsearchメソッドが呼ばれ、

  def search
    @suggests = ApiSuggest.suggest(params[:keyword], SUGGEST_MAX_NUM)
    render body: @suggests.body, status: @suggests.code
  end

ApiSuggest.suggestによりhttpclientでの外部APIリクエストを介した結果、

render body: @suggests.body, status: @suggests.code
が返されて、

app/assets/javascripts/suggest.jsのajax

success: function (res) {
  resp(res);
},
error: function (xhr, ts, err) {
  resp(xhr, ts, err);
}

成功、失敗それぞれのケースに返される。
という流れ。

ajax部分について詳しく

render bodyのオプションが、戻り値の本体を返していて、
statusがステータスコード(200, 404, 500など)の外部APIの結果が返される。

ajax側でそれを受け取ると、
ajaxの中では、そのstatus codeを参照して、200系、300系を正常として判定して、success側を実行。

それ以外のstatus codeがきたらerror側を実行、
という処理を行っている。

以上。

終わりに。

最後まで読んで頂きありがとうございます:bow_tone1:
転職の為、未経験の状態からRailsを学習しております。正しい知識を着実に身に着け、実力のあるエンジニアになりたいと考えています。継続して投稿していく中で、その為のインプットも必然的に増え、成長に繋がるかと考えています。
今現在、初心者だからといって言い訳はできないですが、投稿の内容に間違っているところや、付け加えるべきところが多々あるかと思いますので、ご指摘頂けると幸いです。この記事を読んで下さりありがとうございました。

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

Ruby 正規表現

正規表現とは

・文字列の一部分を置換
・文字列の一部分を抽出
・文字列が制約を満たしているか調べる

 などの操作を行うための技術が正規表現です。

 正規表現のほとんどの記述はどの言語間でも共有可能です。

メソッドと使用例

subメソッド

文字列の指定した部分を別の文字列に置き換える

irb(main):001:0> str = "リンゴを食べる"
=> "リンゴを食べる"

irb(main):002:0> str.sub(/リンゴ/,"オレンジ")
=> "オレンジを食べる"

変数strに文字列 "リンゴを食べる" が代入されています。

次にstrに対し、subメソッドを使用し、第一引数にリンゴ、第二引数にオレンジを指定しています。

出力すると、リンゴを食べる → オレンジを食べるになっています。

このように第一引数に置き換えたい文字列を「 / (スラッシュ)」囲み、第2引数に変換後の文字列を指定します。

matchメソッド

文字列がメソッドの左の文字列に含まれているか否かをチェックする


irb(main):001:0> str = "Hello, World"
=> "Hello, World"

irb(main):002:0> str.match(/Hello/)
=> #<MatchData "Hello">

irb(main):003:0> str.match(/Good/)
=> nil

変数strに文字列 "Hello, World" が代入されています

次にstrに対し、matchメソッドを使用し、引数にHelloを指定しています

"Hello, world" には指定した "Hello" という文字列は含まれているので、MatchDataオブジェクトの返り値として指定した文字列 "Hello" が得られます。

"Good" は含まれていないので、返り値はnilになります。

matchメソッドもsubメソッドと同じように引数を「 / (スラッシュ)」で囲みます。

gsubメソッド

文字列の指定した部分を全て別の文字列に置き換える

irb(main):001:0> tel = '080-1234-5678'
=> "080-1234-5678"

irb(main):002:0> tel.sub(/-/,'')
=> "0801234-5678"

irb(main):003:0> tel.gsub(/-/,'')
=> "08012345678"

変数telには電話番号が代入されています。

次にsubメソッドでハイフンを空の文字列に置き換えることで取り除こうとしますが、最初のハイフンだけが置き換えられています。

指定した初めの文字列だけを置き換えるならsub,全て置き換えるならgsubを使います。

正規表現のメタ文字

メタ文字は、特殊な意味・機能を持った文字で、これを使用することで様々な制約が可能になります。

種類が多いので、パスワードの制約を例に挙げる中でいくつか紹介します。

irb(main):001:0> pw = 'Abcd1234'
=> "Abcd1234"

irb(main):002:0> pw.match(/[a-z\d]{8,10}/i)
=> #<MatchData "Abcd1234">

上記は、

・aからzの英字、数字のいずれかの文字
・8文字以上10文字以内
・文字は大小どちらでも可

という制約をかけています。

引数の中身を分解し、それぞれの文字の意味を説明していきます

/[a-z\d]{8,10}/i

↓ 

/[a-z\d]{8,10}/      i(スッラッシュの中身の文字列は大文字小文字どちらでも可)

[a-z\d]         {8,10}(直前の文字が8から10文字出現するものにマッチ)

[a-z]          \d (数字にマッチ)

[a-z] (aからzまでの文字いずれかにマッチ)

※今回はa-zに加え、数字も角括弧に囲まれているため、英数字いずれかにマッチする)

まとめ

種類 意味
[ ] 囲まれたいずれか1つの文字にマッチ
\d 数字にマッチ
{a,b} 直前の文字がa回以上b回以下出現するものにマッチ
i (オプション) 大文字・小文字を区別しない

基本的に紹介した2つのメソッドと正規表現のパターンを組み合わせることで様々な制約が実装できます。

パターンに関してはここに記したのは一例です。他にも正規表現を用いてできることはたくさんあります。

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

FontAwesomeの導入と使い方解説

今回はFontAwesomeの導入方法から表示させるまでについてを解説していきます。

FontAwesomeの導入

1.Gemfileに以下の記述を追記

gem "font-awesome-sass"
$ bundle install

2.application.scssに以下を記述。

@import "font-awesome-sprockets";
@import "font-awesome";

これで導入は完了です。

ビューで表示

iconヘルパーメソッドを使っていきます。
使い方の模範はこんな感じです。

icon('接頭辞名', 'アイコン名')

実際に使うとこんな感じです。

= icon('fab', 'facebook-square') #例

参考資料

接頭辞名とアイコン名については以下のサイトで調べて使いましょう!
https://fontawesome.com/

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

備忘録 Ruby 『p』と『puts』の違い

2020/05/17

Atcoderで競技プログラミングをしていたときに、
やらかしてしまったミスを備忘録として残しておく。

Atcoder168_B

出力に以下が表示されればOK

$ ruby Bmain.rb 
4 #入力
aaaaa #入力
aaaa... #出力

以下のようなコードを書いた。

K = gets.to_i
S = gets.chomp

if S.length <= K then
  p S
elsif S.length > K then
  p S[0..(K-1)]+"..."
end

出力
出力に""が表示されてしまっているためエラーとなる。

$ ruby Bmain.rb 
4 #入力
aaaaa #入力
"aaaa..." #出力

pをputsに変更

K = gets.to_i
S = gets.chomp


if S.length <= K then
  puts S
elsif S.length > K then
  puts S[0..(K-1)]+"..."
end

次は、""なしで表示された。

$ ruby Bmain.rb 
4 #入力
aaaaa #入力
aaaa... #出力

pはデバッグ用途で使用するためのものなのでわかりやすいように""をつけるとのこと。

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

Rubyの基礎2~わかりにくいところ復習~

メソッド

メソッドは使えるオブジェクトが決まっている。
eachメソッドの場合は配列オブジェクトや範囲オブジェクトにしか使えません。
また、eachメソッドを配列オブジェクトに使った場合の返り値は配列オブジェクトそのものです。

クラス

クラスとは、とあるオブジェクトの共通の属性とメソッドをまとめておく型のようなもの。
"Hello"と"こんにちは"はそれぞれ別のオブジェクトですが、文字を持つと言う点においては共通です。
この性質は予めクラスの性質として定義されているものなのです。
この型を予め用意しておけば、その肩に沿って効率的にオブジェクトを生成できます。

インスタンス

クラスから生まれたオブジェクトのことをインスタンスと言います。
オブジェクトから先に生まれることはなく、クラスからインスタンスというオブジェクトが生まれます。
属性と属性値とメソッドが入った状態でインスタンスが生成されます。
つまり、クラスで属性が定義されていて、具体的な属性値を持った状態でインスタンスが生成されます。

例えば文字列オブジェクトの "Hello" は Stringクラスで定義された属性=文字に、属性値="Hello"が入った状態、かつlengthメソッドやto_iメソッドなどのメソッドを持った状態でインスタンスが生成されます。

Rubyに予め定義されているクラス

Rubyには予め定義されたクラスがある。
文字列オブジェクトのStringクラス
配列オブジェクトのArrayクラス
数値オブジェクトのIntegerクラス
ハッシュオブジェクトのHashクラス

newメソッド

newメソッドは全てのクラスで定義しなくても使うことができます。
newメソッドを使うことによってインスタンスを生成できます。
返り値として利用したクラスのインスタンスを返します。
クラスメソッドである。なぜならインスタンスを生成するのはクラスが行うべきだから。

クラスメソッド

クラスメソッドはクラスメソッドを定義したクラス自身が利用できるものでクラスで共通の情報を使った処理に使います。
メソッド名の前にselfをつけます。

インスタンスメソッド

インスタンスメソッドは、インスタンスが利用できるメソッドです。インスタンスメソッドを定義したクラスのインスタンスに使用できる。インスタンスごとの個別の情報を使った処理に使えます。

クラスメソッドとインスタンスメソッドの違い
特徴   インスタンスメソッド クラスメソッド
定義方法 メソッド名の前に selfを付けない メソッド名の前にselfを付ける
用途      インスタンスごとの属性を用いるとき 属性が関係のない共通の処理をするとき
呼び出せるオブジェクト クラスのインスタンス クラス自身
呼び出し方      インスタンス名.メソッド名(引数) クラス名.メソッド名(引数)

クラスの変数

クラスでは共通の属性は変数を使って定義します。
その変数に代入した値が属性値です。
クラスに定義できる変数は、クラス変数とインスタンス変数があります。

クラス変数

クラス変数はクラス全体で使用できる変数です。つまり、クラスメソッド内でもインスタンスメソッド内でも使用することができます。クラスを通して値が共通の情報に使用する変数。

インスタンス変数

インスタンス変数は、共通の属性としてインスタンスに定義できる変数です。
値はそれぞれのインスタンスごとに設定できます。
各インスタンスでのみ使用ができます。
定義場所はインスタンスメソッド内で行います。
インスタンスメソッド内で定義されたインスタンス変数の値は、そのインスタンスメソッドを利用したインスタンスが持つインスタンス変数の値になる。

initializeメソッド

initializeメソッドはインスタンスを生成したと同時に実行したい処理を自動で実行できます。

クラスの継承

あるクラスに定義されたメソッドを別のクラスで利用できるようにすることを継承と言います。
継承したいクラスのことを親クラスといい継承する側のクラスのことを子クラスと言います
class 子クラス名 < 親クラス名 で親クラスを継承できます。

pメソッド

pメソッドはpの右側に書かれたオブジェクトやインスタンスを出力するものです。putsメソッドと似ていますがputsメソッドが返り値nilを返すのに対しpメソッドはそのオブジェクトやインスタンス自体を返り値として返します。

for文

while文と同じ繰り返しを行う文法です。

for num in 1..10 do
  puts num
end

変数numに1〜10を代入して出力しています。
inの後ろにあるオブジェクト順番に変数numに代入しています。
1..10は1~10という意味です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby と Python で解く AtCoder ABC168 A case式

はじめに

AtCoder Problems の Recommendation を利用して、過去の問題を解いています。
AtCoder さん、AtCoder Problems さん、ありがとうございます。

今回のお題

AtCoder Beginner Contest A - ∴ (Therefore)
Difficulty: 2

今回のテーマ、case式

Ruby

本戦では、if式で解いていますが、editorial

余談ですが,Ruby では case 文がこれにあたり,もっと高機能です.

と書かれていますので、caseで書いてみたいと思います。これまでにcaseを書いたことはないです
まずは、if

ruby.rb
n = gets.to_i
n %= 10
if n == 3
  puts "bon"
elsif n == 0 || n == 1 || n == 6 || n == 8
  puts "pon"
else
  puts "hon"
end
last.rb
n %= 10

10で割った余りで1の位を取得していますが、gets.chompとして文字列としn[-1]とすることもできます。

case.rb
n = gets.chomp
case n[-1]
when "3" then
  puts "bon"
when "0", "1", "6", "8" then
  puts "pon"
else
  puts "hon"
end

editorial の解説にある 高機能 とは,を用いて複数条件を指定することができるという意味です。

Python

python.py
n = int(input()) % 10
if n == 3:
    print("bon")
elif n in {0, 1, 6, 8}:
    print("pon")
else:
    print("hon")

pythonはcaseが無いようなので、似た感じにしてみました。
python のinは SQL のinに似ていますね。

まとめ

  • ABC 168 A を解いた
  • Ruby に詳しくなった
  • Python に詳しくなった

参照したサイト
Python に switch や case 文がないのはなぜですか?
pythonにswitchはないけれど

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