20200603のRubyに関する記事は19件です。

Rails Tutorial 第6版 学習まとめ 第3章

概要

この記事は私の知識をより確実なものにするためにRailsチュートリアル解説記事を書くことで理解を深め
勉強の一環としています。稀にとんでもない内容や間違えた内容が書いてあるかもしれませんので
ご了承ください。
できればそれとなく教えてくれますと幸いです・・・

出典
Railsチュートリアル

これからやること

TwitterライクなサンプルアプリSample_appの作成を通してRailsアプリの作成方法を総合的に学習していく
本章では新しいプロジェクトSample_appの作成から始める。

第2章まではかなり詳細まで記事を書いたが第3章以降
コードの量がかなり増えてくるのでRailsチュートリアルを読めばできるところは
省略して書くことにします…

セットアップ

初期設定

新規でSample_appを作成し、
Gemfileを更新する。今回も本番用のpg gemをインストールしたくないので--without productionは忘れずに。
新規アプリなのでGitリポジトリを初期化する。
READMEもここで書き換えておく。
READMEを書き換えたらとりあえずコミットしておく。
GithubのSample_app用リモートリポジトリも作成しておく。
リモートリポジトリを作成したらプッシュしておく
Cloud9環境の場合はdevelopment.rbを編集し、アプリをローカル起動できるようにしておく。
とりあえず2章と同じようにhello,world表示のコードだけ追加してherokuにもプッシュしておく。

演習

1.Githubのリポジトリのトップページのサイト下部にREADMEが自動表示されている。
もちろんファイルを開いて直接覗いてもいい
image.png
2.hello,world!が表示されているのが確認できる。
image.png
ここで豆知識
herokuにデプロイしたアプリのドメイン名はheroku domainsで確認できる。

静的ページ

開発の習慣として常にmasterブランチ上で作業するのではなく何かを実装するタイミングで都度トピックブランチを作成
して作業するのがいい習慣と言われている。そうすることで作業の分担がしやすい。作業のくくりが見えやすいなど
様々な利点がある。
癖付けに今回から都度トピックブランチを作って作業する

$ git checkout -b static-pages
静的ページの生成

さっそく静的ページ用のコントローラから作成していく

$ rails g controller StaticPages home help 

generateは省略形のgでも良い
他にも短縮形があり、そちらを覚えるのをお勧めする。

完全なコマンド 短縮形
$ rails server $ rails s
$ rails console $ rails c
$ rails generate $ rails g
$ rails test $ rails t
$ bundle install $ bundle

Railsチュートリアル第6版より
https://railstutorial.jp/chapters/static_pages?version=6.0#table-shortcuts

とりあえず今の段階でstatic-pagesブランチをリモートにプッシュしておく
-uオプションを使ってoriginをstatic-pagesのアップストリームに設定すると
以降はgit pushだけで同じプッシュができる。

generateコマンドでコントローラを自動生成するとroutes.rbファイルも自動更新される。
今回の場合generateでhomeアクションとhelpアクションを作成したので

routes.rb
Rails.application.routes.draw do
  get 'static_pages/home'
  get 'static_pages/help'
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  root "application#hello"
end

homeアクションとhelpアクションのルーティングルールが自動設定されている。
さっそくローカルサーバーを立ち上げstatic_pagesのhomeページを表示してみる。
image.png

RailsはURLを指定すると(今回は/static_pages/home)ルーターを参照し、
対応するコントローラのアクションを実行する。(StaticPagesコントローラのhomeアクション)
そのあとにそのアクションに対応するビューを出力する。
静的ページのコントローラでは都度内容が変わることはないので(ページの内容が同じ)アクションは空になっている。

演習

1.

$ rails g controller Foo bar baz

2.destroyも短縮形dが使える。

$ rails d controller Foo

静的なページの調整

現在の状態だと作成されたhomeページ、helpページはHTMLで完結しており、完全に静的なページ
つまりRailsの知識がなくても編集できるページになっているという状態。
ここで第2章のようにユーザーのデータを取得したり投稿のデータを取得したりしてその内容に応じて
表示内容を変える(動的)ような動作をするとRailsの知識(ERB)が必要になる。

テストから始める

最初のテスト

aboutページを追加する前にaboutページに対するテストを先行で書いてみる。
generateコマンドでhomeとhelpページに対するテストが自動生成されているので
まずはテストを実行して問題ないことを現時点で確認しておく

$ rails t

...

Finished in 6.708000s, 0.2982 runs/s, 0.2982 assertions/s.
2 runs, 2 assertions, 0 failures, 0 errors, 0 skips

Red

テスト駆動開発(TDD)のサイクルは
失敗するテスト(未実装の機能に対するテスト等)を書く→失敗(RED)
実際のアプリケーションコードを書いて先に書いたテストをパスさせる→成功(GREEN)
リファクタリング(REFACTOR)の3ステップ

これを踏まえてまだ作っていないAboutページのテストを書いてみる

static_pages_controller_test.rb
require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest

  ...

  test "should get about" do
    get static_pages_about_url
    assert_response :success
  end
end

このコードではstatic_pagesのaboutページにGETリクエストを送って
レスポンスコードが200 OK(success)になるという内容をテストしている。

もちろんまだAboutページを何も実装していないので期待通りエラーをはく

Green

先ほどのエラーメッセージをみてみる

Error:
StaticPagesControllerTest#test_should_get_about:
NameError: undefined local variable or method `static_pages_about_url' for #<StaticPagesControllerTest:0x000055b65cfc03b0>
    test/controllers/static_pages_controller_test.rb:15:in `block in <class:StaticPagesControllerTest>'

詳しく読み解くと
StaticPagesControllerTestのshould_get_aboutで
static_pages_about_urlなんてメソッドは定義されていないよ(AboutのURLがないよ)
と怒られている。

これはルーティングを設定していないから

さっそくルーティングを追加してみる。
routes.rbに
get 'static_pages/about'を追加する。
ルーティングを追加することでstatic_pages_about_urlというヘルパーが有効になる。

もういちどテストを流すと今度は

Error:
StaticPagesControllerTest#test_should_get_about:
AbstractController::ActionNotFound: The action 'about' could not be found for StaticPagesController
    test/controllers/static_pages_controller_test.rb:15:in `block in <class:StaticPagesControllerTest>'

これもシンプルなエラーで
aboutアクションが見つからないよと怒られている。
ルーティングを追加して、static_pagesコントローラのaboutアクションを参照するようにした結果である。

さっそくAboutアクションを追加してみる

  def about 
  end

これをstatic_pagesコントローラの中に書くだけ
アクションの中身はhomeやhelpと同じくまだ完全に静的ページなので空でOK

これでテストを流すと今度は

Error:
StaticPagesControllerTest#test_should_get_about:
ActionController::MissingExactTemplate: StaticPagesController#about is missing a template for request formats: text/html
    test/controllers/static_pages_controller_test.rb:15:in `block in <class:StaticPagesControllerTest>'

これはaboutテンプレート(ビュー)が見つからないよと怒られている。

これもビューを追加して対応する。
app/views/static_pages内にabout.html.erbを追加する。

この状態でテストは成功(GREEN)する

Finished in 0.976764s, 3.0714 runs/s, 3.0714 assertions/s.
3 runs, 3 assertions, 0 failures, 0 errors, 0 skips

少しだけ動的なページ

タイトルを動的に変更する。
勉強用にレイアウトを無効にしておく

$ mv app/views/layouts/application.html.erb layout_file

このコマンドでapplication.html.erbというレイアウトファイルの名前を一時的に変更し移動することで無効にしている。

