- 投稿日:2020-06-03T23:56:45+09:00
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が自動表示されている。
もちろんファイルを開いて直接覗いてもいい
2.hello,world!が表示されているのが確認できる。
ここで豆知識
herokuにデプロイしたアプリのドメイン名はheroku domains
で確認できる。静的ページ
開発の習慣として常にmasterブランチ上で作業するのではなく何かを実装するタイミングで都度トピックブランチを作成
して作業するのがいい習慣と言われている。そうすることで作業の分担がしやすい。作業のくくりが見えやすいなど
様々な利点がある。
癖付けに今回から都度トピックブランチを作って作業する$ git checkout -b static-pages静的ページの生成
さっそく静的ページ用のコントローラから作成していく
$ rails g controller StaticPages home helpgenerateは省略形の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.rbRails.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" endhomeアクションとhelpアクションのルーティングルールが自動設定されている。
さっそくローカルサーバーを立ち上げstatic_pagesのhomeページを表示してみる。
RailsはURLを指定すると(今回は/static_pages/home)ルーターを参照し、
対応するコントローラのアクションを実行する。(StaticPagesコントローラのhomeアクション)
そのあとにそのアクションに対応するビューを出力する。
静的ページのコントローラでは都度内容が変わることはないので(ページの内容が同じ)アクションは空になっている。演習
1.
$ rails g controller Foo bar baz2.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 skipsRed
テスト駆動開発(TDD)のサイクルは
失敗するテスト(未実装の機能に対するテスト等)を書く→失敗(RED)
実際のアプリケーションコードを書いて先に書いたテストをパスさせる→成功(GREEN)
リファクタリング(REFACTOR)の3ステップこれを踏まえてまだ作っていないAboutページのテストを書いてみる
static_pages_controller_test.rbrequire '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" endtitleタグを選択しその中身が一致することを確かめている。
もちろん未実装のためテストは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.rbtest "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.rbtest "should get root" do get root_url assert_response :success end2.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章の作業が一通り終わったので
コミットしておく
デプロイするときにはテストを走らせるとデプロイ後にバグ発見なんて言うめんどくさいことにならないのでいい。
- 投稿日:2020-06-03T21:27:16+09:00
【Rails】deviseでのセッションタイムアウト設定
deviseでのセッションタイムアウト設定
目次
- セッションタイムアウトを設定するメリット
- セッションタイムアウトを設定するデメリット
- deviseでのセッションタイムアウト設定
1. セッションタイムアウトを設定するメリット
- セッションの盗用などの不正行為の対策になり、安全にアプリケーションを運用することができる
- 利用ユーザーのステータスを判定することによって、サーバー側の負担を軽減させることができる
2. セッションタイムアウトを設定するデメリット
- 入力フォームなどで、一度中断をし、再開後に入力を行うことができないこと
- ログイン状態が切れる回数が多いと、ユーザーが再度ログインする必要があるので、アプリケーションの使い勝手が悪いと判断されてしまうこと
3. deviseでのセッションタイムアウト設定
3-1. Deviseのセッションタイムアウトを設定
以下の記述を入力しましょう。
(コメントアウトされているので、コメントを解除すればOK)config/initializers/devise.rbconfig.timeout_in = 30.minutes3-2. Userモデルに「timeoutable」を設定
以下の記述を入力しましょう。
app/models/user.rbclass User < ApplicationRecord devise :database_authenticatable, :registerable,...省略...:timeoutable end※ テストを行う際は1分で設定することがおすすめです。
以上でdeviseでのセッションタイムアウト設定になります。
- 投稿日:2020-06-03T21:21:04+09:00
Kinx ライブラリ - Getopt
Kinx ライブラリ - Getopt
はじめに
「見た目は JavaScript、頭脳(中身)は Ruby、(安定感は AC/DC)」 でお届けしているスクリプト言語 Kinx。言語はライブラリが命。ということでライブラリの使い方編。
今回は Getopt です。SpecTest で内部的に実装して使っていたのですが、標準ライブラリのほうに移動させました。
- 参考
- 最初の動機 ... スクリプト言語 KINX(ご紹介)
- 個別記事へのリンクは全てここに集約してあります。
- リポジトリ ... https://github.com/Kray-G/kinx
- Pull Request 等お待ちしております。
ロングオプションにも対応しました(
まだリリースしてませんが...リリースしました)。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
のサポートです。今後もっと便利なものが出てくるかもしれない(どこから?)。ではまた、次回。
- 投稿日:2020-06-03T21:00:23+09:00
define_methodってどんなmethod?
define_methodってどんなmethod?
gemを読んでいたらdefine_methodなるメソッドが出てきたけど、
よくわからなかったので調べてみた。
直訳するとmethodを定義する。って名前のメソッド。
ますますわからない。。ということで例をみてみます。
ruby.rbNUMBERS = %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) #=> 27define_methodはmethodを動的に定義できるメソッドです
上記の例でもtwoやnineと言ったメソッドは直接定義したわけではないけれど
メソッドとして使えることができます。
これはdefine_methodによって動的にtwo,nineメソッドが定義されたからです。ruby.rbNUMBERS.each_with_index do |word, num| define_method word do |i = nil| i ? num * i : num end enddefine_methodの引数にwordが渡されています。
これが動的に定義されるメソッド名となります。
wordには["zero","one","two",..."nine"]という配列の要素が入っていきます。
なのでtwo,nineというメソッドが使えました。そしてdefine_methodのブロック部分が動的に定義されるメソッドの処理内容となります。
ruby.rbdefine_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 = 27define_methodの説明はここまでです。
お役に立てたら幸いです。一人前のエンジニアになるまであと86日
- 投稿日:2020-06-03T20:14:20+09:00
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 に順番に代入されていきます。そして、ハッシュの要素の数だけブロック内で記述された処理が繰り返し実行された後、ブロックから抜け出し処理が終了します。参考にした文献
- 投稿日:2020-06-03T19:11:49+09:00
中学2年が1週間で自分のアイディアをいるかいらないか投票できるTogmarks(トグマークス)作った
アイディアにいるかいらないか投票できるTogmarksというサイトを作りました。5月26日に作り始めて6月2日に公開しました。たった1週間しかかけていませんが前作ったQuaよりもいい出来だと思っています(機能の数は少ない)。今回も前と同じようによかった点と悩んだことを振り返ろうと思います。
紹介
トップページ
素人が個人で1週間で作ったのですごくいいとは言えませんが青色をアクセントカラーにしてシンプルなデザインはそこそこ気に入っています。
投票画面
タイトルと内容は気にしないでください(笑)公開して間もないため投稿がなく開発環境でseedでデータを作るしかなかったんです(泣)
他にもページはありますがどれもtopページと似ていてコメントすることがないので割愛します。
どうして作ったか
自分でアイディアを考えても「これ使われるのかな...人にしられてもいいから他の人の意見が聞きたいな...」と思ったことがよくあります。個人で趣味でやっている人は特にあるとおもいます’。そういうときにこのwebアプリを思いつきました。正直このwebアプリもいると思う人がいるのかわかりませんが投票してくれる人がいるなら自分も使ってみたいです。
今回の良かった点
①サイトマップやデータベース設計をしっかりしてから開発を行った・・・当たり前かもしれませんがQuaのときは一切そういうのをやらなかったので地味にしっかりとやったのは初めてでした。やはりこういうのは重要だなと感じました。
②必要な機能と欲しい機能をわけた・・・最初にそれをまとめておくと次に何をやるべきかがすぐわかるのでスムーズになります。
③cssのコードを少なくできた・・・じつは最も自分的には良かった点です。cssはスマホ用・PC用のデザインと分けるとどうしても長くなりがちですが今回は同じクラスを何回も使うことで最小限似できたと思います。
④技術面で悩んだことが一回もなかった・・・機能とデザインをシンプルにしたからだと思います。悩んだこと
①お金・・・ロゴやイラスト台です。中2が払える訳ありません。最終的にはなしでいくことにしました。ただファビコンはなしでは寂しいのでいつの日か無料のやつ探して設定しようと思います。
②使われるか・・・誰しもが思うことですがこれ使う人いるの...という不安感です。ただこれを乗り切らないとどんなものもできません。最後に
このwebアプリを開発中に最も驚いたのは開発スピードです。これが普通なのかもしれませんが基本機能だけだと1週間で作れてしまうんだなと思いました。
最初にしか触れていませんがこのアプリは1週間で作ったと思えばなかなかなのかな?自分的にはそこそこだと思います。
今回2つ目のアプリですが誰も登録しない...ということだけは避けたいです。みなさんお願いします。
- 投稿日:2020-06-03T18:26:08+09:00
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.rbclass 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.rbclass Application < Rails::Application config.load_defaults 5.2 config.after_initialize do SomeModel end endirb> 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
となってしまう。該当コードはこのあたりである。
解決例
初期化が早すぎるのが問題なので、実際の利用タイミングまで遅らせることが考えられる。
app/models/some_model2.rbclass SomeModel2 < ApplicationRecord class << self def set_key(key) @key = key end def encryptor @encryptor ||= ActiveSupport::MessageEncryptor.new @key end end set_key 'x' * 32 endconfig/application.rbconfig.after_initialize do SomeModel2 endこれでほとんどの場合
aes-256-gcm
が利用できる。irb> SomeModel2.encryptor.instance_variable_get '@cipher' => "aes-256-gcm"ただし、
MessageEncryptor
を利用したいタイミング自体がuse_authenticated_message_encryption
の設定反映前である場合は、これでも解決とはならない。そのときはMessageEncryptor.new
にcipher:
オプションを明示するのが良いだろう。Rails 6
以下のバージョンで改めて調査したが、同じ状況になるようだ。
- Ruby 2.7.1p83
- Rails 6.0.3.1
5.2 と少し事情が違うのは、デフォルトのオートローダーが Zeitwerk となり
config/initializers/*.rb
で各モデルをオートロードするのが非推奨となった点だ。このためconfig/initializers/*.rb
でうっかりモデルを参照してしまった場合は、警告メッセージにて検出が可能となっている。しかしながら本記事での例のように、config.after_initialize
では警告はないようだ。Rails では各ファイルは必要に応じてロードされるが、その順番はときに分かりづらいこともある。ロード順によって問題が発生することもあるので気を付けよう。
- 投稿日:2020-06-03T18:03:15+09:00
Rails gem deviseって?
Rails gem devise について
Ruby on Rails を学習中、deviseというユーザーも新規登録、ログイン機能などがgemをインストールするだけで簡単に作れちゃうというもの。非常に優れものです。
投稿主の備忘録もかねて手順を簡単に紹介していきます。
deviseをインストールする
Gemfilegem '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.rbclass 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.rbclass 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これで簡単ではありますがユーザーの新規登録とログイン機能の実装ができました。
- 投稿日:2020-06-03T17:45:47+09:00
【git/基本編】これだけは押さえてほしいgitの仕組み&コマンド完全攻略版
今回やること
gitコマンドを使えることは個人開発でもチーム開発でも必須です
特にチーム開発ではgitを使う機会が非常に多くなります
かなり基本的な仕組みとコマンドのみなので実際に使って身につけていただけたらと思います
git(基本編)
gitの仕組み
①ワークツリー
下記コマンドでワークツリーでの変更をステージに記録していきます
$ git add②ステージ
下記コマンドでステージからローカルリポジトリにコミット(記録を保存)することができます
$ git commit$ git commit -m "" # メッセージ付きで記録(変更)を保存$ git commit -v # 変更内容を確認してからcommitが可能③ローカルリポジトリ
下記コマンドでリモートリポジトリにプッシュ(送る)ことができます
$ git push リモート名 ブランチ名④リモートリポジトリ
リモートリポジトリはGitHubなどのアプリケーションなどのファイル・ディレクトリの履歴を管理するネット上の場所のことです
リモートリポジトリにファイルなどをアップロードすることでバージョンごとに履歴を管理することができるため、開発において不本意な変更があった際に簡単に戻したいバージョンに戻すことができます
もっと詳しい仕組みを知ってちゃんとgitを使いこなしたい方は下の記事をご覧ください
ブランチとは
ブランチとは現在のコミットを指しているただのポインタのことです
それでは以下のgitコマンドでブランチを新規追加していきましょう
$ git branch ブランチ名$ git branch feature # 作成したブランチに移動$ git checkout feature上の2つのコマンドを同時に行うコマンドが下のコマンドです
$ git checkout -b featureもっと詳しくブランチについて知ってから他のgitコマンドを身につけたい方は下の記事をご覧ください
開発の流れ
1. クローンを作る(コピーを作成する)
リモートリポジトリ(GitHub等)のファイルがワークツリーとローカルリポジトリ(.git directoryが)にコピーされる
$ git clone <repository url>2. ブランチを作る
$ git checkout -b feature3. プッシュする
$ git push リモート名 ブランチ名4. 修正する
プロジェクトに変更を加える
5. 完了後にコミットする
$ git add .コミットしていきます
$ git commit -m "First commit"6. プッシュする
$ git push7. Pull requestを送る
GitHub上でプルリクエストを送ります
以上がgitでの開発の流れですが説明はかなり省略しています
もっと詳しく知って実際の開発に役立てたい方は下の記事をご覧ください
新規プロジェクトをGitHubで扱う
①git init
$ git initGit に必要なファイル(.git)がダウンロードされます
②リモートリポジトリ(github)を新規で登録する
GitHubをブラウザで開き新規リポジトリを作成してください
その後下のコマンドを打ち込みます
$ git remote add origin githubのURL③プッシュする
$ git push -u origin masterかなり端折って紹介したのでもっとわかりやすい説明は下の記事からご覧ください
開発で役立つコマンド
リモートから情報を取得する
リモートリポジトリから情報を取得するには以下の2種類の方法があります
- フェッチ(fetch)
- プル(pull)
①フェッチ
以下のgitコマンドでリモートリポジトリから情報を取得できます
$ git fetch リモート名専用に作成されたブランチのワークツリー には以下のgitコマンドを使って反映していきます
$ git merge origin/master②プル
pullコマンドはこのコマンド1つで以下2つの役割を持ちます
$ git fetch origin master $ git merge origin/master実際のプルコマンドは以下です
$ git pull リモート名 ブランチ名簡単なフェッチとプルの使い方だけだとわかりにくいと思うので下の記事もご覧ください
リモート名の変更/削除
リモート名の変更
$ git remote rename 旧リモート名 新リモート名 $ git remote rename sample_app test_appリモートの削除
$ git remote rm リモート名 $ git remote rm test_appもっと詳しく知りたい方は下の記事が役立つと思います
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は開発において非常に重要な箇所なので是非詳しい説明は下の記事でご覧ください
ここまででgitの基本を押さえられると思います
まだまだgitコマンドはありますが、まずは今回紹介した基礎を身につけて実際に使ってみてください
開発をする際に必ず役立つと思います
今回の元記事は下の記事になります
- 投稿日:2020-06-03T17:45:47+09:00
【git/基本編】これだけわかれば100%オッケーなgitの仕組み&コマンド完全攻略版
今回やること
gitコマンドを使えることは個人開発でもチーム開発でも必須です
特にチーム開発ではgitを使う機会が非常に多くなります
かなり基本的な仕組みとコマンドのみなので実際に使って身につけていただけたらと思います
git(基本編)
gitの仕組み
①ワークツリー
下記コマンドでワークツリーでの変更をステージに記録していきます
$ git add②ステージ
下記コマンドでステージからローカルリポジトリにコミット(記録を保存)することができます
$ git commit$ git commit -m "" # メッセージ付きで記録(変更)を保存$ git commit -v # 変更内容を確認してからcommitが可能③ローカルリポジトリ
下記コマンドでリモートリポジトリにプッシュ(送る)ことができます
$ git push リモート名 ブランチ名④リモートリポジトリ
リモートリポジトリはGitHubなどのアプリケーションなどのファイル・ディレクトリの履歴を管理するネット上の場所のことです
リモートリポジトリにファイルなどをアップロードすることでバージョンごとに履歴を管理することができるため、開発において不本意な変更があった際に簡単に戻したいバージョンに戻すことができます
もっと詳しい仕組みを知ってちゃんとgitを使いこなしたい方は下の記事をご覧ください
ブランチとは
ブランチとは現在のコミットを指しているただのポインタのことです
それでは以下のgitコマンドでブランチを新規追加していきましょう
$ git branch ブランチ名$ git branch feature # 作成したブランチに移動$ git checkout feature上の2つのコマンドを同時に行うコマンドが下のコマンドです
$ git checkout -b featureもっと詳しくブランチについて知ってから他のgitコマンドを身につけたい方は下の記事をご覧ください
開発の流れ
1. クローンを作る(コピーを作成する)
リモートリポジトリ(GitHub等)のファイルがワークツリーとローカルリポジトリ(.git directoryが)にコピーされる
$ git clone <repository url>2. ブランチを作る
$ git checkout -b feature3. プッシュする
$ git push リモート名 ブランチ名4. 修正する
プロジェクトに変更を加える
5. 完了後にコミットする
$ git add .コミットしていきます
$ git commit -m "First commit"6. プッシュする
$ git push7. Pull requestを送る
GitHub上でプルリクエストを送ります
以上がgitでの開発の流れですが説明はかなり省略しています
もっと詳しく知って実際の開発に役立てたい方は下の記事をご覧ください
新規プロジェクトをGitHubで扱う
①git init
$ git initGit に必要なファイル(.git)がダウンロードされます
②リモートリポジトリ(github)を新規で登録する
GitHubをブラウザで開き新規リポジトリを作成してください
その後下のコマンドを打ち込みます
$ git remote add origin githubのURL③プッシュする
$ git push -u origin masterかなり端折って紹介したのでもっとわかりやすい説明は下の記事からご覧ください
開発で役立つコマンド
リモートから情報を取得する
リモートリポジトリから情報を取得するには以下の2種類の方法があります
- フェッチ(fetch)
- プル(pull)
①フェッチ
以下のgitコマンドでリモートリポジトリから情報を取得できます
$ git fetch リモート名専用に作成されたブランチのワークツリー には以下のgitコマンドを使って反映していきます
$ git merge origin/master②プル
pullコマンドはこのコマンド1つで以下2つの役割を持ちます
$ git fetch origin master $ git merge origin/master実際のプルコマンドは以下です
$ git pull リモート名 ブランチ名簡単なフェッチとプルの使い方だけだとわかりにくいと思うので下の記事もご覧ください
リモート名の変更/削除
リモート名の変更
$ git remote rename 旧リモート名 新リモート名 $ git remote rename sample_app test_appリモートの削除
$ git remote rm リモート名 $ git remote rm test_appもっと詳しく知りたい方は下の記事が役立つと思います
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は開発において非常に重要な箇所なので是非詳しい説明は下の記事でご覧ください
ここまででgitの基本を押さえられると思います
まだまだgitコマンドはありますが、まずは今回紹介した基礎を身につけて実際に使ってみてください
開発をする際に必ず役立つと思います
今回の元記事は下の記事になります
- 投稿日:2020-06-03T16:02:51+09:00
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 するときの元となるデータがなかったためエラーになったみたいだ。
- 投稿日:2020-06-03T15:24:02+09:00
Rails Herokuデプロイ手順
プログラミング初学者のため訂正がありましたらご指摘ください。
gitをインストールしている前提です。自身の環境
- Ruby 2.5.1
- Ruby on Rails 5.2.4.1
- MySQL (gem 'mysql2', '>= 0.4.4', '< 0.6.0')
デプロイの流れ
- The Heroku CLIの設定
- Herokuにログイン
- Herokuにデプロイ
Herokuとは
HerokuとはWebアプリケーションを簡単に全世界に公開できるクラウドプラットフォームです。
参考)HEROKU とは
以下のURLからHerokuのユーザー登録を行います。ユーザー登録は無料です。
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' endpg gemは本番用のgemでローカル環境にはインストールしないようにします。その場合、bundle installに--without productionを追加します。このフラグを追加することで、pg gemはローカル環境には反映されないようになります。それでは以下のコマンドを実行します。
$ bundle install --without productionbundle installの本番環境用
次に「heroku create アプリ名」コマンドでheroku上にアプリケーションを作成します。 以下のコマンドを実行します。
$ heroku create上記のようにアプリ名を入力しないと自動で名前をつけてくれます。
一度登録した名前は使えないので注意してください上記のコマンドを実行すると、以下のような結果が表示されます。
Creating app... done, ⬢ app(アプリ名) https://app(アプリ名).herokuapp.com/ | https://git.heroku.com/app(アプリ名).githttps://~~.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
- 投稿日:2020-06-03T14:00:44+09:00
[Rails]フォームのすべての値をワンクリックで初期化する(helperメソッド定義+JavaScript)
はじめに
様々な検索条件を付けられる検索フォームを実装している中で、検索条件をワンクリックでリセットできる方法がないかと試行錯誤しました。
結果、下記の方法で実装できたのでまとめます。
環境
- Ruby2.5.1
- Rails5.2.4
手順
概要を簡単に説明すると、
1. ヘルパーメソッドにリセットボタンタグを生成するメソッドを定義
2. ビューでそれを呼び出す
3. チェックボックスをjsでクリアする処理を書く
という3本でお送りする感じです1. ヘルパーメソッドの定義
どのファイルでもいいですが、今回は
helpers/application.rb
に定義します。helpers/application.rbmodule ApplicationHelper def reset_tag(value = "Reset form", options = {}) options = options.stringify_keys tag :input, { type: "reset", value: value }.update(options) end end2. ビューファイルで呼び出し
search.html.haml%div = reset_tag 'クリア', id: 'js_clear_btn' %div = f.submit '完了'本来Railsに
reset_tag
はありませんが、ヘルパーメソッドで定義したので、この書き方で呼び出せます。3. チェックボックスをJavaScriptでクリアする記述
私の場合は、リセットボタンだとチェックボックスをクリア(チェックを外す)ことができなかったので、そこはJavaScript書きました。
コードは環境に大きく依存してしまうので、割愛します。
結果
こんな感じで、text_fieldもnumber_fieldも、selectもcheckboxもすべて初期化するボタンを作成できました!参考
- 投稿日:2020-06-03T13:34:50+09:00
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
- 投稿日:2020-06-03T12:40:18+09:00
【Rails】Geocoding APIを用いて高精度で緯度経度を算出し、Google Mapに表示する方法
目標
ユーザーが登録した住所をマップの中心に表示し、マーカーを立てる。
開発環境
・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.下記リンクにアクセス
2. 「APIの概要に移動」をクリック
3.「ライブラリ」をクリック
4.検索フォームに「geo」と入力し、「Geocoding API」をクリック
5.「有効にする」をクリック
6.赤枠で囲われている箇所をクリック
7.プルダウンメニューが表示されるので、「全てのGoogle Maps API」をクリック
8.「認証情報」をクリック
9.「APIキーの名前」をクリック
10.認証情報の設定をする
①APIの制限
キーを制限
を選択し、プルダウンメニューからGeocoding API
を選択する。②
Maps JavaScript API
と、Geocoding API
が選択されている事を確認して、保存
をクリック11.APIが2個になっているかを確認
APIを追加した事でAPIキーが変更されるという事は無いので、これで完了。
実装
1.Gemを導入
Gemfilegem 'gon' gem 'geocoder'
gem 'gon'
➡︎ コントローラーで定義したインスタンス変数をビューのJavaScript内で使用出来る様にする。
gem 'geocoder'
➡︎ 住所から緯度経度を算出する。ターミナル$ bundle2.
geocorder
の設定ファイルを作成し、編集ターミナル$ touch config/initializers/geocoder.rbgeocoder.rb# 追記 Geocoder.configure( lookup: :google, api_key: ENV['GOOGLE_MAP_API'] )これで
Geocoding API
を使用する事ができ、緯度経度の算出が高精度で行えます。3.カラムを追加
ターミナル$ rails g migration AddColumnsToUsers address:string latitude:float longitude:floatadd_columns_to_users.rbclass 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:migrate4.モデルを編集
user.rb# 追記 geocoded_by :address after_validation :geocode
geocoded_by :address
➡︎ addressカラムを基準に緯度経度を算出する。
after_validation :geocode
➡︎ 住所変更時に緯度経度も変更する。5.コントローラーを編集
①
application_controller.rb
を編集ストロングパラメーターに「address」を追加します。
application_controller.rbdef configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:email, :name, :address]) end②
users_controller.rb
を編集users_controller.rbdef show @user = User.find(params[:id]) gon.user = @user # 追記 end6.ビューを編集
①
application.html.slim
を編集
gon
を読み込みます。
CSSとJavaScriptより先に読み込んでいる事に注意して下さい。application.html.slimdoctype 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をオフにする方法」につきましては後日記事にしたいと思います。
- 投稿日:2020-06-03T10:39:40+09:00
学んだイディオム
||=を使った自己代入
x ||= Aのコードを見たら、「変数Xがnilまたはfalseなら、AをXに代入」と解釈する
number = nil number ||= 10 number #=> 10 number = 20 number ||= 10 number #=> 20n += 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 enddef title_exists? !!find_title end参考文献
プロを目指す人のためのRuby入門
- 投稿日:2020-06-03T09:02:37+09:00
シンボルについて詳しく
シンボルを作成する上での注意点
エラーが出る書き方#識別子として無効な文字列(数字で始まる、ハイフン、スペースを含む文字列)を使うとエラーが発生 :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入門
- 投稿日:2020-06-03T09:02:37+09:00
シンボルについて学習したこと
シンボルを作成する上での注意点
エラーが出る書き方#識別子として無効な文字列(数字で始まる、ハイフン、スペースを含む文字列)を使うとエラーが発生 :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入門
- 投稿日:2020-06-03T01:48:21+09:00
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が追加されたことが確認できます。
記号の意味
=> - 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
で一覧から消えていれば、削除されたことが確認できます。