20191008のRailsに関する記事は17件です。

自分用メモ(editとDelete)

Edit

edit_post_path(post)
→postオブジェクトを渡しているので、post.idを渡している(Railsはオブジェクトを一意に表す値を取得しようとするから)
→/posts/id/というようなパスが生成

bundle install と bundle updateの違い

「前提」
(設計図)gemfile・・・gemfileに書くもの全ては書いてない
90記載

↓設計図を元に作るーbundler(gemfileに書いてないもの残り10を取ってくる)

(設計した結果)gemfile.lock
100記載

「bundle update」

gemfileを元に

bundle update

gemfile.lockを更新

「bundle install」
A,B,Cをgemとする。Bのアップデート後をB'とする。
gemfileにA,B,C
gemfile.lockにA,B'が記載されているとする

gemfile.lock

bundle install
gemfile.lockに書かれている A,B'のgemをインストール
gemfile.lockに書かれていなくて、gemfileに書かれているgem Cをインストール

gemfile.lockを更新

→gemfile.lockにもともと記載されていたgemはアップデートされない

bundle install とbundle updateの使い分け

新しい環境に変わった・新しくgemfileに新しくgemを記載した(ローカル環境で行う)

bundle install
※本番環境で行うと、gemが更新されクラッシュするので注意
ーーーー

gemのバージョン更新

bundle update

参考
https://qiita.com/lasershow/items/1a048d03ddaaba98171e

ユーザーmodel作成

メルアドはデータベースレベルで一意性を保ちたいので、indexつけて、それをunique: trueにする

bcryptとpassword_digest作ったら
models/user.rb にhas_secure_passwordを書く
→仮想属性password と password_confirmationが作られる

DB
疑問↓
データベース単位で受け取れる値を決めた方が良いのか(db:migrate前でデータの制約)
データ送信時にデータを検証した方が良いのか

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

【Rails】viewにおけるページタイトルの扱い方

開始タグ

ページタイトルの存在がすっぽ抜けていたので設定しました。

方法

ページタイトル例:ログイン画面|テストアプリ

最初に/app/views/layouts/内にある何かのテンプレート内の<title></title>の中に以下を記述。

application.html.erb
<title>
  <%= content_for?(:html_title) ? yield(:html_title) : "" %> |テストアプリ
</title>

最後に/app/views/以下のビューファイルに以下を記述。

login.html.erb
  <% content_for(:html_title) { 'ログイン画面' } %>

簡単2STEP!

自分は究極にざっくりとこう解釈。

content_for=コンテンツを1箇所にまとめて他のビューでも使用できるようにしてるんじゃない?
yield(:html_title)=yieldとあるから、ビューファイルにcontent_for(:html_title)があればそこから持ってくるんじゃない?

閉じタグ

「全然仕組み分かってないなー!」と文字に起こそうとする思い知らされますね。
「知らなければ知ればいい」と自分を励ましておきます。

参考サイト

ActionView::Helpers::CaptureHelper(リファレンス)
Rails: ページタイトルはビューテンプレートのcontent_forで表示すること(翻訳)

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

Date.today.since(7.days) ←7日後

何日後:since

何日前:ago