先にタイトルのテストを書いておく
タイトルはページごとに変わればいいのでこのようなコードになる。

  test "should get home" do
    get static_pages_home_url
    assert_response :success
    assert_select "title", "Home | Ruby on Rails Tutorial Sample App"
  end

  test "should get help" do
    get static_pages_help_url
    assert_response :success
    assert_select "title", "Help | Ruby on Rails Tutorial Sample App"
  end

  test "should get about" do
    get static_pages_about_url
    assert_response :success
    assert_select "title", "About | Ruby on Rails Tutorial Sample App"
  end

titleタグを選択しその中身が一致することを確かめている。
もちろん未実装のためテストはRED

まずはhome,help,aboutページのビューを書き換える。

それぞれのページにタイトルを設定したのでテストはGREENになる。

Finished in 0.062407s, 48.0717 runs/s, 96.1433 assertions/s.
3 runs, 6 assertions, 0 failures, 0 errors, 0 skips

演習

1.ダブルクォーテーションで囲った部分(文字列)の中に#{}で変数を囲むとその変数を展開できる。
今回は変数の中にRuby on Rails Tutorial Sample Appという文字列を代入しているのでその文字列が展開される。
共通な部分は変数で代用して変更に柔軟に対応できるようにするのはどのプログラム言語でも変わらない基本事項。

  def setup
    @base_title = "Ruby on Rails Tutorial Sample App"
  end
  test "should get home" do
    get static_pages_home_url
    assert_response :success
    assert_select "title", "Home | #{@base_title}"
  end

  test "should get help" do
    get static_pages_help_url
    assert_response :success
    assert_select "title", "Help | #{@base_title}"
  end

  test "should get about" do
    get static_pages_about_url
    assert_response :success
    assert_select "title", "About | #{@base_title}"
  end

レイアウトと埋め込みRuby

現段階だとhome,help,aboutのどのページもHTML構造の大半(headなどの基本タグ)が重複している。
タイトルもRuby on Rails Tutorial Sample Appは共通。
こういった重複を取り除いてDRYすることが大切。

provideメソッドはビューで
provide(:シンボル,"文字列")といった指定をすることで
yieldでシンボルに結びつけた文字列を呼び出せる。
ビューでRubyのコードが使えるのは
ビューが埋め込みRuby[ERB(Embedded RuBy)]という形式のファイルでHTML内にRubyを埋め込めるようになっているから。
<% %>で囲むと中の文を実行するだけ
<%= %>で囲むと中の文を実行して結果がテンプレートに挿入されるという違いがある。

この仕組みを使ってタイトル部分を書き換えてみた結果がこちら

<% provide(:title,"Help") %>
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
  </head>

もちろんテストも通る。

このままだと共通な部分が残ってしまうのでさっそくリファクタリングしてみることにする。
まずは先ほど無効化したレイアウトファイルを有効化する

mv layout_file app/views/layouts/application.html.erb

そしてhome,help,aboutにそれぞれ個別に入れているtitleタグを丸ごとレイアウトファイルのタイトルタグと入れ替える。

application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title)%> | Ruby on Rails Tutorial Sample App</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>

yieldの部分には各ページのビューの中身がそのまま代入される。
つまり各ページを表示しようとしたときに表示されているのは
各ページのビューを読み込んだapplication.html.erbである。

あとはhtmlタグなどの余計なものが各ページのビューに残ってしまっていて、このままだとapplication.html.erbと
重複してしまうので不要な部分を削除し、各ページのビューはコンテンツだけにする。

help.html.erb
<% provide(:title,"Help") %>
<h1>Help</h1>
<p>
  Get help on the Ruby on Rails Tutorial at the
  <a href="https://railstutorial.jp/help">Rails Tutorial help page</a>.
  To get help on this sample app, see the
  <a href="https://railstutorial.jp/#ebook"><em>Ruby on Rails Tutorial</em>
  book</a>.
</p>
演習

1.先にContactのテストを書いておく(TDD)

static_pages_controller_test.rb
  test "should get contact" do
    get static_pages_contact_url
    assert_response :success
    assert_select "title", "Contact | #{@base_title}"
  end

あとはroutes.rbにcontactのルーティングを追加し、
static_pages_controllerにcontactアクションを追加し、
contactビューを作成すれば良い。

Finished in 1.044651s, 3.8290 runs/s, 7.6581 assertions/s.
4 runs, 8 assertions, 0 failures, 0 errors, 0 skips

テストもパスする。

ルーティングの設定

とりあえずデプロイするためにhello,worldを表示するhelloアクションをルートURLに設定していたが
今回homeページを作ったのでそちらに移す
root 'static_pages/home'

演習

1.

static_pages_controller_test.rb
  test "should get root" do
    get root_url
    assert_response :success
  end

2.Rubyは行頭に#をつけることでその行をコメントアウトできる
ちなみにWindowsはCTRL+/でその行をコメントアウトできる。
rootURLをコメントアウトする。# root 'static_pages#home'

Error:
StaticPagesControllerTest#test_should_get_root:
NameError: undefined local variable or method `root_url' for #<StaticPagesControllerTest:0x000055d85cb31200>
    test/controllers/static_pages_controller_test.rb:10:in `block in <class:StaticPagesControllerTest>'

root_urlメソッドが定義されていないとエラーが出た。

rootURLを設定したことでroot_urlヘルパーが使えるようになっていることがわかる。

本章のまとめ

3章の作業が一通り終わったので
コミットしておく
デプロイするときにはテストを走らせるとデプロイ後にバグ発見なんて言うめんどくさいことにならないのでいい。

←前の章へ

次の章へ→

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

【Rails】deviseでのセッションタイムアウト設定

deviseでのセッションタイムアウト設定

目次

  1. セッションタイムアウトを設定するメリット
  2. セッションタイムアウトを設定するデメリット
  3. deviseでのセッションタイムアウト設定

1. セッションタイムアウトを設定するメリット

  1. セッションの盗用などの不正行為の対策になり、安全にアプリケーションを運用することができる
  2. 利用ユーザーのステータスを判定することによって、サーバー側の負担を軽減させることができる

2. セッションタイムアウトを設定するデメリット

  1. 入力フォームなどで、一度中断をし、再開後に入力を行うことができないこと
  2. ログイン状態が切れる回数が多いと、ユーザーが再度ログインする必要があるので、アプリケーションの使い勝手が悪いと判断されてしまうこと

3. deviseでのセッションタイムアウト設定

3-1. Deviseのセッションタイムアウトを設定

以下の記述を入力しましょう。
(コメントアウトされているので、コメントを解除すればOK)

config/initializers/devise.rb
config.timeout_in = 30.minutes

3-2. Userモデルに「timeoutable」を設定

以下の記述を入力しましょう。

app/models/user.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,...省略...:timeoutable
end

※ テストを行う際は1分で設定することがおすすめです。

以上でdeviseでのセッションタイムアウト設定になります。

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

Kinx ライブラリ - Getopt

Kinx ライブラリ - Getopt

はじめに

「見た目は JavaScript、頭脳(中身)は Ruby、(安定感は AC/DC)」 でお届けしているスクリプト言語 Kinx。言語はライブラリが命。ということでライブラリの使い方編。

今回は Getopt です。SpecTest で内部的に実装して使っていたのですが、標準ライブラリのほうに移動させました。

ロングオプションにも対応しました(まだリリースしてませんが... リリースしました)。

Getopt - System.getopt

使い方

以下のように、while 文の条件式の場所にオプションの配列とオプション文字列、ロングオプション・オブジェクトを指定する。ロングオプション・オブジェクトは省略可能。

var opt, add, check;
while (opt = System.getopt($$, "a:df", { add: 'a', delete: 'd', help: null, "do-check": '=' })) {
    switch (opt.type) {
    case 'a':               // '--add' でも 'a' が返る。
        add = opt.arg;      // ':' 指定は引数があることを示す。
        System.println('-a with "%{add}"');
        break;
    case 'd':               // '--delete' でも 'd' が返る。
        System.println('-d');
        break;
    case 'f':               // '-f' で返る。
        System.println('-f');
        break;
    case 'help':            // '--help' で返る。
        System.println('--help');
        break;
    case 'do-check':        // '--do-check' で返る。
        check = opt.arg;    // '=' 指定は引数があることを示す。
        System.println('--do-check with "%{check}"');
        break;
    case '-':               // オプションではなかった場合、ここに来る。
        list.push(opt.arg);
        break;
    }
}

// オプション以外の表示
System.println("Program options: ", list);

オプション文字列の詳細

  • 引数有りを指定した場合、引数を指定しなかった時には ArgumentException 例外が送出される。
  • 引数が無いオプションの場合、同じオプション内に次のオプションを指定できる。例えば、-d -f-df と書いても良い。
  • 引数があるオプションの場合、次に文字が続いていれば引数とみなされる。例えば、-a ARG-aARG と書いてよい。
  • 上記 2 つを組み合わせると、-d -a ARG-da ARG とも -daARG とも書くことができる。

ロングオプションの詳細

  • ロングオプションでオプション文字を指定した場合、引数の有無もオプション文字の指定に従う。
  • 引数有りを指定した場合、引数を指定しなかった時には ArgumentException 例外が送出される。
  • ロングオプションの場合は --long-option=argument の形式で引数を指定する。また、ロングオプションの場合は空文字列の引数が許容される。

サンプルの実行

先ほどのサンプルを動作させると次のようになる。

$ ./kinx examples/option.kx -d -a arg
-d
-a with "arg"
Program options: ["examples/option.kx"]

$ ./kinx examples/option.kx -da arg
-d
-a with "arg"
Program options: ["examples/option.kx"]

$ ./kinx examples/option.kx -daarg
-d
-a with "arg"
Program options: ["examples/option.kx"]

$ ./kinx examples/option.kx --help something
--help
Program options: ["examples/option.kx", "something"]

$ ./kinx examples/option.kx --do-check=
--do-check with ""
Program options: ["examples/option.kx"]

$ ./kinx examples/option.kx --do-check=abc
--do-check with "abc"
Program options: ["examples/option.kx"]

$ ./kinx examples/option.kx -a
Uncaught exception: No one catch the exception.
ArgumentException: Needs an argument for -a
Stack Trace Information:
        at <main-block>(examples/option.kx:2)

$ ./kinx examples/option.kx --unknown
Uncaught exception: No one catch the exception.
ArgumentException: Unknown option: --unknown
Stack Trace Information:
        at <main-block>(examples/option.kx:2)

おわりに

オプション解析の方法も色々あって、getopt も歴史が古いですが今でも現役ですね。Most fitting in C programmers の観点では getopt は使いやすいんじゃないかな、と思います。

ヘルプを表示できるという意味では、boost::program_options も捨てがたい。まずは最低限のことができるという意味で System.getopt のサポートです。今後もっと便利なものが出てくるかもしれない(どこから?)。

ではまた、次回。

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

define_methodってどんなmethod?

define_methodってどんなmethod?

gemを読んでいたらdefine_methodなるメソッドが出てきたけど、
よくわからなかったので調べてみた。
直訳するとmethodを定義する。って名前のメソッド。
ますますわからない。。

ということで例をみてみます。

ruby.rb
NUMBERS = %w(zero one two three four five six seven eight nine)

NUMBERS.each_with_index do |word, num|
  define_method word do |i = nil|
    i ? num * i : num
  end
end

p two      #=> 2
p two(2)   #=> 4
p nine     #=> 9
p nine(3)  #=> 27

define_methodはmethodを動的に定義できるメソッドです
上記の例でもtwoやnineと言ったメソッドは直接定義したわけではないけれど
メソッドとして使えることができます。
これはdefine_methodによって動的にtwo,nineメソッドが定義されたからです。

ruby.rb
NUMBERS.each_with_index do |word, num|
  define_method word do |i = nil|
    i ? num * i : num
  end
end

define_methodの引数にwordが渡されています。
これが動的に定義されるメソッド名となります。
wordには["zero","one","two",..."nine"]という配列の要素が入っていきます。
なのでtwo,nineというメソッドが使えました。

そしてdefine_methodのブロック部分が動的に定義されるメソッドの処理内容となります。

ruby.rb
define_method word do |i = nil|
    i ? num * i : num
  end

内容としてはiが存在するときはi * numを返し、
存在しないときはnumを返すということですね。

そしてiは新たに定義されるメソッドの引数に当たっています。
最後に処理結果をもう一度見てみましょう。

p two      #=> 2 #引数がないのでnumを返す
p two(2)   #=> 4 #引数があるので 2 * 2 = 4
p nine     #=> 9 #引数がないのでnumを返す
p nine(3)  #=> 27 #引数があるので 9 * 3 = 27

define_methodの説明はここまでです。
お役に立てたら幸いです。

一人前のエンジニアになるまであと86日

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

Ruby ハッシュについて

前回のハッシュに関する記事

ハッシュ

ハッシュとは: キーと値の組み合わせでデータを管理するオブジェクトのこと

ハッシュを作成する場合は、以下のような構文を使います

{ キー1 => 値1, キー2 => 値2, キー3 => 値3 }

実際にハッシュを作成した例

{'food' => 'rice', 'fruit' => 'lemon'} 

要素の追加

ハッシュを作成した後から、新しいキーと値を追加したい場合、以下のような構文を使います。

ハッシュ[キー] = 値

(例)以下は新たにドリンクの種類を追加するコードです。

menu = { 'food' => 'rice', 'fruit' => 'lemon',  }

# ドリンクメニューを追加する
menu['drink'] = 'water'

puts menu #=> {"food" => "rice", "fruit" => "lemon", "drink" => "water"}

要素の上書き

既にキーが存在する場合、値が上書きされます。

menu = { 'food' => 'rice', 'fruit' => 'lemon',  }

# 値を上書きする
menu['food'] = 'pizza'

puts menu #=> {"food" => "pizza", "fruit" => "lemon"}

ハッシュを使った繰り返し処理

eachメソッドを使用すると、キーと値のセットを順番に取り出すことができます。

menu = { 'food' => 'rice', 'fruit' => 'lemon',  }

menu.each do |key, value|
  puts "#{key} : #{value}"
end

# => food : rice
#    fruit : lemon

ハッシュに each メソッドを使うときは変数に「キー」と「値」を指定します。

|変数|の変数はブロック引数といい、eachメソッドから渡されたハッシュの要素が入る。
ハッシュの「キー」が変数 key に、「値」が変数value に順番に代入されていきます。そして、ハッシュの要素の数だけブロック内で記述された処理が繰り返し実行された後、ブロックから抜け出し処理が終了します。

参考にした文献

プロを目指す人のためのRuby入門

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

中学2年が1週間で自分のアイディアをいるかいらないか投票できるTogmarks(トグマークス)作った

アイディアにいるかいらないか投票できるTogmarksというサイトを作りました。5月26日に作り始めて6月2日に公開しました。たった1週間しかかけていませんが前作ったQuaよりもいい出来だと思っています(機能の数は少ない)。今回も前と同じようによかった点と悩んだことを振り返ろうと思います。

紹介

トップページ

togmarks.png

素人が個人で1週間で作ったのですごくいいとは言えませんが青色をアクセントカラーにしてシンプルなデザインはそこそこ気に入っています。

投票画面

togmarksshow.png

タイトルと内容は気にしないでください(笑)公開して間もないため投稿がなく開発環境でseedでデータを作るしかなかったんです(泣)

他にもページはありますがどれもtopページと似ていてコメントすることがないので割愛します。

どうして作ったか