どちらも`Dateクラスが持っているメソッドである。

[1] pry(main)> Date.today
=> Tue, 08 Oct 2019

[2] pry(main)> Date.today.since(3.days)
=> Fri, 11 Oct 2019 00:00:00 JST +09:00

[3] pry(main)> Date.today.ago(3.days)
=> Sat, 05 Oct 2019 00:00:00 JST +09:00
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】RSpecでモデルのテストをする

概要

モデルのテストの記述方法を解説します

詳しくはRSpecの公式サイトのモデルに関するページを参考にしてください
今回は一例としてPostモデルのテストを解説します。
前提としてPostにはアソシエーションされたCommentモデルが存在します。

spec/models/post_spec.rb
require "rails_helper"

RSpec.describe Post, :type => :model do
  context "with 2 or more comments" do
    it "orders them in reverse chronologically" do
      post = Post.create!
      comment1 = post.comments.create!(:body => "first comment")
      comment2 = post.comments.create!(:body => "second comment")
      expect(post.reload.comments).to eq([comment2, comment1])
    end
  end
end

基本はRubyの書き方と同じです。コントローラーの記述する感覚で書きます。

  • post = Post.create!

    • postを作成、保存します
    • createメソッドはnew+saveです
    • !をつけると保存できなかった時にその原因を出力してくれます
  • comment1 = post.comments.create!(:body => "first comment")

    • postに紐づいたcomment:body => "first comment"で作成する
    • comment2も同様です
  • expect(post.reload.comments).to eq([comment2, comment1])

    • post.reload.commentsの値が[comment2, comment1]と一致するかどうかを確かめる
    • post.reload.commentsreloadはデータベースの値を再び取得するためのメソッドです

以上がモデルのテストの記述方法の一例の解説です。
これを元に自身のアプリケーションにも適応し、テストしてみてください。

疑問、気になるところがございましたら、質問、コメントよろしくお願いいたします!!

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

Railsでタイムゾーンを使う場合の注意点まとめ

記事の概要

  • 標準時・タイムゾーンの定義を確認
  • Railsでのタイムゾーン設定箇所と注意点の確認

動作確認した環境

  • rails 5.2.1

タイムゾーンという概念

標準時・タイムゾーンとは何か

ある地域で共通している時刻系をその国の標準時と呼びます。

例えば日本ではJST (Japan Standard Time) と言う標準時を採用しています。
今がAM 10:00 なら沖縄でも北海道でも同じくAM 10:00 になります。これは日本国内ではどの地域もJSTを採用しているためです。

標準時と言う時刻系が共通している地域全体のことをタイムゾーンと言います。

標準時の適用範囲

標準時の適用範囲は、便宜上、国または地域という単位になっています。

日本が昼間の時に夜の国があるように、天体的な問題(地球の自転や太陽との関係性など)から地球全域で同じ時間帯を採用することはできません。
逆に、太陽がちょうど真南にくることを意味する南中を基準に各地で正午を観測するような細かさだと、それぞれの経度ごとに標準時ができてしまいます。

それだといろいろ不便(例えば国内だと関東と東北でいちいち小さな時差があるのはめんどくさい)なので、地理的にある程度近い地域では共通の時刻を使いましょうということになってます。

この地域というのは必ずしも国とは限りません。
アメリカのような国土が広大な国だったり離島があったりする国では地方によって採用している標準時が異なったりします。

逆に地理的に近ければ、国が違っても時差がない場合があります。
日本と韓国は時差がありません。日本ではJST、韓国ではKSTという標準時をそれぞれ採用していますが、これは呼び方が違っても時刻系としては同じものになります。

オフセットは協定世界時(UTC)

標準時やタイムゾーンは協定世界時(UTC)を基準に何時間進んでいるか or 遅れているかで表現されます。
日本標準時(JST)は協定世界時(UTC)より9時間進んでいるので +09:00 というような表記になります。

時間帯 (標準時) - Wikipedia

Railsでのタイムゾーン設定

海外展開(異なるタイムゾーンをまたがって)展開しているようなアプリであれば標準時やタイムゾーンの理解が必要になります。

タイムゾーンの設定というのはOSやRailsのアプリケーションで各々持っていて、あるオブジェクトではOSのタイムゾーンを参照、他方ではアプリケーションの設定を参照しているケースなどがあり、その上アプリとは別にデータベースのタイムゾーンも設定が別れていたりします。
このようなややこしさから躓石となりやすい箇所です。

Railsアプリを実装する上で考慮すべき設定は以下です。

  1. OSのタイムゾーン設定
  2. アプリケーションのタイムゾーン設定
  3. アプリケーションがデータベースをどのタイムゾーンで扱うかの設定

各々の設定場所や概略などは下表のとおりです。
※表中の「設定ファイル」はここでは config/application.rb で、既定値はrails 5.2.1でのものとします

  設定場所 概略 既定値
1. OSのタイムゾーン /etc/localtime (UNIX系OSの場合) Rubyの組み込みクラスがこの値を参照する -
2. アプリケーションのタイムゾーン 設定ファイルの config.time_zone ActiveSupport::TimeWithZoneがこの設定値を参照する UTC
3. アプリケーションがデータベースを… 設定ファイルの config.active_record.default_timezone RailsがActiveRecordを通してデータベースに時刻を保存する、または取り出す際に値をどのタイムゾーンとして扱うかの設定 nil
設定ファイルの config.active_record.time_zone_aware_attributes ActiveRecordのインスタンスに時刻型のプロパティがあったときにどう扱うかの設定 -

以下、各々に関して詳しく見ていきます。

1. OSのタイムゾーン

OS毎に設定方法が違っていたりする場合もあると思いますがUNIX系ならだいたい以下のコマンドで参照できると思います。

$ date
2018年 10月13日 土曜日 11時37分44秒 JST

環境変数TZが設定してあれば/etc/localtimeではなく前者の方が優先されたりすることもあるようですが、ここではRailsの設定を重点的に見たいのでその辺は割愛します。

Rubyの組み込みクラスは上記のようなOSのタイムゾーンを参照しますので、実装する際はこの点は念頭に置いた方がいいでしょう。

例えばTimeクラスの以下のクラスメソッドでは仮にRailsの設定ファイル上、config.time_zoneが"UTC"であってもOSのタイムゾーンが"JST"の場合は後者の時間で返ってきます。

2.5.0 :001 > Time.zone.name
 => "UTC"
2.5.0 :002 > Time.new
 => 2018-10-13 13:02:59 +0900
2.5.0 :003 > Time.now
 => 2018-10-13 13:02:58 +0900
2.5.0 :004 > Time.local(2018, 10, 12)
 => 2018-10-12 00:00:00 +0900

要するにアプリケーションのタイムゾーンとしてconfig.time_zoneで指定したものとOSのタイムゾーンが違っているときに、前者で設定したものを使いたいのに上記を呼び出すと意図した結果にならないので注意です。

ただ、Time.zoneTime.currentみたいにActive Supportによって拡張されたものは挙動が違ってきます。

2.アプリケーションのタイムゾーン

ここでは上記小見出しは設定ファイルのconfig.time_zoneで設定するものを意味します。
これは具体的にはActiveSupport::TimeWithZoneで用いるタイムゾーンを指定する設定項目です。

config.time_zone = 'Asia/Tokyo' のようにJSTを使うように設定したら、OSのタイムゾーンが仮にUTCなどJST以外のものであってもJSTで時間を返してくれます。

2.5.0 :001 > Time.zone.name
 => "Asia/Tokyo"
2.5.0 :002 > Time.zone.now
 => Sat, 13 Oct 2018 14:41:44 JST +09:00

設定ファイルで指定したタイムゾーンで時間の処理をしたいなら基本的に ActiveSupport::TimeWithZone を使えばOKだと思います。
なお、Time.currentTime.zone.xxxxxx.in_time_zone 等のメソッドを使うと、Time ではなく、TimeWithZone のインスタンスが返されるので注意してください。

2.5.0 :005 > Time.zone.now.class
 => ActiveSupport::TimeWithZone
2.5.0 :006 > Time.current.class
 => ActiveSupport::TimeWithZone
2.5.0 :007 > Time.zone.now.class
 => ActiveSupport::TimeWithZone
2.5.0 :011 > Time.now.in_time_zone.class
 => ActiveSupport::TimeWithZone

これら TimeWithZone のインスタンスを返すものは ActiveSupport によって実装されたものです。
また、 3.days.ago のようなものも ActiveSupport の実装ですから、これらも TimeWithZone のインスタンスを返します。

2.5.0 :009 > 3.days.ago.class
 => ActiveSupport::TimeWithZone

TimeWithZoneのインスタンスは new ではなく、上記で例示したようなもので生成するのが望ましいらしいです(ActiveSupport__TimeWithZoneにその旨記載がある)

Time は Time.utc のようにUTCで処理できるメソッドがあるので、OSのタイムゾーン以外にUTCも扱えますが、扱えるタイムゾーンはこの2つだけです。
一方 ActiveSupport::TimeWithZone は様々なタイムゾーンを扱えます。

2.5.0 :013 > Time.now.in_time_zone('Hawaii')
 => Fri, 12 Oct 2018 19:55:08 HST -10:00

一般的にはタイムゾーンの扱いに長けている ActiveSupport::TimeWithZone を使った方がいいでしょう。
ただし、 ActiveSupport::TimeWithZone はRuby組み込みのメソッドで取得したUTCの時間を基準に、設定されているタイムゾーンの時間に変換するという仕組みらしいのでOSの時間がずれてたら ActiveSupport::TimeWithZone でタイムゾーンを考慮して算出する時刻もずれるので注意が必要です。

3. アプリケーションがデータベースをどのタイムゾーンで扱うかの設定

設定ファイルには前章のconfig.time_zone以外にも以下のタイムゾーン設定項目があります。

  • config.active_record.default_timezone
  • config.active_record.time_zone_aware_attributes

config.active_record.default_timezone

ActiveRecordがマッピングしたDBテーブルのレコードは、created_atやupdated_atのような時刻をプロパティとして保持することになります。
これらはTimeWithZoneのインスタンスです。

2.5.0 :010 > Admin.first.created_at.class
  Admin Load (0.5ms)  SELECT  `admins`.* FROM `admins` ORDER BY `admins`.`id` ASC LIMIT 1
 => ActiveSupport::TimeWithZone

この設定項目は、上記のようなActiveRecordでActiveSupport::TimeWithZoneを処理する際に基準とするタイムゾーンを指定するものです。

設定できる値は:utc or :localの2択です。

:utcの場合は、ActiveRecordのインスタンスが持っているTimeWithZoneの値をUTCに変換します。OSのタイムゾーンは考慮しません。
:localの場合はOSのタイムゾーンが使われます。

設定値は以下で確認できます。

2.5.0 :011 > ActiveRecord::Base.default_timezone
=> :utc

なので、 config.time_zone = 'Asia/Tokyo' のような設定のアプリでも、 config.active_record.default_timezone = :utc であれば、ActiveRecordでレコード保存する場合に時刻はUTCに変換して保存されます。例えば、日本標準時では15:00の時点で保存するとDB上の記録は0:00となります。
findなどでインスタンス化するときは逆にUTCで保存されたレコードを日本標準時に変換してくれます(ActiveRecordのインスタンスだとcreated_atはActiveSupport::TimeWithZoneのインスタンスなので、config.time_zoneの設定値が適用されるわけです)

config.active_record.time_zone_aware_attributes

この項目を明示的にfalseにすると(config.active_record.time_zone_aware_attributes = false と記述すると)、ActiveRecordが時刻系のプロパティをActiveSupport::TimeWithZoneではなく、Timeで扱うようになります。

2.5.0 :002 > Admin.first.created_at.class
  Admin Load (0.5ms)  SELECT  `admins`.* FROM `admins` ORDER BY `admins`.`id` ASC LIMIT 1
 => Time

こういう振る舞いにしたいという明確な意図がないなら使うことはないと思います。
ここではこの用途に関してはあまり考えないことにします。

個人的に注意した方がいいと思ったこと

  • ActiveSupportがTimeクラスを拡張しているのでTimeのメソッド全てがOSのタイムゾーンを参照するTimeのインスタンスを返すとは限らない
  • config.active_record.default_timezone は途中で変えちゃいけない(例えばMySQLの場合DATETIME型はタイムゾーン情報も保存しているわけではないのでごちゃごちゃになる)
  • MySQLの場合は、SQLでNOW()関数を使う場合その時刻はOSのタイムゾーンが基準なので、ActiveRecordによって記録されているタイムゾーンがOSのものと一致してない場合、比較がずれる
  • 設定ファイルの既定値はRails自体をバージョンアップした時に変わってしまう可能性があるので明示的に指定した方がいい

おまけ: 実務でやらかした例

2018/10/05 13:00 以降にxxしたいみたいな条件判定で使う時刻をローカルで以下のように出してた。

2.5.0 :012 > Time.new(2018, 10, 5, 13).in_time_zone('Asia/Tokyo')
=> Fri, 05 Oct 2018 13:00:00 JST +09:00

ローカルのMacOSのタイムゾーンはJST。Time.newはOSのタイムゾーン参照する。

一方本番のサーバのOSのタイムゾーンはUTC。だから上記と結果が違う。

2.5.0 :003 > Time.new(2018, 10, 5, 13).in_time_zone('Asia/Tokyo')
 => Fri, 05 Oct 2018 22:00:00 JST +09:00

UTCでの 2018/10/05 13:00 にさらにJSTとの差分を追加しているので9時間分ずれて意図した結果にならなかった。

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

Railsチュートリアル 第4章<復習>

第4章の復習メモです。
個人的に重要と思ったことを書きます。
調べたことや、知っていたことも含めて書きます。

ヘルパー

ビューやコントローラ、モデルから呼び出せるメソッド。
以下の二種類がある。

  1. 組み込みヘルパー
  2. 新しく定義できるカスタムヘルパー

1は、Railsで元々用意されている。
2は、自分で定義でき、以下のファイルに記述する。
 app/helpers/application_helper.rb

※以下のサイトも参考にさせていただきました
https://www.sejuku.net/blog/28563

文字列の表現

文字列は、シングルクォート(')またはダブルクォート(")で囲む。
前者は、囲った物をそのまま表現する。
よって、正規表現(\n等)や、式展開(文字列中に変数を埋め込む)は無効となる。
後者は、両方とも有効。

引数、カッコの省略

メソッドにデフォルト引数を設定している場合、引数、カッコを省略できる。

# メソッドの定義
def string_message(str = '')   # デフォルト引数として''を設定
 .
 .
end

# 呼び出す側
string_message

最後の引数がハッシュの場合、波カッコを省略できる。

# 以下の二つは同じ意味となる
stylesheet_link_tag 'application', { media: 'all',
                                     'data-turbolinks-track': 'reload' }

stylesheet_link_tag 'application', media: 'all',
                                   'data-turbolinks-track': 'reload'

範囲 (range) オブジェクト

1..10a..zのように表現する。
to_aメソッドで配列に変換すると、範囲内の値が全て、配列に格納される。

ブロック

{}で囲むパターンと、do~endで囲むパターンがある。
すいません、文章にできるほど理解できていないので、
リンクを貼らせていただきます・・・
https://www.sejuku.net/blog/14291

inspectメソッド

対象のリテラル(プログラムに記述するデータ値。コードに書いた値。)を返却する。

>> puts (1..5).to_a            # 配列を文字列として出力
1
2
3
4
5
>> puts (1..5).to_a.inspect    # 配列のリテラルを出力
[1, 2, 3, 4, 5]
>> puts :name, :name.inspect
name
:name
>> puts "It worked!", "It worked!".inspect
It worked!
"It worked!"

以下を参考にさせていただきました
https://www.sejuku.net/blog/77039
http://www.designmap.info/2016/12/16/javascript-3/#i-2

クラス、継承

Rubyにおけるすべてのクラスは、最終的にスーパークラスを持たない
BasicObjectクラスを継承している。
image.png

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

Railsチュートリアル 第3章<復習>

第3章の復習メモです。
個人的に重要と思ったことを書きます。
調べたことや、知っていたことも含めて書きます。

Webページの作成

Railsで、Webページ作成に最低必要なのは、以下の3つ。

  1. URLのルーティング
  2. 1に対応するコントローラ及び、アクションの作成
  3. 2に対応するビューの作成

以下のコマンドを実行すると、上記3つを自動生成してくれる。

$ rails generate controller <コントローラ名> <アクション名1> <アクション名2> <アクション名xx>
  • ルーティングについて
    • config/routes.rbファイルにルーティングが追記される。
  • コントローラについて
    • 慣習的に、コントローラ名はキャメルケース(頭だけ大文字)で記載する。
    • 生成されるコントローラは、スネークケース(単語間を_でつないだ形)になる。
    • アクション名は全て小文字にする。また、いくつ書いても良い。
  • ビューについて
    • コントローラのアクション毎、ビューが生成される。

切り戻しについて

コマンドを打ち間違えて、変なファイルを作ってしまった場合、
元の状態に戻すためのコマンドが用意されている。

  • コントローラを戻す
$ rails destroy  controller <モデル名> <アクション名1> <アクション名2>
  • モデルを戻す
$ rails destroy model <モデル名>
  • DBへの反映を1つ戻す
$ rails db:rollback
  • DBへの反映を全部戻す
$ rails db:migrate VERSION=0

テストについて

$ rails test

で、テストを実行できる。
テストコードは、あらかじめ生成されている物もある。
また、Guardを使ってテストを自動化できるみたい。
詳しく理解するのはまたの機会に。

Gitについて

git push origin <ブランチ名>

で、GitHub上のブランチにPUSHされる。
GitHubにブランチが存在しない場合、新規作成される。

最低限、3章まではやろうと思っていたので、目標は達成しました。
4章以降についても、できれば続けていきたいと思います。

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

Ruby on Rails アプリ作成のはじめのはじめ

Ruby on Rails作成におけるアウトプット用も兼ねて記載していきます。
間違い等あればご連絡ください。

新規Railsアプリケーションの作成
 アプリケーションを配置するディレクトリを作る。
  自分の作成したい場所までターミナルで移動する。
  cd
現在のディレクトリ(カレントディレクトリ)を移動する
mkdir
新しくディレクトリを作成する
pwd
現在のディレクトリ(カレントディレクトリ)のパスを表示する
ls
現在のディレクトリ(カレントディレクトリ)のファイル一覧を表示する

新規アプリケーションを作成
ターミナルで「rails new」コマンドの実行
  rails new アプリケーション名 -オプション名

これでRuby on Railsのアプリ制作における雛形ができるので、ここから色々と編集していくことで立派なアプリへと成長させていくことが可能となる。

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

[Rails] Slackにエラー通知を行う

メモ

graphql_controllerの処理の流れ

エンドポイントをAPIモードのgraphql_controllerのexecuteメソッドに指定しているので、まずここが呼び出される。

(1) Webhook URLの取得

下記から、URLを取得する。

https://slack.com/services/new/incoming-webhook

(2) credentials.yml に秘匿情報を記載

  • webhook_url
  • channel

は隠していた方が良いと思うので、credentials.ymlに記載する

$ EDITOR="vi" bin/rails credentials:edit
credentials.yml
slack:
  webhook_url: https://hooks.slack.com/services/...
  error_channel: #{YOUR_CHANNEL}
  notification_channel: #{YOUR_CHANNEL}

(3) graphql_controllerに設定

graphql_controller.rb
class GraphqlController < ActionController::API
  def execute
    処理...  
  rescue => e
    slack_error_notifier(e, query, request, current_user)
  end

  private
    # https://api.slack.com/docs/message-attachments
    def slack_error_notifier(e, query, request, current_user)
      notifier = Slack::Notifier.new Rails.application.credentials.slack[:webhook_url].to_s, username: "#{YOUR_USERNAME}"
      attachments = {
        author_name: Rails.env.to_s,
        text: "■ *Request*\n" << "*#{request.headers[:REQUEST_METHOD]}* #{request.headers[:REQUEST_URI]}" \
              "\n\n■ *Time*\n" << "#{Time.zone.now}" \
              "\n\n■ *Current User*\n" << "*USER_ID* #{current_user&.id || "NONE"}" \
              "\n\n■ *User Agent*\n" << "#{request.headers[:HTTP_USER_AGENT]}" \
              "\n\n■ *IP*\n" << "#{request.headers[:REMOTE_ADDR]}" \
              "\n\n■ *Query*\n" << "#{query}" \
              "\n\n■ *Message*\n" << "#{e.message}" \
              "\n\n■ *Backtrace*\n" << e.backtrace.join("\n").to_s,
        color: "danger",
      }
      notifier.post attachments: [attachments], channel: "#{YOUR_CHANNEL}"
    end
end

(4) 通知の確認

  • requestの中身を全て確認する。
        text: "■ *Request*\n" + "#{request.headers.sort.map { |k, v| "#{k}:#{v}" }}" + 
              "\n\n■ *User Agent*\n" + "#{request.headers[:HTTP_USER_AGENT]}" + 
              "\n\n■ *IP*\n" + "Im P!!" + 
              "\n\n■ *Query*\n" + "#{query}" + 
              "\n\n■ *Message*\n" + "#{e.message}" + 
              "\n\n■ *Backtrace*\n" + "#{e.backtrace.join("\n")}",

参考

Railsヘッダーの中身について

エラーについて

Slackの通知カスタマイズ

Action Controllerについて

Action Dispatchについて

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

VScodeでRailsをデバッグする

経緯

  • VScodeでRailsアプリケーションをdebugしたくなった
  • 便利だから(たぶん)
  • ちなみに僕のVScodeは日本語になっているのでよしなに解釈してください

設定

プラグインのインストール

  • ということでVScodeでRubyをインストールしましょう スクリーンショット 2019-10-08 9.51.45.png

gemのインストール

  • 次は必要になるgemをインストールします
$ gem install ruby-debug-ide
$ gem install debase

構成の追加

  • ポチッと構成の追加をクリックします

スクリーンショット 2019-10-08 9.55.59.png

  • Rubyを選択(あるはず)
  • launch.jsonが作成されるはずなので中身をこんな感じにします
vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug Rails",
      "type": "Ruby",
      "request": "launch",
      "cwd": "${workspaceRoot}",
      "program": "${workspaceRoot}/bin/rails",
      "pathToRDebugIDE": "/home/trantan/.rbenv/versions/2.5.1/bin/rdebug-ide",
      "args": [
        "server"
      ]
    }
  ]
}

実行

  • あとは実行するだけです
  • 左側のサイドバーにDebug Railsがあると思うのでそれをポチっとしましょう

スクリーンショット 2019-10-08 14.30.15.png

  • そうすると、Railsサーバーが立ち上がりデバッグコンソールにババーッと何かが表示されると思います

スクリーンショット 2019-10-08 14.45.00.png

ブレークポイントを貼る

  • もちろん実行するだけでは分からないのでブレークポイントを貼って処理を止めます
  • ババーッと処理している何かしらのファイルに貼りましょう
  • コントローラー辺りにしますか
  • 数字の左脇辺りをポチッと押すとそこで処理が止まってくれます

スクリーンショット 2019-10-08 14.48.12.png

あとはサイドバーをみる

  • どんな値を持っているかとかスタックがどうなっているのかが左サイドバーに出ます(設定がデフォルトなら)
  • どこにブレークポイントを貼ったのかも分かります
  • 他にも何かあると思いますが割愛しますm(_ _)m

結論

  • 意外と簡単に設定できるのでぜひデバッグをやってみてください
  • 便利!!!!

参考

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

Rails6 のちょい足しな新機能を試す91(ActiveRecord annotate編)

はじめに

Rails 6 に追加された新機能を試す第91段。 今回は、 ActiveRecord annotate 編です。
Rails 6 では、 ActiveRecord で、発行される SQL にコメントを含めることができるように annotate メソッドが追加されました。
ログに出力して解析したり、デバッグしたりするときに便利そうです。

Ruby 2.6.4, Rails 6.0.0 で確認しました。

$ rails --version
Rails 6.0.0

今回は、User の CRUD を作り、一覧ページを表示するとき、そこで実行される SQL がどのコントローラのどのアクションから呼ばれているのかわかるようにしてみます。

プロジェクトを作る

rails new rails_sandbox
cd rails_sandbox

User の CRUD を作る

name をもつ User の CRUD を作ります

bin/rails g scaffold User name

コントローラとアクションの名前を返すメソッドを定義する

full_action_name というプライベートメソッドを ApplicationController に追加します

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  private

  def full_action_name
    "#{self.class.name}##{action_name}"
  end
end

ApplicationRecord に scope を追加する

annotate を使った scope を1つ ApplicationRecord に追加します。

app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
  scope :called_from, ->(from) { annotate("called from #{from}") }
end

UserController#index を変更する

User.allUsersController#index から呼ばれていることがわかるように、修正します。

app/controllers/users_controller.rb
class UsersController < ApplicationController
  ...
  def index
    @users = User.all.called_from(full_action_name)
  end
  ...
end

実際に一覧ページを表示してコンソールを確認する

rails server を実行し、ブラウザから http://localhost:3000/users にアクセスし、コンソールを確認します。
SQL 文にコメント"called from UsersController#index" が含まれていることがわかります。

...
  User Load (0.4ms)  SELECT "users".* FROM "users" /* called from UsersController#index */
...

試したソース

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

参考情報

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

capybaraとselenium-webdriverとは

capybaraとselenium-webdriverとは

capybara

統合テスト(Feature Spec/フィーチャースペック)を書くときに、ブラウザにを仮想的に操作するためのgem。
細かい動作まで検証できる。

selenium-webdriver

capybaraはシンプルなブラウザシミュレータ(つまりドライバ)を使って、 テストに書かれたタスクを実行していきます。このドライバは Rack::Test というドライバで、速くて信頼性が高いのですが、JavaScript の実行はサポートしていません。
javascriptをテストするためにselenium-webdriverというgemをを使います。

CapybaraでもデフォルトのJavaScript ドライバになっていて、
デフォルトでは Capybara は selenium-webdriver に対して Firefox を使ってテストを実行するように伝えます。ですのでChromeを使いたい場合はそのように設定しなければなりません。

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

【個人開発】プログラミングを勉強したので誰かの書き込みを表示するだけのWebサイトを作った

kotoniwa

https://tzanarkand.com

何をするwebサイトなのか

ユーザーそれぞれが好きな言葉を書き込む、そして画面をクリックすると誰かが書いた言葉がランダムでぼんやりと出てくるだけのサイト。

スクリーンショット 2019-10-04 1.54.09.png
スクリーンショット 2019-10-04 1.57.32.png

使ったもの

ruby
rails
javascript
jquery
Nginx
unicorn
postgresql

自分のスキル

専門学校でサーバーとネットワークの勉強をしていたけど、プログラミングの経験はほぼ0(シェルスクリプトちょっとやったかなくらい)。

他人が書いたrailsアプリを自分が立てたapacheサーバーで公開した事はある。

railsもjavascriptもコードを見たことはあります程度。

自分で1からコードを書いてというのはこれが初めて。

勉強したこと

udemyでjavascriptとrailsとhtmlとcssの講座を購入してみたけど最初にざっと見ただけであまり活用しなかった。結局これ実際にやってみないとよくわからないな、と思ったので。

実装したいと思ったことをその都度ググって、よくわからなかったらそこを深掘りして、みたいな感じで作りながら学習を進めた。

作るまでの流れ

現在はサーバー運用系のお仕事をしていて、web系の方に転職してみようかなという思いが出てきたのでとりあえず何かを作ってみることに。

今まで自分で一からwebサイトを作ったことはなかったのであんまり難しいことをやろうとすると挫折するだろうと思い、とにかくシンプルなものを作りたかった。

wikipediaをランダムで表示したりするやつとかのランダム系のサイトが好きだったのでそんな感じのをイメージしていて、「なんでも好きに書いていい」となった時に皆がどんなことを書くのかに興味があったのでこれを作ろうと思った。

感想

とりあえず公開まで持っていけてよかった。
こんな簡単な感じのサイトでもここまで躓きポイントが大量にあるのか…と思ったので、作ろうと思っても途中で諦めてしまう人は大量にいると思う。
次はもうちょい真面目なwebサービス感のあるサイトを作る予定。
もっと技術つけてはやく転職したい。

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

Rails on Railsにおける命名規則

目的

Ruby on Railsを使ってコントローラーやモデルを作成する際の命名規則を備忘録のためにまとめておく

命名規則

コントローラー
命名
コントローラー名 tasks
コントローラークラス名 TaskController
ファイル名 tasks_controller.rb
モデル
命名
モデル名 task
モデルクラス名 Task
モデルファイル名 task.rb
テーブル名 tasks

ポイント

コントローラーを作成するとき、コントローラー名は複数形
モデルを作成するとき、コントローラー名は単数形

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

Vagrant + RailsでHerokuにHello ,World!する

vagrantローカル環境でhello world!を表示するアプリを作成しherokuにデプロイするまでの忘備録

環境

  • Ruby 2.4.0

  • Ruby on Rails 5.1.7

  • rbenv 1.1.2-2-g4e92322

  • Node.js v4.9.1

  • bundler 2.0.2

Vagrantローカル環境構築

https://qiita.com/karlley/items/0812bd33a3952ea40de5

上記URLを参考に環境構築

上記URLではRails 5.1.6で進めていますが今回は5.1.7を使用

順番に進めれば/home/vagrant/centos67/your_workspace/your_appにアプリが作成され「Yay! Your on Rails!」まで表示できるはずです

まずはローカル環境でHello World!

作成されたアプリのファイルを編集し「Hello World!」が表示されるようにします

修正する使用するファイルは2つ

  • app/controllers/application_controller.rb

  • config/route.rb

上記のファイルを以下のように修正

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  def hello
    render html: "Hello, World!"
  end
end
config/route.rb
Rails.application.routes.draw do
  root 'application#hello'
end

http://192.168.33.10:3000で「Hello World!」が表示されているか確認

Git

  1. 初期設定
  2. Initial commit

1. 初期設定

HerokuのデプロイにはGitを使用するので初期設定

設定を確認

$ git config --list
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true

usernameとemailが未設定の場合は下記コマンドで設定

$ git config --global user.name "Your Name"
$ git config --global user.email your.email@example.com
$ git congit --list
user.name=Your Name
user.email=your.email@example.com
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true

設定を反映し、初期化

$ git init
Reinitialized existing Git repository in /home/vagrant/centos67/workspace/hello_app/.git/

上記コマンドを実行するとアプリのルートディレクトリに.gitが作成されます

2. Initial commit

Git設定後、最初のコミットを作成

ファイルをリポジトリに追加、確認

$ git add -A
$ git status
# On branch master
#
# Initial commit
.
.

リポジトリにコミット、確認

$ git commit -m "initialize repository"
56 files changed, 1181 insertions(+), 0 deletions(-)
 create mode 100644 .gitignore
.
.
$ git log
commit 28b...
Author: Your Name <your.email@example.com>
.
.

最初のコミットが作成されました

データベース

  1. postgreSQL
  2. sqlite3
  3. 設定したGemをインストール

1. postgreSQL

Herokuで使用するデータベースはデフォルトでpostgreSQLなのでGemの設定

Railsの開発環境でのデフォルトはsqlite3

Gemfileに下記を追記

Gemfile
group :production do
  gem 'pg', '0.20.0'
end

:production doは本番環境のみで使用するという意味

2. sqlite3

既存のsqlite3の記述をコメントアウト、または削除

Gemfile
#gem 'sqlite3'

開発/テスト環境のみの仕様に変更する為、group :development, :test dogem 'sqlite3'を追加

Gemfile
group :development, :test do
  # sqlite3 for development/test only ← 追記
  gem 'sqlite3'                       ← 追記
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
end

3. 設定したGemをインストール

$ bundle install --without production

--without productonをオプションで付ける事で本番環境へのデプロイの失敗を防止

pg gemを追加したことやRubyバージョンを指定したことをGemfile.lockに反映させないと、本番環境へのデプロイで失敗してしまうためです。

引用:RailsTutorilal

Gemfileを変更したので再度コミット

$ git commit -a -m "Update Gemfile for Heroku"

-aオプションは変更のあったすべてのファイルという意味

Heroku

  1. Herokuとは
  2. Heroku CLI インストール
  3. ssh鍵を追加
  4. デプロイ

1. Herokuとは

  • webアプリ用ホスティングサービス

  • Gitを使う事で簡単に本番環境にデプロイできる

  • Heroku本番環境ではデータベースにpostgreSQLを使用(Railsの開発環境でのデフォルトはsqlite3)

2. Heroku CLI インストール

Herokuをコマンドラインで使用するために必要

下記URLを参考にしてください

https://qiita.com/karlley/items/c423d02eee2292dab1f9

3. Heroku SSH鍵追加

/home/vagrant/.sshにSSH鍵があるか確認

$ cd ~/.ssh
$ ls -a
authorized_keys

id_rsa, id_rsa.pubが無い場合はSSH鍵が無いので下記URLを参考に生成

https://git-scm.com/book/ja/v1/Git-サーバー-SSH-公開鍵の作成

$ cd ~/.ssh
$ ssh-keygen
$ ls -a
authorized_keys  id_rsa  id_rsa.pub

SSH鍵が生成されたのでHerokuにログインし鍵を追加

Herokuアカウントが無い場合は下記URLから作成

https://jp.heroku.com

HerokuアカウントのEmail,Passwordを入力しログイン

$ heroku login --interactive
heroku: Enter your login credentials
Email:
Password:

Herokuにログイン後、SSH鍵を追加

$ heroku keys:add
Found an SSH public key at /home/vagrant/.ssh/id_rsa.pub
? Would you like to upload it to Heroku?
Uploading /home/vagrant/.ssh/id_rsa.pub SSH key... done

HerokuにSSH鍵が追加されました
HerokuのアカウントページのSSH Keysで追加された鍵を確認できます

4. デプロイ

Herokuにアプリケーションを作成

$ heroku create your-app-name
Creating app... done, ⬢ your-app-name
.
.

アプリ名が表示されアプリケーションが作成されます

リポジトリをプッシュ

$ git push heroku master
.
.
remote: Verifying deploy... done.
.
.
 * [new branch]      master -> master

デプロイ成功したのでブラウザで確認

$ heroku open
.
.
▸    Manually visit https://your-app-url/ in your browser.

表示されたURLをブラウザで確認

helloworld.png

無事「Hello world!」できました!

あっさり進んでいるように見えますが私のようなプログラミング初心者にとってローカル環境からデプロイするのは一つの大きな壁でした汗

同じように悩んでいる方に少しでも参考になればと思います!

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

自分用メモ(form_for関連・render・パスの確認)

render (Viewでの役割)

→部分テンプレートをビューに出力する

ex)<%= render 'form'%> ←ここに _form.html.erbが挿入される

post:@postって何

postという名のパラメーターにテンプレート変数@postを渡しなさい

ex) <%= render 'form' post:@post%>
→部分テンプレートの_form.html.erbの post という変数に @postを渡せ

・オプション色々はここに書いてある
https://web-camp.io/magazine/archives/17675

form_for(ビューヘルパーの一種)

→特定のモデルを編集するためのフォーム

(ビューヘルパーにはモデルのプロパティ名に対応した名前(シンボル)を渡すという点を覚えておくと良いらしい)あまりわからないのであとでビューヘルパーについて学ぶ

モデルを受け取る ex)post

form_for(model) do |f|
ーーーbodyーーー
end

bodyの中身
<% f.text_field :title %>
→postオブジェクトを編集するフォームで、titleプロパティに対応するテキストボックス

f.text_field

f.submit
→新規作成と編集の時では挙動が異なる
新規作成の時→create
編集する時→update

newで@postに代入する意味

formから代入する情報を格納するための器を作るため

newからcreateまでの流れ

フォーム作っておく
→データ受け取るときに受け取るデータ絞れる(1)

(C-new)newで空の容器@postを作成

(V)render 'なんたら',post: @post
でformのpostというパラメータに@postを渡す

(V)データ入力

(V)submitでデータ送信

(C-create)@postにデータを受け取る(再構築)
・データを絞って受け取る params.require(:model名).permit(:A,:B,:C...)
(Strongパラメータっていうらしい)

保存

パスの確認

rake routes
で出てくる

参考:https://qiita.com/nantekkotai/items/6fab459e1b9a38b9a816

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

attr_encryptedなカラムを検索する方法

初めまして、ガッシーです。Qiita初投稿となります。(なんか癖でQuiitaって打っちゃうんですよね)
日頃Railsの開発で躓いて調べたことなどを書き留めていければなと思ってます。
そんなところで本題へ。

railsでカラムを暗号化する際には一般的にattr_encryptedを利用するかと思いますが
READMEを翻訳しますと 

暗号化されたデータを検索することはできません。検索できないため、インデックスを作成することもできません。

との記載があります。
でも暗号化しつつ検索したいことって結構あると思うんですよね。

そこで登場するGemがblind_indexです。
ただし LIKE検索はできない ので注意してください。

blind_indexとは

例えばnameというカラムでattr_encryptedを使うときは encrypted_nameencrypted_name_iv の2つのカラムを用意すると思いますが、
それに加えて encrypted_name_bidx というカラムを追加してあげることで、そこに検索できる値を保存する感じです。早速やってみましょう。

設定

READMEに書いてあることをそのままやっていけばいいのですが一応書きます。
Gemfileに下記を追加してbundle install

gem 'blind_index'

コンソールを起動して下記コードを実行しランダムなキーを取得します。

irb(main):001:0> BlindIndex.generate_key
# SecureRandom.hex(32).force_encoding(Encoding::US_ASCII) でも同じ
=> "222189cbba7ba0381c66faf8f687197b4bd4256a99bf81c917256c2871ca5289"

キーを保存・設定します。

credentials.yml.enc
blind_index_master_key: "222189cbba7ba0381c66faf8f687197b4bd4256a99bf81c917256c2871ca5289"
config/initializers/blind_index.rb
BlindIndex.master_key = Rails.application.credentials.blind_index_master_key

(initializerを読み込むためサーバーは再起動しておいてください)

blind_index用のカラムを追加します。

db/migrate/add_name_bidx_to_users.rb
add_column :users, :encrypted_name_bidx, :string

modelも変更を加えます。

app/models/user.rb
class User < ApplicationRecord
  attr_encrypted :name, key: Rails.application.credentials.encrypted_key
  blind_index :name_bidx, key: Rails.application.credentials.blind_index_master_key #←こちら追加
end

以上で設定は完了です!

※既に暗号化カラムが保存されている方はコンソールにて下記コマンドを実行することで既存のレコードにも対応できます。

User.unscoped.where(encrypted_name_bidx: nil).find_each do |user|
  user.compute_name_bidx
  user.save(validate: false)
end

実行

User.where(name: "山田太郎")

これができるようになっているはずです。

感想

完全一致検索しかできないけど何もできないよりはマシか・・・
知識がないのですが、最初こちらの記事 attr_encryptedされたカラムに対してwhere likeしたかった。を見ましたが恐らく現在ivカラムを利用した暗号化を行っている場合は適応できないかな?と思ってます。
Qiita初めての記事となりましたのでもし誤りがありましたらご指摘いただければ幸いです。

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