自分でアイディアを考えても「これ使われるのかな...人にしられてもいいから他の人の意見が聞きたいな...」と思ったことがよくあります。個人で趣味でやっている人は特にあるとおもいます’。そういうときにこのwebアプリを思いつきました。正直このwebアプリもいると思う人がいるのかわかりませんが投票してくれる人がいるなら自分も使ってみたいです。

今回の良かった点

①サイトマップやデータベース設計をしっかりしてから開発を行った・・・当たり前かもしれませんがQuaのときは一切そういうのをやらなかったので地味にしっかりとやったのは初めてでした。やはりこういうのは重要だなと感じました。
②必要な機能と欲しい機能をわけた・・・最初にそれをまとめておくと次に何をやるべきかがすぐわかるのでスムーズになります。
③cssのコードを少なくできた・・・じつは最も自分的には良かった点です。cssはスマホ用・PC用のデザインと分けるとどうしても長くなりがちですが今回は同じクラスを何回も使うことで最小限似できたと思います。
④技術面で悩んだことが一回もなかった・・・機能とデザインをシンプルにしたからだと思います。

悩んだこと

①お金・・・ロゴやイラスト台です。中2が払える訳ありません。最終的にはなしでいくことにしました。ただファビコンはなしでは寂しいのでいつの日か無料のやつ探して設定しようと思います。
②使われるか・・・誰しもが思うことですがこれ使う人いるの...という不安感です。ただこれを乗り切らないとどんなものもできません。

最後に

このwebアプリを開発中に最も驚いたのは開発スピードです。これが普通なのかもしれませんが基本機能だけだと1週間で作れてしまうんだなと思いました。
最初にしか触れていませんがこのアプリは1週間で作ったと思えばなかなかなのかな?自分的にはそこそこだと思います。
今回2つ目のアプリですが誰も登録しない...ということだけは避けたいです。みなさんお願いします。

https://www.togmarks.com/

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

Rails 5.2/6.0 で MessageEncryptor を使うときは初期化タイミングに気を付けよう

Rails 5.2 から ActiveSupport::MessageEncryptor のデフォルト暗号方式が aes-256-cbc から aes-256-gcm に変更となった。しかし、期化タイミングによっては意図しない暗号方式を使うことになる場合があるため紹介する。

Rails 5.2

以下のバージョンで確認:

  • Ruby 2.6.5
  • Rails 5.2.4.3

デフォルト

まず rails console でデフォルト暗号方式を確認する。

irb> encryptor = ActiveSupport::MessageEncryptor.new 'key'
=> #<ActiveSupport::MessageEncryptor:0x0000561c2eae8940 @secret="key", @sign_secret=nil, @cipher="aes-256-gcm", @aead_mode=true, @verifier=ActiveSupport::MessageEncryptor::NullVerifier, @serializer=Marshal, @options={}, @rotations=[]>
irb> encryptor.instance_variable_get '@cipher'
=> "aes-256-gcm"

確かに aes-256-gcm であることがわかる。

実例

実際のアプリケーションでは、なんらかのモデルに持たせておいて利用することもあるだろう。

app/models/some_model.rb
class SomeModel < ApplicationRecord
  class << self
    attr_reader :encryptor

    def set_key(key)
      @encryptor = ActiveSupport::MessageEncryptor.new key
    end
  end

  set_key 'x' * 32
end

これも同じように確認してみる。

irb> SomeModel.encryptor.instance_variable_get '@cipher'
=> "aes-256-gcm"

問題なさそうに見える。

問題例

ところが、 MessageEncryptor の初期化タイミングが早すぎると、異なる暗号方式になってしまう。例えば after_initialize コールバック内で SomeModel 定数が参照されていると、そのタイミングでオートロードされ、 MessageEncryptor が生成されることとなる。

config/application.rb
class Application < Rails::Application
  config.load_defaults 5.2
  config.after_initialize do
    SomeModel
  end
end
irb> SomeModel.encryptor.instance_variable_get '@cipher'
=> "aes-256-cbc"

aes-256-gcm ではなく aes-256-cbc となってしまった。

原因

ことの問題は Rails.application.config.active_support.use_authenticated_message_encryption の設定反映のタイミングにある。この設定値は過去バージョンとの互換性のために設けられており、 false に設定することでデフォルト暗号方式を aes-256-cbc に戻すことができる。本設定値は Rails 5.2 としてはデフォルト true ではあるが、この設定値が config.after_initialize 実行時点ではまだ反映されていないようなのだ。従ってこのタイミングで初期化してしまうと、 MessageEncryptor 自身のデフォルトである aes-256-cbc となってしまう。

該当コードはこのあたりである。

https://github.com/rails/rails/blob/v5.2.4.3/activesupport/lib/active_support/message_encryptor.rb#L88

解決例

初期化が早すぎるのが問題なので、実際の利用タイミングまで遅らせることが考えられる。

app/models/some_model2.rb
class SomeModel2 < ApplicationRecord
  class << self
    def set_key(key)
      @key = key
    end

    def encryptor
      @encryptor ||= ActiveSupport::MessageEncryptor.new @key
    end
  end

  set_key 'x' * 32
end
config/application.rb
config.after_initialize do
  SomeModel2
end

これでほとんどの場合 aes-256-gcm が利用できる。

irb> SomeModel2.encryptor.instance_variable_get '@cipher'
=> "aes-256-gcm"

ただし、 MessageEncryptor を利用したいタイミング自体が use_authenticated_message_encryption の設定反映前である場合は、これでも解決とはならない。そのときは MessageEncryptor.newcipher: オプションを明示するのが良いだろう。

Rails 6

以下のバージョンで改めて調査したが、同じ状況になるようだ。

  • Ruby 2.7.1p83
  • Rails 6.0.3.1

5.2 と少し事情が違うのは、デフォルトのオートローダーが Zeitwerk となり config/initializers/*.rb で各モデルをオートロードするのが非推奨となった点だ。このため config/initializers/*.rb でうっかりモデルを参照してしまった場合は、警告メッセージにて検出が可能となっている。しかしながら本記事での例のように、 config.after_initialize では警告はないようだ。

Rails では各ファイルは必要に応じてロードされるが、その順番はときに分かりづらいこともある。ロード順によって問題が発生することもあるので気を付けよう。

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

Rails gem deviseって?

Rails gem devise について

Ruby on Rails を学習中、deviseというユーザーも新規登録、ログイン機能などがgemをインストールするだけで簡単に作れちゃうというもの。非常に優れものです。

投稿主の備忘録もかねて手順を簡単に紹介していきます。

deviseをインストールする

Gemfile
gem 'devise'

ここで注意すべきなのはdeviceではなくdevise

私がプログラミング超初心者だった時このスペルミスでエラーが出てしまいました。

ここでgemをインストールするのでコマンドラインで$ bundle installします

また、devise用のインストールコマンドがあるので実行します。

ターミナル
$ rails g devise install

ここまででdeviseのインストールが完了します。

deviseのモデルを作成する

マイグレーションファイルに記載した情報を基にデータベースの型、制約を設定していきます。

ターミナル
$ rails g devise user

普段Railsアプリケーションでモデルを作成していく時には $ rails g model userというコマンドを打てばモデルの作成ができますがここではdeviseコマンドでモデルを作成します。

このコマンドを実行後model/user.rbとuser用のマイグレーションファイルが作成されていれば成功です。

ユーザーのマイグレーションファイルには

20200603_devise_create_users.rb
class DeviseCreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :name,               null: false
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      # 〜省略〜
    end

    add_index :users, :name, unique: true
    # usersの情報全てに検索がかけれるようにadd_indexを貼る

nameカラム、eーmailカラムなどが設定され、それぞれnull: falseで制約がかけられておりnullであればユーザーの新規登録でエラー表示されるようになります。

user.rbにはバリデーションもかけておきましょう。

user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable,  :validatable

  validates :name, presence: true, uniqueness: true
   # nameカラムが空でないこと、重複したnameは登録できないようにバリデーションをかけている

end

バリデーションには様々な制約を設けることができ、もっと知りたいという方はこちらから!
https://qiita.com/h1kita/items/772b81a1cc066e67930e

これでデータベースと紐づくマイグレーションファイルとモデルの設定が完了しました。

ターミナル
$ rails db:migrate

マイグレーションファイルをマイグレートしておきましょう。

ビューファイルの準備

ビューファイルもdeviseコマンド一発で作成できます。

ターミナル
$ rails g devise:views users

これで簡単ではありますがユーザーの新規登録とログイン機能の実装ができました。

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

【git/基本編】これだけは押さえてほしいgitの仕組み&コマンド完全攻略版

git basic tutorial.png

今回やること

gitコマンドを使えることは個人開発でもチーム開発でも必須です

特にチーム開発ではgitを使う機会が非常に多くなります

かなり基本的な仕組みとコマンドのみなので実際に使って身につけていただけたらと思います

git(基本編)

gitの仕組み

①ワークツリー

下記コマンドでワークツリーでの変更をステージに記録していきます

$ git add

②ステージ

下記コマンドでステージからローカルリポジトリにコミット(記録を保存)することができます

$ git commit
$ git commit -m ""
# メッセージ付きで記録(変更)を保存
$ git commit -v 
# 変更内容を確認してからcommitが可能

③ローカルリポジトリ

下記コマンドでリモートリポジトリにプッシュ(送る)ことができます

$ git push リモート名 ブランチ名

④リモートリポジトリ

リモートリポジトリはGitHubなどのアプリケーションなどのファイル・ディレクトリの履歴を管理するネット上の場所のことです

リモートリポジトリにファイルなどをアップロードすることでバージョンごとに履歴を管理することができるため、開発において不本意な変更があった際に簡単に戻したいバージョンに戻すことができます

もっと詳しい仕組みを知ってちゃんとgitを使いこなしたい方は下の記事をご覧ください

スクリーンショット 2020-06-03 17.17.44.png

ブランチとは

ブランチとは現在のコミットを指しているただのポインタのことです

それでは以下のgitコマンドでブランチを新規追加していきましょう

$ git branch ブランチ名
$ git branch feature
# 作成したブランチに移動
$ git checkout feature

上の2つのコマンドを同時に行うコマンドが下のコマンドです

$ git checkout -b feature

もっと詳しくブランチについて知ってから他のgitコマンドを身につけたい方は下の記事をご覧ください

スクリーンショット 2020-06-03 17.19.01.png

開発の流れ

1. クローンを作る(コピーを作成する)

リモートリポジトリ(GitHub等)のファイルがワークツリーとローカルリポジトリ(.git directoryが)にコピーされる

$ git clone <repository url>

2. ブランチを作る

$ git checkout -b feature

3. プッシュする

$ git push リモート名 ブランチ名

4. 修正する

プロジェクトに変更を加える

5. 完了後にコミットする

$ git add .

コミットしていきます

$ git commit -m "First commit"

6. プッシュする

$ git push

7. Pull requestを送る

GitHub上でプルリクエストを送ります

以上がgitでの開発の流れですが説明はかなり省略しています

もっと詳しく知って実際の開発に役立てたい方は下の記事をご覧ください

スクリーンショット 2020-06-03 17.19.12.png

新規プロジェクトをGitHubで扱う

①git init

$ git init

Git に必要なファイル(.git)がダウンロードされます

②リモートリポジトリ(github)を新規で登録する

GitHubをブラウザで開き新規リポジトリを作成してください

その後下のコマンドを打ち込みます

$ git remote add origin githubのURL

③プッシュする

$ git push -u origin master

かなり端折って紹介したのでもっとわかりやすい説明は下の記事からご覧ください

スクリーンショット 2020-06-03 17.19.24.png

開発で役立つコマンド

リモートから情報を取得する

リモートリポジトリから情報を取得するには以下の2種類の方法があります

  1. フェッチ(fetch)
  2. プル(pull)

①フェッチ

以下のgitコマンドでリモートリポジトリから情報を取得できます

$ git fetch リモート名

専用に作成されたブランチのワークツリー には以下のgitコマンドを使って反映していきます

$ git merge origin/master

②プル

pullコマンドはこのコマンド1つで以下2つの役割を持ちます

$ git fetch origin master
$ git merge origin/master

実際のプルコマンドは以下です

$ git pull リモート名 ブランチ名

簡単なフェッチとプルの使い方だけだとわかりにくいと思うので下の記事もご覧ください

スクリーンショット 2020-06-03 17.19.34.png

リモート名の変更/削除

リモート名の変更

$ git remote rename 旧リモート名 新リモート名
$ git remote rename sample_app test_app

リモートの削除

$ git remote rm リモート名
$ git remote rm test_app

もっと詳しく知りたい方は下の記事が役立つと思います

スクリーンショット 2020-06-03 17.19.50.png

rebaseコマンドの使い方

*基本的な使い方

$ git rebase -I HEAD~数

修正したいコミットをpickからeditに変更して保存/ファイルを閉じます(コミット削除:pick~文を削除、コミット並び順変更:pick~文を並び替える)

$ git commit --amend

エディタが立ち上がるのでコミットメッセージを変更してください

$ git rebase -continue

*ブランチの変更を別ブランチに取り込みたい場合

$ git rebase master
$ git merge feature
$ git rebase -I HEAD~数

修正したいコミットをpickからsquashに変更して保存/ファイルを閉じます

*コミットを分割したい場合

$ git rebase -I HEAD~数

分割したいコミットをpickからeditに変更して保存/ファイルを閉じます

$ git reset HEAD^

別々にgit addでステージに上げてgit commitでコミットします

$ git add .
$ git commit -m "First commit"
$ git add .
$ git commit -m "Second commit"
$ git rebase —continue

以上がrebaseの使い方となりますがこれだけだとイメージが湧かないと思います

rebaseは開発において非常に重要な箇所なので是非詳しい説明は下の記事でご覧ください

スクリーンショット 2020-06-03 17.20.01.png

ここまででgitの基本を押さえられると思います

まだまだgitコマンドはありますが、まずは今回紹介した基礎を身につけて実際に使ってみてください

開発をする際に必ず役立つと思います

今回の元記事は下の記事になります

スクリーンショット 2020-06-03 17.20.43.png

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

【git/基本編】これだけわかれば100%オッケーなgitの仕組み&コマンド完全攻略版

git basic tutorial.png

今回やること

gitコマンドを使えることは個人開発でもチーム開発でも必須です

特にチーム開発ではgitを使う機会が非常に多くなります

かなり基本的な仕組みとコマンドのみなので実際に使って身につけていただけたらと思います

git(基本編)

gitの仕組み

①ワークツリー

下記コマンドでワークツリーでの変更をステージに記録していきます

$ git add

②ステージ

下記コマンドでステージからローカルリポジトリにコミット(記録を保存)することができます

$ git commit
$ git commit -m ""
# メッセージ付きで記録(変更)を保存
$ git commit -v 
# 変更内容を確認してからcommitが可能

③ローカルリポジトリ

下記コマンドでリモートリポジトリにプッシュ(送る)ことができます

$ git push リモート名 ブランチ名

④リモートリポジトリ

リモートリポジトリはGitHubなどのアプリケーションなどのファイル・ディレクトリの履歴を管理するネット上の場所のことです

リモートリポジトリにファイルなどをアップロードすることでバージョンごとに履歴を管理することができるため、開発において不本意な変更があった際に簡単に戻したいバージョンに戻すことができます

もっと詳しい仕組みを知ってちゃんとgitを使いこなしたい方は下の記事をご覧ください

スクリーンショット 2020-06-03 17.17.44.png

ブランチとは

ブランチとは現在のコミットを指しているただのポインタのことです

それでは以下のgitコマンドでブランチを新規追加していきましょう

$ git branch ブランチ名
$ git branch feature
# 作成したブランチに移動
$ git checkout feature

上の2つのコマンドを同時に行うコマンドが下のコマンドです

$ git checkout -b feature

もっと詳しくブランチについて知ってから他のgitコマンドを身につけたい方は下の記事をご覧ください

スクリーンショット 2020-06-03 17.19.01.png

開発の流れ

1. クローンを作る(コピーを作成する)

リモートリポジトリ(GitHub等)のファイルがワークツリーとローカルリポジトリ(.git directoryが)にコピーされる

$ git clone <repository url>

2. ブランチを作る

$ git checkout -b feature

3. プッシュする

$ git push リモート名 ブランチ名

4. 修正する

プロジェクトに変更を加える

5. 完了後にコミットする

$ git add .

コミットしていきます

$ git commit -m "First commit"

6. プッシュする

$ git push

7. Pull requestを送る

GitHub上でプルリクエストを送ります

以上がgitでの開発の流れですが説明はかなり省略しています

もっと詳しく知って実際の開発に役立てたい方は下の記事をご覧ください

スクリーンショット 2020-06-03 17.19.12.png

新規プロジェクトをGitHubで扱う

①git init

$ git init

Git に必要なファイル(.git)がダウンロードされます

②リモートリポジトリ(github)を新規で登録する

GitHubをブラウザで開き新規リポジトリを作成してください

その後下のコマンドを打ち込みます

$ git remote add origin githubのURL

③プッシュする

$ git push -u origin master

かなり端折って紹介したのでもっとわかりやすい説明は下の記事からご覧ください

スクリーンショット 2020-06-03 17.19.24.png

開発で役立つコマンド

リモートから情報を取得する

リモートリポジトリから情報を取得するには以下の2種類の方法があります

  1. フェッチ(fetch)
  2. プル(pull)

①フェッチ

以下のgitコマンドでリモートリポジトリから情報を取得できます

$ git fetch リモート名

専用に作成されたブランチのワークツリー には以下のgitコマンドを使って反映していきます

$ git merge origin/master

②プル

pullコマンドはこのコマンド1つで以下2つの役割を持ちます

$ git fetch origin master
$ git merge origin/master

実際のプルコマンドは以下です

$ git pull リモート名 ブランチ名

簡単なフェッチとプルの使い方だけだとわかりにくいと思うので下の記事もご覧ください

スクリーンショット 2020-06-03 17.19.34.png

リモート名の変更/削除

リモート名の変更

$ git remote rename 旧リモート名 新リモート名
$ git remote rename sample_app test_app

リモートの削除

$ git remote rm リモート名
$ git remote rm test_app

もっと詳しく知りたい方は下の記事が役立つと思います

スクリーンショット 2020-06-03 17.19.50.png

rebaseコマンドの使い方

*基本的な使い方

$ git rebase -I HEAD~数

修正したいコミットをpickからeditに変更して保存/ファイルを閉じます(コミット削除:pick~文を削除、コミット並び順変更:pick~文を並び替える)

$ git commit --amend

エディタが立ち上がるのでコミットメッセージを変更してください

$ git rebase -continue

*ブランチの変更を別ブランチに取り込みたい場合

$ git rebase master
$ git merge feature
$ git rebase -I HEAD~数

修正したいコミットをpickからsquashに変更して保存/ファイルを閉じます

*コミットを分割したい場合

$ git rebase -I HEAD~数

分割したいコミットをpickからeditに変更して保存/ファイルを閉じます

$ git reset HEAD^

別々にgit addでステージに上げてgit commitでコミットします

$ git add .
$ git commit -m "First commit"
$ git add .
$ git commit -m "Second commit"
$ git rebase —continue

以上がrebaseの使い方となりますがこれだけだとイメージが湧かないと思います

rebaseは開発において非常に重要な箇所なので是非詳しい説明は下の記事でご覧ください

スクリーンショット 2020-06-03 17.20.01.png

ここまででgitの基本を押さえられると思います

まだまだgitコマンドはありますが、まずは今回紹介した基礎を身につけて実際に使ってみてください

開発をする際に必ず役立つと思います

今回の元記事は下の記事になります

スクリーンショット 2020-06-03 17.20.43.png

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

Rails tutorialでMySQLを使う方法

rails tutorialも2週目に入りsqliteでは無く、今後を考えmysqlを使いたいと考えた。

rails new アプリケーション名 --database=mysql

上記を使用することでmysqlが使用できるとのことだがエラーが発生。
下記を実行しろと言われるのでそのまま従う。
gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/'
rails sを使用するとmysqlにエラーがあるよと言われる。bundle installすると同じエラーが発生してしまう。

結論から言うと、下記コマンドを順に実施することで解決した。
sudo apt-get install libmariadb-dev
sudo apt-get install libmysqlclient-dev
sudo yum install mysql-devel'
gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/'

新しいパッケージを入れるためには、その元となる「-dev」なんとかdevというものを事前にインストールしておく必要があるらしい。このgem install するときの元となるデータがなかったためエラーになったみたいだ。

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

Rails Herokuデプロイ手順

プログラミング初学者のため訂正がありましたらご指摘ください。
gitをインストールしている前提です。

自身の環境

  • Ruby 2.5.1
  • Ruby on Rails 5.2.4.1
  • MySQL (gem 'mysql2', '>= 0.4.4', '< 0.6.0')

デプロイの流れ

  1. The Heroku CLIの設定
  2. Herokuにログイン
  3. Herokuにデプロイ

Herokuとは

HerokuとはWebアプリケーションを簡単に全世界に公開できるクラウドプラットフォームです。

参考)HEROKU とは

以下のURLからHerokuのユーザー登録を行います。ユーザー登録は無料です。

https://signup.heroku.com/jp

1. The Heroku CLIの設定

The Heroku CLIをインストールすることで、Herokuのコマンドが使えるようになります。

下記のリンクからOSを指定してダウンロードしてインストールを完了させてください。

https://devcenter.heroku.com/articles/heroku-cli

2. Herokuにログイン

The Heroku CLIをインストールしたので、ターミナル上でHerokuのコマンドが使えるようになりました。

早速ターミナルからHerokuにログインしましょう。

Herokuへアップロードしたいアプリのディレクトリへ移動し、「heroku loginコマンド」を実行してください。

loginコマンド実行後、herokuに登録したメールアドレスとパスワードの入力が必要です。

$ cd app # appの部分を自分の作ったアプリ名にします
$ heroku login # herokuにログインする
Enter your Heroku credentials:
Email:

メールアドレスとパスワードの入力が完了すると以下のように表示されます。

Logged in as 入力したメールアドレス

3. Herokuにデプロイ

HerokuではPostgreSQLデータベースを使います。

なので、PostgreSQLをインストールしていきます。

以下のコマンドをターミナルで実行します。(既にインストールされている方はインストールしなくて大丈夫です。)

$ brew install postgresql

インストールが完了したら、本番 (production) 環境にpg gemをインストールしてRailsがPostgreSQLと通信できるようにします。

以下のコードをGemfileの最下部に追加してください。

Gemfile.
group :production do
  gem 'pg'
end

pg gemは本番用のgemでローカル環境にはインストールしないようにします。その場合、bundle installに--without productionを追加します。このフラグを追加することで、pg gemはローカル環境には反映されないようになります。それでは以下のコマンドを実行します。

$ bundle install --without production

bundle installの本番環境用

次に「heroku create アプリ名」コマンドでheroku上にアプリケーションを作成します。 以下のコマンドを実行します。

$ heroku create

上記のようにアプリ名を入力しないと自動で名前をつけてくれます。
一度登録した名前は使えないので注意してください

上記のコマンドを実行すると、以下のような結果が表示されます。

Creating app... done, ⬢ app(アプリ名)
https://app(アプリ名).herokuapp.com/ | https://git.heroku.com/app(アプリ名).git

https://~~.herokuapp.com/が上記のコマンドで作成されたサブドメインです。 この時点でブラウザに表示可能ですが、今はまだ何もありません。デプロイしてWebページを表示させましょう。

RailsアプリケーションをHerokuにデプロイするには、まずGitを使ってHerokuにリポジトリをプッシュします。

$ git add .
$ git commit -m "initial commit"
$ git push heroku master

上手く行くと、下記のようにremote: Verifying deploy... done.と表示されます。

.
.
.
remote: Verifying deploy... done.
To https://git.heroku.com/app(アプリ名).git
 * [new branch]   master -> master

次に以下コマンドでmigrationを実行します。ローカル環境で行なっていたrails db:migrateのコマンドを本番環境でも行うというイメージです。

$ heroku run rails db:migrate

上記のコマンドを実行したら、以下のコマンドを実行してWebページを表示させましょう。

$ heroku open

以上です。

参考記事

https://qiita.com/kazukimatsumoto/items/a0daa7281a3948701c39
https://qiita.com/NaokiIshimura/items/eee473675d624a17310f

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

[Rails]フォームのすべての値をワンクリックで初期化する(helperメソッド定義+JavaScript)

はじめに

様々な検索条件を付けられる検索フォームを実装している中で、検索条件をワンクリックでリセットできる方法がないかと試行錯誤しました。

結果、下記の方法で実装できたのでまとめます。

環境

  • Ruby2.5.1
  • Rails5.2.4

手順

概要を簡単に説明すると、
1. ヘルパーメソッドにリセットボタンタグを生成するメソッドを定義
2. ビューでそれを呼び出す
3. チェックボックスをjsでクリアする処理を書く
という3本でお送りする感じです

1. ヘルパーメソッドの定義

どのファイルでもいいですが、今回はhelpers/application.rbに定義します。

helpers/application.rb
module ApplicationHelper
  def reset_tag(value = "Reset form", options = {})
    options = options.stringify_keys
    tag :input, { type: "reset", value: value }.update(options)
  end
end

2. ビューファイルで呼び出し

search.html.haml
%div
  = reset_tag 'クリア', id: 'js_clear_btn'
%div
  = f.submit '完了'

本来Railsにreset_tagはありませんが、ヘルパーメソッドで定義したので、この書き方で呼び出せます。

CSSもで調整してこんな感じに↓
スクリーンショット 2020-06-03 13.53.06.png

3. チェックボックスをJavaScriptでクリアする記述

私の場合は、リセットボタンだとチェックボックスをクリア(チェックを外す)ことができなかったので、そこはJavaScript書きました。

コードは環境に大きく依存してしまうので、割愛します。

結果

f923d6ccbb11ae2bb0c6d320371bc226.gif
こんな感じで、text_fieldもnumber_fieldも、selectもcheckboxもすべて初期化するボタンを作成できました!

参考

フォームを初期化するボタンをRailsで使う

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

macにrailsがインストールできない

この記事について

プログラミングの勉強をしています。
勉強の過程で得た知識を、忘れないようまとめておくのと共に、誰かの助けになればと思います。

「rails -v」が上手くいかない!

(base) hoge@MacBook-Pro ~ % rails -v
Rails is not currently installed on this system. To get the latest version, simply type:

    $ sudo gem install rails

You can then rerun your "rails" command.

調べた通りにrailsをインストールしたのに、rails -vを何度実行してもこのエラーが出てしまいます。

対処法

rbenv rehash

このコマンドを実行し、再度rails -vを実行すると

(base) hoge@MacBook-Pro ~ % rails -v
Rails 6.0.3.1

上手くいきました!!

参考

https://qiita.com/amuyikam/items/313bc89c1de320a4257e
https://github.com/railsgirls-jp/coach.info/issues/32

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

【Rails】Geocoding APIを用いて高精度で緯度経度を算出し、Google Mapに表示する方法

目標

ユーザーが登録した住所をマップの中心に表示し、マーカーを立てる。
ezgif.com-video-to-gif (1).gif

開発環境

・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina

前提

下記実装済み。

Slim導入
ログイン機能実装
Google Map表示

gem 'geocoder'だけでは精度が低い(番地指定が出来ない地域がある)為、
Geocoding APIを使用して高精度で住所から緯度経度を特定出来る様に実装していきます。

Geocoding API有効化

1.下記リンクにアクセス

Google Cloud Platform

2. 「APIの概要に移動」をクリック

スクリーンショット 2020-06-03 10.01.36.png

3.「ライブラリ」をクリック

スクリーンショット 2020-06-03 10.01.41.png

4.検索フォームに「geo」と入力し、「Geocoding API」をクリック

スクリーンショット 2020-06-03 10.02.08.png

5.「有効にする」をクリック

スクリーンショット 2020-06-03 10.02.13.png

6.赤枠で囲われている箇所をクリック

スクリーンショット 2020-06-03 10.02.31.png

7.プルダウンメニューが表示されるので、「全てのGoogle Maps API」をクリック

スクリーンショット 2020-06-03 10.04.02.png

8.「認証情報」をクリック

スクリーンショット 2020-06-03 10.12.39.png

9.「APIキーの名前」をクリック

スクリーンショット 2020-06-03 10.12.46.png

10.認証情報の設定をする

①APIの制限
キーを制限を選択し、プルダウンメニューからGeocoding APIを選択する。

Maps JavaScript APIと、Geocoding APIが選択されている事を確認して、保存をクリック

スクリーンショット 2020-06-03 10.13.14.png

11.APIが2個になっているかを確認

APIを追加した事でAPIキーが変更されるという事は無いので、これで完了。

スクリーンショット 2020-06-03 10.13.25.png

実装

1.Gemを導入

Gemfile
gem 'gon'
gem 'geocoder'

gem 'gon'
➡︎ コントローラーで定義したインスタンス変数をビューのJavaScript内で使用出来る様にする。

gem 'geocoder'
➡︎ 住所から緯度経度を算出する。

ターミナル
$ bundle

2.geocorderの設定ファイルを作成し、編集

ターミナル
$ touch config/initializers/geocoder.rb
geocoder.rb
# 追記
Geocoder.configure(
  lookup: :google,
  api_key: ENV['GOOGLE_MAP_API']
)

これでGeocoding APIを使用する事ができ、緯度経度の算出が高精度で行えます。

3.カラムを追加

ターミナル
$ rails g migration AddColumnsToUsers address:string latitude:float longitude:float
add_columns_to_users.rb
class AddColumnsToUsers < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :address, :string
    add_column :users, :latitude, :float
    add_column :users, :longitude, :float
  end
end
ターミナル
$ rails db:migrate

4.モデルを編集

user.rb
  # 追記
  geocoded_by :address
  after_validation :geocode

geocoded_by :address
➡︎ addressカラムを基準に緯度経度を算出する。

after_validation :geocode
➡︎ 住所変更時に緯度経度も変更する。

5.コントローラーを編集

application_controller.rbを編集

ストロングパラメーターに「address」を追加します。

application_controller.rb
def configure_permitted_parameters
  devise_parameter_sanitizer.permit(:sign_up, keys: [:email, :name, :address])
end

users_controller.rbを編集

users_controller.rb
def show
  @user = User.find(params[:id])
  gon.user = @user # 追記
end

6.ビューを編集

application.html.slimを編集

gonを読み込みます。
CSSとJavaScriptより先に読み込んでいる事に注意して下さい。

application.html.slim
doctype html
html
  head
    title
      | Bookers2
    = csrf_meta_tags
    = csp_meta_tag
    = include_gon # 追記
    = stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload'
    = javascript_include_tag 'application', 'data-turbolinks-track': 'reload'

②新規会員登録画面に住所入力フォームを追加

resistrations/new.html.slim
= f.label :address, '住所'
br
= f.text_field :address, class: 'form-control'
br

③マップを編集

users/show.html.erb
#map style='height: 500px; width: 500px;'

- google_api = "https://maps.googleapis.com/maps/api/js?key=#{ ENV['GOOGLE_MAP_API'] }&callback=initMap".html_safe
script{ async src=google_api }

javascript:

  let map;

  function initMap() {
    geocoder = new google.maps.Geocoder()

    map = new google.maps.Map(document.getElementById('map'), {
      // コントローラーで定義した変数から緯度経度を呼び出し、マップの中心に表示
      center: {
        lat: gon.user.latitude,
        lng: gon.user.longitude
      },
      zoom: 12,
    });

    marker = new google.maps.Marker({
      // コントローラーで定義した変数から緯度経度を呼び出し、マーカーを立てる
      position: {
        lat: gon.user.latitude,
        lng: gon.user.longitude
      },
      map: map
    });
  }

注意

turbolinksをオフにしないと地図が切り替わらないので、必ずオフにしましょう。
「turbolinksをオフにする方法」につきましては後日記事にしたいと思います。

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

学んだイディオム

||=を使った自己代入

x ||= Aのコードを見たら、「変数Xがnilまたはfalseなら、AをXに代入」と解釈する

number = nil
number ||= 10
number #=> 10

number = 20
number ||= 10
number #=> 20

n += 1 がn=n+1と展開できるのと同じ要領で

number ||= 10
number = number || 10
#同じ意味になる。

!!を使った真偽値の型変換

!は否定の演算子

 !Aと書いた場合
 Aが真 -> false
 false または nil -> true

!true    #=> false
!!true   #=> true

!!7      #=> true
!!false  #=> false
!!nil    #=> false

使用例

def title_exists?
  #データベースなどからタイトルを探す(なければnil)
  title = find_title
  if title
    true
  else
    false
  end
end
def title_exists?
  !!find_title
end

参考文献
プロを目指す人のためのRuby入門

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

シンボルについて詳しく

シンボルを作成する上での注意点

エラーが出る書き方
#識別子として無効な文字列(数字で始まる、ハイフン、スペースを含む文字列)を使うとエラーが発生
:12345        #=>SyntaxError
:ruby-is-fun  #=>Nameerror
:ruby is fun  #=>SyntaxError
:()           #=>SyntaxError

#シングルクオートで囲むとシンボルとして有効
:'12345'        #=>"12345"
:'ruby-is-fun'  #=>"ruby-is-fun"
:'ruby is fun'  #=>"ruby is fun"
:'()'           #=>"()"
シンボルの中で式展開
#ダブルクオートを使う
name = 'Alice'
:"#{name.upcase}" #=> :ALICE

シンボルと文字列

文字列とシンボルは別物なので、互換性はない。しかし、文字列をシンボルに変換するメソッド、シンボルを文字列にするメソッドはある。

string = 'apple'
sypbol = :apple
string == symbol #=> false

#to_symメソッド:文字列をシンボルに変換
string.to_sym           #=> :apple 
string.to_sym == symbol #=> true

#to_sメソッド:シンボルを文字列に変換
symbol.to_s           #=> "apple" 
symbol.to_s == string #=> true  

参考文献
プロを目指す人のためのRuby入門

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

シンボルについて学習したこと

シンボルを作成する上での注意点

エラーが出る書き方
#識別子として無効な文字列(数字で始まる、ハイフン、スペースを含む文字列)を使うとエラーが発生
:5678             #=>SyntaxError
:rails-is-easy    #=>Nameerror
:rails is easy    #=>SyntaxError
:()               #=>SyntaxError

#シングルクオートで囲むとシンボルとして有効
:'5678'           #=>"5678"
:'rails-is-easy'  #=>"rails-is-easy"
:'rails is easy'  #=>"rails is easy"
:'()'             #=>"()"
シンボルの中で式展開
#ダブルクオートを使う
title = 'Taro'
:"#{title.upcase}" #=> :TARO

シンボルと文字列

文字列とシンボルは別物なので、互換性はない。しかし、文字列をシンボルに変換するメソッド、シンボルを文字列にするメソッドはある。

string = 'ruby'
sypbol = :ruby
string == symbol #=> false

#to_symメソッド:文字列をシンボルに変換
string.to_sym           #=> :ruby 
string.to_sym == symbol #=> true

#to_sメソッド:シンボルを文字列に変換
symbol.to_s           #=> "ruby" 
symbol.to_s == string #=> true  

参考文献
プロを目指す人のためのRuby入門

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

AWS Cloud9の環境構築 Rubyを最新の安定版にアップデートする

Cloud9の環境でプリインストールされている「RVM」を使っています。

現在のRubyの最新の安定版のバージョンを確認する

公式サイトで確認できます。
Rubyのダウンロードページ

2020/6/3時点で最新の安定版は2.7.1でした。

Cloud9の環境でインストールされているRubyのバージョンを確認する

listコマンドでインストールされている(切り替えることができる)Rubyのバージョンの一覧を表示します。
rvm list

デフォルトで入っているバージョンが2.7.1ではなかったので追加でインストールします。

RVMでインストール可能なRubyのバージョンの一覧を表示する

rvm list known
インストール可能なRubyのバージョンの一覧が表示されます。

[ ]で囲まれた部分はバージョンを指定するときに省略できる部分です。
MRI の一覧にインストールしたいRubyのバージョン「2.7」が含まれていませんでした。この場合、RVMの更新が必要です。
AWS Cloud9でRVMのアップデートをする - Qiita

メモ:
MRI (Matz’ Ruby Implementation)は最も一般的なRubyの処理系。

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

バージョン2.7をインストールする場合は以下のようにコマンドを入力します。
rvm install 2.7

処理が終わったらインストールができたか確認します。
rvm list
でインストールされているRubyのバージョンの一覧を表示します。

インストール完了です。

rubyコマンドでも現在のバージョンを確認できます。
ruby -v

バージョンを細かく指定してRubyをインストールする

書き方はゆるく指定するときと同じです。
バージョン2.3.1をインストールする場合は以下のようにコマンドを入力します。
rvm install 2.3.1
エンターキーを押すとインストールが開始されます。

インストールできたか確認します。
rvm list
2.3.1が追加されたことが確認できます。
image.png

記号の意味

=> - current(現在使用中のRubyのバージョン)
=* - current && default(現在使用中かつデフォルトのバージョン)
* - default(デフォルトのバージョン)

使用中のRubyのバージョンを切り替える

rvm use <バージョン>

例えば2.7.0を使用するには以下のコマンドを実行します。
rvm use 2.7.0

切り替わったかどうかの確認はrvm listです。
現在使用中のバージョンは「=>」か「=*」で選択されます。

rubyコマンドでも現在のバージョンを確認できます。
ruby -v

デフォルトで使うRubyのバージョンを設定する

2.7.0をデフォルトに設定する場合のコマンド
rvm --default use 2.7.0

rvm list で確認

「*」が付いているのがデフォルトの印。

インストールしたRubyを削除する

rvm remove <version>

削除するバージョンを入力してコマンドを実行します。
rvm remove 2.3.8

処理が終わったら
rvm ls
で一覧から消えていれば、削除されたことが確認できます。

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