20190909のRubyに関する記事は23件です。

ActiveRecordのvalidatesで表示されるエラーメッセージのフォーマットを変更する

何に困っているか

ActiveRecordのvalidatesでエラーになった時に表示されるメッセージを%{attribute}%{message}ではないフォーマットにしたい。
例えば、User.nameのvalidatesエラーでこの名前は1文字以上入力してください。みたいなエラーメッセージを表示したい。
さらに、そのフォーマットを適用するスコープを限定したい。

validatesのエラーメッセージを変更するには

0. サンプルアプリの概要

今回の環境はruby:2.5.2rails:6.0.0です。

Userモデルを持つアプリを用意します。

$ rails new validation_message_sample
$ rails g model user name:string

nameにvalidationを設定します。

class User < ApplicationRecord
  validates :name, presence: true
end

この状態でvalidationエラーを発生させるとエラーメッセージはこうなります。

$ rails c
Running via Spring preloader in process 27748
Loading development environment (Rails 6.0.0)
irb(main):001:0> user = User.new
   (2.0ms)  SELECT sqlite_version(*)
=> #<User id: nil, name: nil, created_at: nil, updated_at: nil>
irb(main):002:0> user.valid?
=> false
irb(main):003:0> user.errors.full_messages
=> ["Name can't be blank"]

これをこの名前は1文字以上入力してください。に変更します。

1. attribute名を日本語にする

まずはNameとなっている箇所を名前に変更します。

これにはrails-i18nというgemを利用します。
Gemfileに以下を追記して、bundle installを実行します。

Gemfile
gem 'rails-i18n`

次にconfig/application.rbにi18nの設定を追加します。

config/application.rb
module ValidationMessageSample
  class Application < Rails::Application
    config.load_defaults 6.0

    # 下の2行を追加する
    config.i18n.default_locale = :ja
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.yml').to_s]
  end
end

config/local/models/ja.ymlファイルを作成し、変更したいattribute名を定義します。

config/local/models/ja.yml
ja:
  activerecord:
    models:
      user: ユーザー
    attributes:
      user:
        name: 名前

この状態で実行すると、以下のようになります。

$ rails c
Running via Spring preloader in process 28562
Loading development environment (Rails 6.0.0)
irb(main):001:0> user = User.new
   (3.0ms)  SELECT sqlite_version(*)
=> #<User id: nil, name: nil, created_at: nil, updated_at: nil>
irb(main):002:0> user.valid?
=> false
irb(main):003:0> user.errors.full_messages
=> ["名前を入力してください"]

attribute名が名前になりました。
ついでにデフォルトのメッセージも日本語になりました。

2. :messageを利用する

:messageオプションを利用することで、メッセージを変更することができます。
詳細はRails Guideを参照してください。

class User < ApplicationRecord
  validates :name, presence: { message: 'は1文字以上入力してください。' }
end

実行するとこうなりました。

$ rails c
Running via Spring preloader in process 29059
Loading development environment (Rails 6.0.0)
irb(main):001:0> user = User.new
   (1.5ms)  SELECT sqlite_version(*)
=> #<User id: nil, name: nil, created_at: nil, updated_at: nil>
irb(main):002:0> user.valid?
=> false
irb(main):003:0> user.errors.full_messages
=> ["名前は1文字以上入力してください。"]

では、attribute名の前にこのという文字列を表示しようとしてみます。

app/models/user.rb
class User < ApplicationRecord
  validates :name, presence: { message: "この%{attribute}は1文字以上入力してください。" }
end

実行してみます。

$ rails c
Running via Spring preloader in process 29190
Loading development environment (Rails 6.0.0)
irb(main):001:0> user = User.new
   (1.6ms)  SELECT sqlite_version(*)
=> #<User id: nil, name: nil, created_at: nil, updated_at: nil>
irb(main):002:0> user.valid?
=> false
irb(main):003:0> user.errors.full_messages
=> ["名前この名前は1文字以上入力してください。"]

うーん、頭にもattribute名が付いてしまいます。
これは、エラーメッセージのデフォルトフォーマットが%{attribute}%{message}となっているためです。

3. カスタムメソッドを利用する

カスタムメソッドを利用して、エラーメッセージを変更する。

errors.add(:カスタムメソッド名, エラーメッセージ)でエラーメッセージを追加できますが、結局カスタムメソッド名が文頭に表示されてしまうので、:baseを利用することにします。
コードは以下の通り。

app/models/user.rb
class User < ApplicationRecord
  validate :name_presence

  private

  def name_presence
    return if name.present?

    errors.add(:base, "この名前は1文字以上入力してください.")
  end
end

実行するとこうなります。

$ rails c
Running via Spring preloader in process 33134
Loading development environment (Rails 6.0.0)
irb(main):001:0> user = User.new
   (2.5ms)  SELECT sqlite_version(*)
=> #<User id: nil, name: nil, created_at: nil, updated_at: nil>
irb(main):002:0> user.valid?
=> false
irb(main):003:0> user.errors.full_messages
=> ["この名前は1文字以上入力してください."]

確かに意図通りにエラーメッセージを変更することはできました。

しかし、attribute名をわざわざベタ打ちしてしまっていてDRYじゃないし、本来の:baseの用途ではないので、あまり良い解ではないと考えます。

4. エラーメッセージのフォーマットを変更する

この記事によると、Rails6.0.0からエラーメッセージのフォーマットをスコープを限定して変更できるようになったようです。

スコープを限定するために以下の設定を追記します。

require_relative 'boot'

require 'rails/all'

Bundler.require(*Rails.groups)

module ValidationMessageSample
  class Application < Rails::Application
    config.load_defaults 6.0

    config.i18n.default_locale = :ja
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.yml').to_s]
    config.active_model.i18n_customize_full_message = true  # この行を追加
  end
end

config.active_model.i18n_customize_full_messageはデフォルトがfalseなので、この設定を実施しておかないと機能しません。(これに気づかずにハマりました・・・)

エラーメッセージのフォーマットを以下の通り設定します。

config/local/models/ja.yml
ja:
  activerecord:
    models:
      user: ユーザー
    attributes:
      user:
        name: 名前
    errors:
      models:
        user:
          attributes:
            name:
              format: '%{message}'
              blank: この%{attribute}は1文字以上入力してください。

ちなみにUserモデルは下の通りです。

app/models/user.rb
class User < ApplicationRecord
  validates :name, presence: true
end

実行するとこうなります。

$ rails c
Running via Spring preloader in process 34119
Loading development environment (Rails 6.0.0)
irb(main):001:0> user = User.new
   (2.4ms)  SELECT sqlite_version(*)
=> #<User id: nil, name: nil, created_at: nil, updated_at: nil>
irb(main):002:0> user.valid?
=> false
irb(main):003:0> user.errors.full_messages
=> ["この名前は1文字以上入力してください。"]

遂に目的を達成する実装にたどり着くことが出来ました :star2:

一応、サンプルコードをGitHubに置いてます。

参考文献

https://qiita.com/Ushinji/items/242bfba84df7a5a67d5b
https://qiita.com/suketa/items/5af12acd88ebc8a2a1a5

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

docker-composeで「docker-compose up」ができないとき

docker-composeでdocker-compose upを実行すると、以下のように

(略)

web_1        | 
web_1        | - Gracefully stopping, waiting for requests to finish
web_1        | === puma shutdown: 2019-09-09 13:48:21 +0000 ===
web_1        | - Goodbye!
web_1        | Exiting
app_web_1 exited with code 1

といったエラーが出てしまうときがあります。

解決方法

docker-composeでは、gemを新規で導入するときには、まず以下のコマンドを実行すれば良いだけでした。

$ docker-compose build

それから、docker-compose upを実行すれば、通常通りコンテナが生成されるようになります。

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

9/9 Tech Expert (事前学習) day 10 / 変数スコープ

【学習アウトプット】

今日の目標(やること)
Ruby!

今日のまとめ

変数のスコープ

変数には、その変数が使える範囲がきまっている。
(例:メソッド内ではそのメソッド内で定義した変数)
スコープの範囲外の変数を使おうとすると、エラーが起こる。

【例】スコープの範囲内のため、正常に動作する

capital = "東京"        # 首都は「東京」
puts capital

【例】スコープの範囲が違うため、エラーになる

capital = "東京"        # 首都は「東京」
 def america
 puts capital
end

america                 # エラー

【例】同じ名前の変数でもスコープが違えば別の変数となる

capital = "東京"         # 首都は「東京」

def america
  capital = "ワシントン"   # americaの首都は「ワシントン」
  puts capital
end

america                 # => ワシントン

引数(ひきすう)

引数はメソッドの外からメソッドに渡す値
「メソッドを呼び出す部分(本引数)」と「メソッドを定義している部分(仮引数)」両方に書く

def メソッド名(仮引数)
   実行する処理
end

【例】引数を用いたメソッドの実行

def multi(input)
   puts input * input
end

puts "何か数字を入力してください"
input = gets.to_i

multi(input)

(メソッドmultiは、引数として渡した数を2乗した数字を出力してくれるメソッド)
()のinput
この記述により、メソッドmultiが実行される際にinputを引数として利用することが出来る。

・メソッドの中では仮引数の名前で扱うため、本引数と仮引数の名前が同じである必要はない。
・仮引数の名前は何でも良いが、誰が読んでもそれが何を指すかわかるようなネーミングを。(aやbではなく、numberやnameを使おう。)(引数が渡されたメソッドの性質によって名前を変えた方がわかりやすい場合がある。)

先ほどのメソッドの仮引数を以下のようにしても問題ない。
(仮引数の変数名をnumberに変更)

【例】仮引数の名前を変更

def multi(number)
  puts number * number
end

puts "何か数字を入力してください"
input = gets.to_i

multi(input)

〜独り言(まとめやら感想やら)〜

特になし。。。

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

Cucumberからwebdriversのgemを使ってブラウザテストを実行する

chromedriver-helper が deprecated になって久しいので、いい加減 webdrivers に切り替えてみる。

RSpecSystemSpec から webdrivers を使う例はよくみるけど、
cucumber から使う例は自分で探した限りあまり無かったので改めて書き留めておくなど。

前提

  • CentOS 7 で実験した手順です
  • Ruby 2.6.4 を使用します

手順

1. 依存ライブラリをインストールしておく

もしインストールされていない場合はgoogle chromeとIPAフォントをインストールします

rootで実行
# cat << EOS > /etc/yum.repos.d/google-chrome.repo
[google-chrome]
name=google-chrome
baseurl=http://dl.google.com/linux/chrome/rpm/stable/$basearch
enabled=1
gpgcheck=1
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub
EOS

# yum install -y google-chrome-stable ipa-*-fonts
2. Gemfileにwebdriversを追加します
Gemfile
# ----- 前略 -----
gem 'webdrivers'
gem 'cucumber' # Railsプロジェクトの場合は 'cucumber-rails' を使用する
gem 'capybara'
# ----- 後略 -----
  • selenium-webdriverchromedriver-helper はもう記述する必要はありません( selenium-webdriverwebdrivers によってインストールされます)
3. bundle install を実行する
4. env.rb に設定を記述する
features/support/env.rb
require 'capybara/cucumber'
require 'webdrivers'

Capybara.configure do |config|
  config.default_driver    = :selenium_chrome_headless
  config.javascript_driver = :selenium_chrome_headless

  # Rails以外のアプリを試験する場合や、環境も含めたE2Eテストを実施する場合、下記の2行指定する必要がある
  # (直接Railsアプリを試験する場合は下記の2行は不要)
  config.app               = nil   
  config.run_server        = false
end

以上でインストールと設定は完了です。
stepやfeatureはこれまで通り使えますが、CapybaraやWebDriverに直接オプションを指定している場合は動かないケースもありますので、その場合はオプションの指定を外してください。

おまけ1:画面サイズの変更

ブラウザの画面サイズを変更する場合、SystemSpecでは driver_forのオプションでscreen_sizeを渡したり、Capybara.register_driver でオプションを指定して設定する場合もあります。

ただしこの場合、cucumberでは画面サイズ毎にoptionを指定したドライバを Capybara.register_driver し、step内でcurrent_driverを差し替えながら試験を進めないといけなくなります。

それよりは下記の方がLGTM(Looks Good to Me)です。

stepファイル
When("ブラウザのウィンドウを {int}px × {int}px にリサイズする") do |width, height|
  page.driver.browser.manage.window.resize_to(width, height)
end
featureファイル
シナリオ: WebDrivers経由で画面表示をしスクリーンショットを撮る
  もし "https://google.com"を表示する
  かつ ブラウザのウィンドウを 1000px × 600px にリサイズする
  # 後略

おまけ2:スクリーンショットを撮る

webdrivers経由でChromeを呼び出しても、これまで通りスクリーンショットは撮ることができます

stepファイル
Then("スクリーンショットを撮って{string}に保存する") do |file_path|
  page.save_screenshot "tmp/#{file_path}"
end
featureファイル
* スクリーンショットを撮って"screen_shot.png"に保存する

参考

これらのファイルはここで公開しています。参考になれば。

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

Google App EngineのRuby/スタンダード環境を試してみた

はじめに

Google App Engineスタンダード環境でRubyがサポートされました。
https://cloud.google.com/appengine/docs/standard/ruby/?hl=ja
サポートされたんだよね、本記事執筆時点(2019/9/9)で「ベータ版です」とか書いてあるけどドキュメントが追い付いてない?

まあそれはともかくGAEスタンダード環境とあれば私の出番だということで(?)、GAEスタンダード環境でのRubyの使い方について見ていきたいと思います。見ていくポイントは以下の3点です。

  • 依存ライブラリはどうやって入れる?
  • DatastoreとかのGCPサービス使うAPI(Rubyライブラリ)ある?
  • Rails動かせる?

依存ライブラリの指定方法

まずは依存ライブラリをどうやって入れるのかです。
結論から先に言うとGemfileを書いておけば普通にBundlerを使ってインストールしてくれます。ここら辺はPythonやNode.jsと同じですね。

Quickstartで紹介されているHello World app(Sinatraで書かれています)を見るとGemfileで依存ライブラリが指定されていることが確認できます。

起動方法と待ち受けるポート

起動するプログラムはapp.yamlにentrypointで指定します。先のHello World appの場合は以下のようになっています。

app.yaml
runtime: ruby25
entrypoint: bundle exec ruby app.rb

このアプリの場合、Sinatraデフォルトのサーバ起動が行われ、Sinatraしか入れてないので標準ライブラリのWEBrickがサーバとして使われます。

production環境でWEBrickはあかんやろm9(^Д^)プギャー、という場合はすぐ横にHello WorldアプリをPuma(Rack)使って起動している例があります1
こちらを見ると待ち受けるポートは環境変数PORTで渡されてくることがわかります2。またこの例を見るとstaticファイルはGAEにserveさせる方法もわかります。
https://github.com/GoogleCloudPlatform/ruby-docs-samples/tree/master/appengine/standard-hello_configs

GCPサービスのAPI

Rubyがスタンダード環境で動かせると言ってもGCPの各種サービスにアクセスできなければ意味がない、まあ究極的にはWeb APIなので自力で書くことはできますがライブラリがあるなら使いたい。
はい、あります。これも公式サンプルに用意されています。フレキシブル環境使ってますがスタンダード環境を使うように直すのは容易です。
https://github.com/GoogleCloudPlatform/ruby-docs-samples/tree/master/appengine/datastore

app.yamlを以下のように直してgcloud app deployするだけです。

app.yaml
runtime: ruby25
#env: flex
entrypoint: bundle exec ruby app.rb

Railsの動かし方

SinatraはいいからRailsはどう動かすんだという声が聞こえてきそうですが、あらかじめ言っておくと結構大変です(笑)

Railsなんだから当然データベース使いますよね。
ここで「無課金で動かす」は諦めてください。
GCPにはCloud SQLというRDBMS(MySQL or PostgreSQL)動かすサービスが提供されていますがお金かかります。
Cloud SQLはGCEのインスタンス立ててDB専用にするみたいな感じ、値段はそこそこのお値段になります3

現時点ではフレキシブル環境のサンプルしかありません。スタンダード環境とフレキシブル環境の違いがわかっていればこれを参考にして動かすことは可能です。ということで以下その方法です。
https://cloud.google.com/ruby/rails/using-cloudsql-postgres

Rails / GAEスタンダード環境デプロイ方法

基本的に上記のチュートリアルに沿って話を進めていきます。

1. Cloud SQLインスタンスを作成する

先に説明した、Railsで使うデータベースを作成します。
インスタンス作成→データベース作成の順番になります。インスタンス作成時のpostgresユーザパスワードはもちろん覚えておくように。

2. Railsアプリの用意

私は普段Windowsで生きてるのですがデプロイできるバージョン構成が作れなかったので結局Cloud ShellでRailsアプリを作成・デプロイを行いました。
2019/9/9時点でRailsは6.0.0が入っているのですが6.0.0で作ってデプロイしたところ動かせなかった4ので以下のようにGemfile書いて5.2.3入れて5.2.3でアプリを作りました。

Gemfile
source 'https://rubygems.org'

gem 'rails', '5.2.3'
$ bundle install
$ bundle exec rails new cat_sample_app

以降、scaffoldしてroute.rbを設定するところは普通のRailsアプリ通りです。

3. GAE用の設定を書く

チュートリアルにあるようにpgとappengineのgemを足します。

$ bundle add pg
$ bundle add appengine

次にconfig/database.ymlのproductionを設定します。「インスタンス接続名」はコマンドか管理画面で確認できます。
パスワード直書きとかm9(^Д^)プギャーという方は環境変数DATABASE_URLで指定できると思うので(未検証)、そちらで指定してください。ちなみに「/cloudsql/インスタンス接続名」とあるように接続はUNIXドメインソケットで行われます(実際にApp EngineとDBが同じマシン内で動くわけではないと思うのですが)

config/database.yml
production:
  adapter: postgresql
  encoding: unicode
  pool: 5
  timeout: 5000
  username: "postgres"
  password: "パスワード"
  database: "cat_list_production"
  host:   "/cloudsql/インスタンス接続名"

チュートリアルにはありませんが(フレキシブル環境だと必要ない?)、これ以外にGemfileでRubyのバージョンを指定しているのをコメントアウトする必要がありました。
スタンダード環境は2.5.5なので、それ以外が書いてあるとデプロイ時にエラーになります。

Gemfile先頭
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

#ruby '2.6.3'

4. app.yamlを書く

チュートリアルに書かれているのはフレキシブル環境用のapp.yamlなので、これをスタンダード環境用に書き換えます。cloud_sql_instancesは必要ありません。

app.yaml
entrypoint: bundle exec rackup --port $PORT
runtime: ruby25

env_variables:
  SECRET_KEY_BASE: 「bundle exec bin/rails secret」の結果

5. .gcloudignoreを用意する

.gcloudignoreはデプロイしないファイルを指定するものです。これがない場合ドット始まりのファイルが送信されないという仕様?なのかsprocketsが正常動作しませんでした。

.gcloudignore
#!include:.gitignore
.git
.gitignore

!/public/assets

6. デプロイ(まだ終わりじゃないよ)

App Engineアプリを作り、アセットをコンパイルし、デプロイします。チュートリアルでは--no-promoteが付いていますが初デプロイの場合は結局それがメインのバージョンになるので違いはありません。

$ gcloud app create
$ bundle exec bin/rails assets:precompile
$ gcloud app deploy

7. データベースマイグレーション

上で一度デプロイをしているのはCloud Buildのサービスアカウントを作るためです。Cloud Buildとは何ぞやということは末尾の参考記事をご参照ください。

プロジェクトIDだったりプロジェクト番号だったりでうっとうしいですが以下のようにして必要な権限を追加します。

$ gcloud projects add-iam-policy-binding プロジェクトID --member=serviceAccount:プロジェクト番号@cloudbuild.gserviceaccount.com --role=roles/editor

さてとデータベースマイグレーションです。ここで先ほど入れたappengine gemが出てきます。
何をしているのかというと、テンポラリのapp.yamlを作って、entrypointに指定されたコマンドを書いて実行して、デプロイされたテンポラリのバージョンを消すという超絶なことがされています(笑)
このappengine gemが2.5で追加されたメソッド使っているので5、デプロイする環境のRubyも2.5以上である必要があります。

$ bundle exec rake appengine:exec -- bundle exec rake db:migrate

以上でデプロイは終了です。

二回目以降のデプロイ

二回目からは以下のコマンドを打てばデプロイが行えます。

$ bundle exec bin/rails assets:precompile
$ gcloud app deploy
$ bundle exec rake appengine:exec -- bundle exec rake db:migrate

おわりに

以上、Google App Engineのスタンダード環境でRubyを使う場合を見てきました。
Node.jsと大体同じでした(広く使われている依存ライブラリの指定方法、起動プログラムは自分で指定、ポートは環境変数PORT)

触ってみた感想としては、Rails動かすのは特に無課金で使うつもりだったのなら諦めてHerokuを使え、GAE使うならDBはDatastore使ってフレームワークはSinatra使うのが楽だぞというところです。

参考というかこちらもどうぞの記事

Google App EngineのNode.js/Standard環境の仕組みについて調べてみた
Node.jsがスタンダード環境にデプロイされる仕組み(デプロイプロセスは何を行っているのか)を調べた記録です。Rubyでも大体同じ仕組みでデプロイが行われています。

GoogleAppEngineでDjangoを3年ほど動かしてわかったこと
思い出話ですがこの記事と関連する箇所としてはCloud SQLの話があります。


  1. ここで起動しているアプリサーバが直接リクエストを受けるわけではなくロードバランサがいてリクエストがフォワードされるわけですが、まあWEBrickよりはPumaの方がいいですよね。 

  2. 素のSinatraの場合は環境変数PORTを見ているのでentrypointで指定はされていませんでした。 

  3. MySQLはインスタンスのスペックを落とせますがPostgreSQLは最低スペックがメモリ3.75GBのようです。asia-northeastだと$64/月かかります。 

  4. tmp/pids/server.pidがない、ていうか、tmp/pidsがないというエラー。もう少し調べれば動かせるのかもしれませんが。 

  5. 具体的にはSecureRandom.alphanumeric。他にもあるかもしれません。 

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

基礎メンター試験

試験の内容

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

Ruby on Rails ページ 作成 する コマンド

目的

  • Ruby on Railsを使用したWebアプリ作成で新しいページを作成する際にコントローラファイルとアクションを新規作成するコマンドを知る

抑えるポイント

  • 紹介するコマンドはコントローラファイルが存在しない状態で新しくページを作成する際に使用できる。
  • コントローラファイルが既に存在していて、ビューファイルを作成したいときはコマンドでの作成はできない。

書き方の例

  • 下記コマンドを使用して新規ページを作成する。
rails g controller コントロールファイル名 記載されるアクション名

より具体的な例

  • uersコントローラファイルの中にeditアクションを新規追加したいときのコマンドを入力する。
rails g controller uers edit
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby入門2

こちらのメモは、『Udemy』の『Web開発入門完全攻略コース - プログラミングをはじめて学び創れる人へ!未経験から現場で使える開発スキルを習得!』で学習したものになります。
Ruby2.5.0
cloud9を利用。
irbを使用。

変数とは

変数名 = 式
例 
a = 100, name = 'aiueo',b = 10 * 3

  • 変数命名規則

アルファベットかアンダーバーで始まる文字を変数名で使用する。

age = 15
age_man = 35
メンテナンスが悪い書き方
_age = 29
age1 = 30
※実務上、原則変数名に数字を入れるのはやってはいけない。
※1age = 10 これはエラーとなる。
x = 123
x = 'aaa'
※このように同じ変数になんども数値を更新して、再代入は原則NG
x,j = 123,234
※実務上NG
a = b = 19
※実務上NG

定数

変化しない値、変化しにくい値を設定する。
大文字で始まる必要がある。
慣習として、すべて大文字で始まる必要がある。
一応できるのだが、再代入は、禁止。

TAX = 1.08 

リテラルとは

プログラムの中に直接記入できる値(数値、文字列、ハッシュ{連想配列})のことをいう。

用語解説

  • オブジェクト データと処理を集めたもの。
  • オブジェクト指向 複数のオブジェクトが互いに関係してることで、システムの動きをとらえる考え方。
  • クラス オブジェクトとの設計図。
  • インスタンス クラスから作成した結果、実態。
  • メソッド クラスの中に定義されているもので、複数の処理をまとめて扱いやすくすること

数値

  • + 足し算
  • - 引き算
  • * 掛け算
  • / 割り算
  • % 割った余りを計算
  • ** べき乗

文字列

  • 文字は、シングルクオートまたは、ダブルクオートで囲う。

例外

1.『\』 このバックスラッシュは、改行するという意味がある。しかし、シングルクオートで囲うと改行がされない。

2.文字列に#{}式展開をシングルクオートでやると式展開が表示されない。

  • 文字列の連結
    puts 'taro' + 'sato'
    この『+』を使うこで、文字列を連結することができる。

  • 文字列を変形

1.変数.to_s 数値を文字に変更する

2.変数.to_f 整数を小数点に変更する

3.変数.upcase 文字を大文字にする

4.3.変数.upcase! 文字を大文字にし、変数を大文字に変更する。

  • 変数の中身の検索等について age = '' age.empty? これで変数ageの中身が空か真偽値で確かめることができる。

age = '34'
age.include?('3')

これで変数ageの中身に『3』が入っているか真偽値で確かめることができる。

演算子による値の比較

  • 真、偽を確かめる条件式
  1. a < b aより大きい
  2. a > b bより小さい
  3. a <= b aと同じ、a以上
  4. a >= b aと同じ、a以下
  5. a == b aとbは等しい
  6. a != b aとbは異なる
  • 演算子の優先順位

『&&』は『||』より優先順位が高い。

x && y ||z
&&が優先されてしまう。
```x && (y || z)
このように明示的に優先順位をつけれる。

文字列の数値化

2 + '1'.to_i
文字列と数字は計算できないので、もしするなら数値化する必要がある。

number = 10
'Number is' + number.to_s

このように逆に数値を文字列化する場合もある。

2 + '1.1'.to_f
文字列が少数の場合は、こちらを使う。

インクリメントとデクリメント

  • インクリメント 値に1を足すこと。
  • デクリメント 値から1を引くこと。


n += 1
n -= 1

真偽値

  • falseかnilであれば偽(false)
  • それ以外は全て真(ture)

!変数
真と偽を反転できる。

論理演算子

複数の条件をまとめることができる。
- && (and)
a && b
aとbが真の時に真となる。
- || (or)
a || c
aとcのどちらかが真の場合にf真となる。

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

Chronicles of Ruby on Rails

Ruby was invented and released (Ruby 0.95) in 1995 by Yukihiro “Matz” Matsumoto in Japan and like any languages, it has undergone several changes in its avatar with the latest version to be 2.6.1. Rails were created in 2003 by David Heinemeier Hansson, while working on the code base for Basecamp, a project management tool, by 37signals. David extracted Ruby on Rails (RoR) and officially released it as open source code in July of 2004. RoR is not its own language and is a library of ruby gems. Similar to Ruby, the latest build is RoR 5.2.2.
Ruby on Rails is one of the highly valued skill in the startup ecosystem. The Rails framework is based on the principles of Convention over configuration.

Some of the outstanding qualities of Ruby on Rails:

• An easy programming language: First things first, one of the nice things about Ruby on Rails lies in the Ruby language itself. The syntax is simple, concise, close to the English language and very flexible. For experienced developers, Ruby opens the way for meta-programming (the act of writing code in order for your service to generate other pieces of code automatically) uniquely. Intellectually, it’s a pleasure to structure one’s thinking and to write code in this language.
• Flexibility: Any development will require elements like a database, a front-end and back-end. De facto, to get all the elements to blend and organise is a sweet spot for Rails.
• ToolKit: Once the setup and config are made, the toolset associated with Ruby on Rails is the simplest of all: a text editor, a terminal and a browser. No time wasted nor loading screen when coding. The automation testing tools let you test code throughout the development phase, saving time and costs for the overall project. This, in turn, helps in enhancing productivity because the code becomes easy to read and the framework is self-documenting.

One of the reasons why Ruby on Rails is still sought after, it helps the startups to get their product to market faster as it cuts down on development time.
• Development principles: Ruby on Rails has best practices imbibed to the framework. This allows distributed focus of time for every phase of the development cycle and testing. That apart enables fine-tuning before moving to a subsequent phase, delivers a better application with fewer bugs and errors.
• Open source: In addition to all of the benefits listed above, one of the best things about Ruby on Rails is that it’s opens source. Software licensing costs can be quite expensive and being able to use an open source solution that works as good as Ruby on Rails is a great way for startups to save costs.
• Community: Ruby on Rails is one of the most popular open source programming platforms used by programmers which has a very large and active online community. Through the multitudes of Ruby on Rails dedicated websites, chat rooms and forums, you have access to instant answers from people who have already experienced your problem and solved it. (ruby-lang, deccanruby, Bangalore-Ruby-Users-Group)

Now with such an edge over their counterparts, why Ruby on Rails is now considered dying?
The truth is Ruby ain’t dying, but maturing in a pattern similar to every other programming languages.
One cannot be oblivious to the fact that programming languages are tools to solve specific problems, and there is no such thing as the best programming language.

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

Rails6 のちょい足しな新機能を試す77(update_all 編)

はじめに

Rails 6 に追加された新機能を試す第77段。 今回は、 update_all 編です。
Rails 6 では、 update_all が楽観的ロックを配慮するようになりました。

Ruby 2.6.3, Rails 6.0.0, Rails 5.2.3 で確認しました。

$ rails --version
Rails 6.0.0

プロジェクトを作る

$ bin/rails new rails_sandbox
$ cd rails_sandbox

今回は、わざと StaleObjectError が発生するような更新処理のメソッドを作って確認します。

User モデルを作る

属性として、 name と age を持つ User モデルを作ります。
楽観的ロックの機能を使うため、 lock_version も追加します。

$ bin/rails g model User name age:integer lock_version:integer

seed データを作成

seed データを作成します。

db/seeds.rb
User.create!(
  [
    { name: 'Taro', age: 10 },
    { name: 'Jiro', age: 10 },
    { name: 'Hanako', age: 10 }
  ]
)

User モデルを修正する

Taro のレコードを検索します。
Taro と Hanako の age を update_all を使って 11 に更新します。
そのあと、StaleObjectError を発生させるために、検索したTaro の age だけ12 に更新します。

app/models/user.rb
class User < ApplicationRecord
  def self.update_age
    taro = User.find_by(name: 'Taro')
    where(name: %w[Taro Hanako]).update_all(age: 11)
    taro.age = 12
    taro.save! # => StaleObjectError
  end
end

seed データの投入

DB マイグレーションを実行しデータを登録します。

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

Rails Runner で確認する

Rails Runner で User.update_age を実行するとStaleObjectError が発生します。

$ bin/rails runner 'User.update_age'
...
27: from /app/models/user.rb:6:in `update_age'
...
/usr/local/bundle/gems/activerecord-6.0.0/lib/active_record/locking/optimistic.rb:95:in `_update_row': Attempted to update a stale object: User. (ActiveRecord::StaleObjectError)`

Rails Console で確認する

rails console で各レコードを確認すると、 Taro と Hanako の age が 11 に lock_version が 1 になっていることがわかります。 ( update_all は実行されているが、 save! メソッドは実行されていない )

irb(main):001:0> User.all.map{|u| [u.name, u.age, u.lock_version]}
  User Load (0.5ms)  SELECT "users".* FROM "users"
=> [["Jiro", 10, 0], ["Taro", 11, 1], ["Hanako", 11, 1]]

Rails 5 では

Rails 5.2.3 では、エラーは発生せず、最後まで実行されます。
Rails Console で確認すると、Hanako の lock_version は 0 のままで、 Taro の lock_version は、 1 になっています。
update_all で更新したときは、lock_version は変わらず、 save! メソッドで更新したときに lock_version が更新されるためです。

irb(main):001:0> User.all.map{|u| [u.name, u.age, u.lock_version]}
  User Load (0.4ms)  SELECT "users".* FROM "users"
=> [["Jiro", 10, 0], ["Hanako", 11, 0], ["Taro", 12, 1]]

試したソース

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

参考情報

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

Progateで作ったアプリをHerokuでデプロイしてたらテスト環境では動いたのにUnknownAttributeErrorをもらったから解決までの奮闘

デプロイはエラーとともに

【Ruby on Rails】スクールを超えるポートフォリオを実装する3STEP【実例あり】」を参考にして、progateで作ったアプリをHerokuでデプロイしていたら、エラーをいただきました。せっかくなので、備忘録がてら解決までにやったことを残しておこうと思います。何かしらの参考になれば幸いです。

環境
ruby 2.6.1
Rails 5.2.3
MacOS Mojave 10.14.6

見慣れぬ文字列

plogateのRailsアプリをローカル環境で作ってHerokuでデプロイしたら「UnknownAttributeError 'image_name' for User」。意味合いは「"image_name"カラムが"User"の中にないよ」ということらしい。そんなことは…ない…はず…?
でもエラーはエラーなので、「HerokuのDBにローカルPCからアクセスしたいんだけど...」の記事を参考にしてコマンドラインからデータベースのカラムを確認しました。

データベースの構成を確認
$ heroku pg:psql -c "-d"

 Schema |         Name         |   Type   |     Owner      
--------+----------------------+----------+----------------
 public | ar_internal_metadata | table    | hoge
 public | posts                | table    | hoge
 public | posts_id_seq         | sequence | hoge
 public | schema_migrations    | table    | hoge
 public | users                | table    | hoge
 public | users_id_seq         | sequence | hoge
(6 rows)

users(User)は存在してるので中身を確認…

Userの中を確認
$ heroku pg:psql -s "select * from users"
--> Connecting to ~~

 id | name | email  |         created_at         |         updated_at         
----+------+--------+----------------------------+----------------------------
  1 | aaa  | foo.jp | 2019-09-03 01:31:55.168638 | 2019-09-03 01:31:55.168638

無いですね?
パスワードとか、アイコン画像とかを保存しておくためのカラムがありません。確かに作ったはずなのに!
どうやら、データベースに変更があるデプロイをした時に、Heroku側のデータベースの更新を忘れていたようです!

更新、そして___

というわけで"heroku run rails migrate"を打ち込んで更新します…

更新
$ heroku run rails db:migrate
Running rails db:migrate on ⬢ hogehogeapp... up, run.7490 (Free)
~~

Runninng〜の後にズラズラーっと更新された内容が並んでいきます。
完了したら確認します。

再確認
$ heroku pg:psql -c "select * from users;"
--> Connecting to ~~
 id | name |  email  |      created_at     |      updated_at      |    image_name    |        password_digest                        
----+------+---------+----------------------------+----------------------------+-------------------------------------
  1 | aaa  | foo.jp  | 2019-09-08 20:14:50 | 2019-09-08 20:14:50. |                  | 

image_nameや、password_digestのカラムができていることが確認できます!!
しかしここで一つ問題があります...それは...

空のレコード

"password_digest","image_name"に空のレコードが入ってしまっていることです。これは良からぬエラーの原因になりますので解消しておかねば?
空白のカラムに対しては、レコードを追加するか、丸々削除するかが選べます…。今回は練習用のアプリでユーザー情報に全く意味はないので削除していきます。今回は"heroku run rails console"でHerokuの中のrails consoleを立ち上げ、データベースを変更していきます!

consoleの立ち上げ
$ heroku run rails console
Running rails console on 

〜〜〜〜〜
irb(main):001:0>

"irb(main):001:0>"←こんなのが出たら立ち上がってますので、空の情報を持ってるユーザーを削除します。
りょうたくさんのわかりやすいまとめを参考にしました!
参考:削除系メソッド(delete, delete_all, destroy, destroy_all)について

削除
irb(main):001:0> User.where(image_name: nil).destroy_all

これで全部削除できているはずですので、再々確認します

再々確認
$ heroku pg:psql -c "select * from users;"
--> Connecting to #"appに紐づくDB"
 id | name |  email  |         created_at         |         updated_at         |    image_name    |                       password_digest                        
----+------+---------+----------------------------+----------------------------+------------------+--------------------------------------------------------------
 (0 rows) 

0rows(データ無いよ!の意)が出たので成功です!
(有料区間なので表示はできませんが、)デプロイしたアプリのエラーも消えてました!!?<バンザイ!!

まとめ

今回のエラーで私が得るべき教訓は、データベースを更新したら中に入ってるデータも確認しておくことです?

次は自作で簡単なアプリを作るはずなので、そこでの奮闘も記事にできたらと思います。
書いた方がいいことや概念の間違いなどがあればお手数ですがコメントにてご教授ください!!
では!!

参照記事

HerokuのDBにローカルPCからアクセスしたいんだけど...
【Ruby on Rails】スクールを超えるポートフォリオを実装する3STEP【実例あり】
削除系メソッド(delete, delete_all, destroy, destroy_all)について

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

Ruby on Rails コマンドコンソールの使い分け

目的

  • Ruby on Railsで使用するコマンドの実行場所をまとめる
  • WindowsでのRuby on Railsの環境でのコマンド実行環境の使い分けをまとめる
    ※ほぼ自分用のメモです。もし間違えてる箇所ありましたら教えていただきたいです。

押さえるポイント

  • コマンドの実行環境はコマンドプロンプトとrailsコンソールの二種類がある。
  • Railsコンソールの起動はコマンドプロンプトにてコマンドrails consoleを実行すると起動する。
  • Webアプリ作成時のコマンドやファイル作成のコマンドはコマンドプロンプトで実行する。
  • Webアプリ内のデータのやり取りはrailsコンソールを使用する。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

deviseのヘルパーメソッドについて

deviseを導入した際に使えるようになる、便利なヘルパーメソッドについて、備忘録として投稿します。

deviseとは

ユーザーの新規登録、ログイン、ログアウトなど、認証に必要な機能を追加することができるgemです。

deviseの導入方法について

【参照】
https://qiita.com/cocoa-engineer/items/625da569fcac1ad2db1f

deviseのヘルパーメソッド

deviseを導入すると、以下の機能が使えるようになります。

メソッド 機能
before_action :authenticate_user! ログイン済ユーザーのみにアクセスを許可する
current_user 現在ログインしているユーザーを取得する
user_signed_in? ユーザーがサインインしているかどうかを判定する
user_session ユーザーのセッション情報にアクセスする

※「user」の部分はモデル名になるので、モデル名に応じて「user」部分を書き換えてください。

各ヘルパーメソッドの使い方については、以下のとおりです。

before_action :authenticate_user!

特定のアクションを、ログイン済みユーザーでないとアクセスできないようにするため、以下のようにコントローラ内に設定します。
※ログインしていない場合は、ログインページにリダイレクトされます。

class SampleController < ApplicationController
  before_action :authenticate_user!, only: [:show]

  def index
  end

  def show
  end
end

このようにonlyを使うと、showアクションはログイン済みユーザーのみアクセス可能とし、indexアクションはログインしていなくてもアクセスできるようになります。

また、以下のように、exceptを使っても同じことが書けます。

class SampleController < ApplicationController
  before_action :authenticate_user!, except: [:index]

  def index
  end

  def show
  end
end

current_user

現在ログインしているユーザーを取得できます。

idを取得する際は、「current_user.id」で取得できます。

<%= link_to "プロフィール", user_path(current_user.id) %>

user_signed_in?

ビュー等でcurrrent_userを使うと、ログインしていない場合エラーになってしまうので、このメソッドを使って条件分岐します。

<% if user_signed_in? %>
    <%= render 'layouts/login_user_header' %>
<% else %>
    <%= render 'layouts/no_login_user_header' %>
<% end %>

user_session

ユーザーのセッション情報にアクセスできます。

参考サイト

https://qiita.com/tobita0000/items/866de191635e6d74e392
https://qiita.com/k4ssyi/items/3edcd0e5373a41677dee

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

Rails6 のAction Textで保存した内容を文字列で読み出す。

試しに下記の形でusersテーブルのprofileカラムに保存したリッチテキストを文字列で読み出してみる。
スクリーンショット 2019-09-09 5.53.50.png

読み出す

$ rails c
pry(main)> User.last.profile.body.to_plain_text
=> "hogeほげ\n[8664c643-550521.png]fugaふが"

太字や斜体などの装飾情報はまた別に保存されているみたいだが、それ以外の情報については一応読み出せた。

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

Rails6 のAction Textで保存した内容を文字列で読み出す

試しに下記の形でUserモデルに追加したフィールドをprofileで参照できるようにしたリッチテキストを文字列で読み出してみる。

models/user.rb
class User < ApplicationRecord
  has_rich_text :profile
end

スクリーンショット 2019-09-09 5.53.50.png

読み出す

$ rails c
pry(main)> User.last.profile.body.to_plain_text
=> "hogeほげ\n[8664c643-550521.png]fugaふが"

太字や斜体などの装飾情報は別に保存されているみたいだが、それ以外の情報については読み出せた。

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

Rails6 のAction Textで保存したリッチテキストを文字列で読み出す

試しに下記の形でUserモデルにフィールドを追加したprofileで参照するリッチテキストを文字列で読み出してみる。

models/user.rb
class User < ApplicationRecord
  has_rich_text :profile
end

スクリーンショット 2019-09-09 5.53.50.png

読み出す

$ rails c
pry(main)> User.last.profile.body.to_plain_text
=> "hogeほげ\n[8664c643-550521.png]fugaふが"

太字や斜体などの装飾情報は別に保存されているみたいだが、それ以外の情報については読み出せた。

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

Array.newで配列を生成するときの注意点

配列の宣言と初期化

Rubyの配列の宣言と初期化方法は主に2つの方法があります。

  • Array.new(size, val)
  • Array.new(size){val}

の2種類です。

Array.new(size, val) で初期化する場合

数値で初期化する場合

例えば、要素10とし0で初期化する場合は

ary = Array.new 10, 0
#=> [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

先頭の要素を2に変更する

ary[0] = 2
ary #=> [2, 0, 0, 0, 0, 0, 0, 0, 0, 0]

数値で初期化する場合はArray.new(size, val)で問題ありません。
シンボルは数値と同じく不変なのでシンボルの場合でも問題ありません。
あとはnilとかも。

配列の中身が文字列の場合

配列の中身が文字列や配列の場合、問題が起こる場合があります。

問題にならない場合

ary = Array.new 10, "Hello"
#=> ["Hello", "Hello", "Hello", "Hello", "Hello", "Hello", "Hello", "Hello", "Hello", "Hello"]

さっきの例のように、末尾の要素を変更してみると、

ary[-1] = "Bye"
ary #=> ["Hello", "Hello", "Hello", "Hello", "Hello", "Hello", "Hello", "Hello", "Hello", "Bye"]

配列の要素が再定義される場合は問題ありません。

問題になる場合

先頭の文字列を1文字消したいのだが…

ary = Array.new 10, "Hello"
#=> ["Hello", "Hello", "Hello", "Hello", "Hello", "Hello", "Hello", "Hello", "Hello", "Hello"]
ary[0].chop!
ary #=> ["Hell", "Hell", "Hell", "Hell", "Hell", "Hell", "Hell", "Hell", "Hell", "Hell"]

すべての要素が変更されてしまいました。

ary #=> ["Hell", "Hell", "Hell", "Hell", "Hell", "Hell", "Hell", "Hell", "Hell", "Hell"]
ary[0][-1] = "p"
ary #=> ["Help", "Help", "Help", "Help", "Help", "Help", "Help", "Help", "Help", "Help"]

この場合もすべての要素が変更されます。

これは仕様です。

なぜ全部変わってしまうか

問題になる理由は、要素を破壊的に変更しているからです。つまり、要素の変更に破壊的メソッドを使っているから。
数値やシンボルが問題にならないのは、破壊ができないからです。

Rubyのリファレンスマニュアルにはこう書いてあります。

new(size = 0, val = nil) -> Array
長さ size の配列を生成し、各要素を val で初期化して返します。
要素毎に val が複製されるわけではないことに注意してください。 全要素が同じオブジェクト val を参照します。 後述の例では、配列の各要素は全て同一の文字列を指します。

引用: https://docs.ruby-lang.org/ja/latest/method/Array/s/new.html

要するにArray.new(size, val)で初期化した場合は要素の中身はすべて同じオブジェクトとなります。

ary = Array.new 3, "hogehoge"
ary.each{ |str| p str.object_id}
# 47194934685780
# 47194934685780
# 47194934685780

オブジェクトIDが全て同じものであると確かめられます。
破壊的メソッドはオブジェクトを破壊してしまい、配列の要素で参照しているオブジェクトはすべて同じなので全て書き換わってるように見えます。

ほかにも破壊が可能な配列やハッシュでも同じことが起きます。

対策

破壊的メソッドを使わなければ問題ないので、非破壊的メソッドを用いると回避することができます。

ary = Array.new 3, "foot"
ary[0] = ary[0].chop
ary
#=> ["foo", "foot", "foot"]

また、文字列をはじめから不変という扱いにすると、破壊しようした場合はエラーを出します。(Ruby2.3以上)

# frozen_string_literal: true

ary = Array.new 3, "Hello"
ary[0].chop!
# Traceback (most recent call last):
#         1: from test.rb:4:in `<main>'
# test.rb:4:in `chop!': can't modify frozen String (FrozenError)

もしくは末尾にfreezeつけるとか。

ary = Array.new 3, "Hello".freeze
ary[0].chop!
# Traceback (most recent call last):
#         1: from test.rb:2:in `<main>'
# test.rb:4:in `chop!': can't modify frozen String (FrozenError)

こうすると、配列やハッシュの場合でもできる。

Array.new(size){val} で初期化する場合

要素が配列やハッシュや文字列の場合は(追記)
Array.new(size){val}とすると、要素はすべて違うオブジェクトになるので
Array.new(size, val)とせずにArray.new(size){val}とするのが安全です。

new(size) {|index| ... } -> Array
長さ size の配列を生成し、各要素のインデックスを引数としてブロックを実行し、 各要素の値をブロックの評価結果に設定します。
ブロックは要素毎に実行されるので、全要素をあるオブジェクトの複製にすることができます。

引用: https://docs.ruby-lang.org/ja/latest/method/Array/s/new.html

ary = Array.new(3){"Hello"}
ary[0].chop!
p ary
# ["Hell", "Hello", "Hello"]

ちなみに、Array.new(size){|index| val}とすると、要素にインデックスの情報を含めることができます。

ary = Array.new(3){|i| "#{i+1}. Hello, world"}
puts ary
# 1. Hello, world
# 2. Hello, world
# 3. Hello, world
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

warning: already initialized constant FileUtils::VERSION

bundle updateしたせいかrails sするとなぜか、次のようなエラーを吐くようになってしまった。
気になるので調べてみた。

.rbenv/versions/2.6.3/lib/ruby/2.6.0/fileutils/version.rb:4: warning: already initialized constant FileUtils::VERSION
$ gem uninstall fileutils
Successfully uninstalled fileutils-1.2.0

$ gem update --default
Updating installed gems
Updating fileutils
Fetching fileutils-1.2.0.gem
Successfully installed fileutils-1.2.0
Done installing documentation for fileutils after 0 seconds
Done installing documentation for fileutils after 0 seconds
Gems updated: fileutils

$ rails s

# うまく行きました。

参考サイト
「rails s」でwarning: already initialized constantが出る : 新人SEの気まぐれ日記

Rails 5.2.0 with Ruby 2.5.1 console - `warning:` `already` initialized constant FileUtils::VERSION - Stack Overflow

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

rails-ujs.self 500 (Internal

Slimでフォームを作っていて追加処理したらJS側でエラーが吐かれた。

エラー文
rails-ujs.self  500 (Internal 

どうやらjsで重複してリクエストされているようだ。

app/assets/javascripts/application.js
//= require rails-ujs  # この行を削除する

//= require activestorage
//= require turbolinks
//= require jquery
//= require popper
//= require bootstrap
//= require_tree .

参考サイト
rails-ujsとjquery-ujsで2回リクエストが送られる - Qiita

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

bootstrap.self- Uncaught TypeError: Cannot read property 'fn' of undefined

エラー文
bootstrap.self-
Uncaught TypeError: Cannot read property 'fn' of undefined
app/assets/javascripts/application.js
//= require jquery
//= require popper
//= require bootstrap

# 順番を入れ替えて、これを一番したに書くようにする
# 読み込む順番があるらしい
//= require_tree .

参考サイト
RailsのbootstrapでUncaught TypeError: Cannot read property 'fn' of undefined at setTransitionEndSupport エラーが発生する 他。 - 技術系備忘録

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

rails rubyがインストールまたはバージョンアップ出来なかった場合の対応

僕自身ドットインストールを使ってRubyOnRaisの学習をしようと思った時インストールエラーが起きました。

そのときの対応策(解決方法)を書き込んで行きます。
その前にまだまだ初学者ですのでそちらは把握よろしくお願い致します。

1 RubyOnRaisのバージョン確認

ターミナル.
$ rails -v
Rails is not currently installed on this system. To get the latest version, simply type:

    $ sudo gem install rails


このシステムにレールは現在取り付けられていない。
最新バージョンを取得するには,次のように入力します。

$sudoの宝石取り付けレール

その後,"rails"コマンドを再実行できます。


っと出てきました。
そこで指示通り
$ sudo gem install rails
を入力してみました。

ターミナル.
$ sudo gem install rails
Password:〇〇
ERROR:  Error installing rails:
    zeitwerk requires Ruby version >= 2.4.4.

エラー: レールの取り付けエラー:
zeitwerkはRubyバージョン>=2.4.4が必要です。


っと言う事でした。

RubyOnRaisの前にruby自体のバージョン低いのがまず問題でしたのでアップデートしていきます。
その前にバージョンを確認することにしました。

2 Rubyのバージョン確認

ターミナル.
$ rbenv install --list
-bash: rbenv: command not found


-bash: rbenv: コマンドが見つかりません。


まずバージョン見れないですね、
そこでbrewのバージョンをアップデートしようと思いました。

ターミナル.
brew upgrade rbenv ruby-build
-bash: brew: command not found


エラーでこれも出来ず、


まずその前にHomebrewのrbenvが入ってないのかな?
っと思ったのでインストールします。

3 Homebrewダウンロード

Homebrewの公式サイトからターミナルに入力する部分を引っ張ってきてインストール。
ダウンロードは公式サイトを確認してください
https://brew.sh/index_ja.html

ざーっと文字が出まくって無事インストールが終わりました。

4 rbenvをインストール

次にrbenvをインストールしていきます。
rubyのversion管理を手伝ってくれるイケてるヤツらしいです。

ターミナル.
brew install rbenv ruby-build

わーーーーって文字がいっぱい出てきます笑
結構時間かかります、、
完了しました。
次にインストールするバージョン確認

ターミナル.
rbenv install -l

ここでも凄いいっぱい文字出てきますが落ち着いて
version指定してinstall

ターミナル.
rbenv install 2.5.1

rbenvでversion管理しちゃう
ターミナル.
rbenv global 2.5.1

環境のversion確認

ターミナル.
rbenv versions
system
* 2.5.1 (set by /Users/[user_name]/.rbenv/version)

(バージョンが変わらない場合)

上記でバージョンが変わっていなければ
rubyの場所を確認してください

ターミナル.
$ which ruby
/usr/bin/ruby
rbenvでRubyをバージョンアップする場合、
/Users/ユーザー/.rbenv/shims/ruby
を参照している必要があるので変更していきます。

$ rbenv init
# Load rbenv automatically by appending
# the following to ~/.bash_profile:

eval "$(rbenv init -)"

eval "$(rbenv init -)"をコピーして~/.bash_profileに追記します

ターミナル.
$ vi ~/.bash_profile

・
・
・
Swap file "~/.bash_profile.swp" already exists!
[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort: 

編集するので eキーをタイプ
vim画面に入ります。

vimについて
vim画面では「コマンドモード」と「挿入モード」があり、
最初はコマンドモードになっています。

編集するには挿入モードにする必要があるので
iキーかaキーを押すと、最下行に

-- INSERT --
と表示されます。これで挿入モードになっています。

先ほどコピーしたeval "$(rbenv init -)"を追記したら、
escキーを押してコマンドモードに戻ります。
:wqと入力してenterすると編集内容を保存して終了します。(カーソルが画面のどこにあっても大丈夫です。)

ちなみに、
保存せずに強制終了する場合は:q!と入力します。
もしless画面に入ってしまった場合はqで終了してください。

再度確認
元の画面に戻ったらまず変更を反映します。

ターミナル.
$ source ~/.bash_profile

再度Rubyのバージョンを確認

ターミナル.
$ ruby -v
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin16]

指定バージョンに変更されました。

5Ruby RubyOnRaisのダウンロード

そして1に戻って
エラーが起きていた入力を再度すると、、

ターミナル.
sudo gem install rails

しっかりダウンロード出来ました、

そしてRuby on Railsのインストール

ターミナル.
gem install rails -v 5.1.3 --no-document

ダウンロード出来ました

流れとしては
Raisバージョン確認出来ない/rubyのバージョンが低い/rubyアップグレードの為にHomebrewとbenvをインストール/rubyバージョンアップ/Raisインストール
ですね!

やり方として遠回りになったかもしれませんがしっかり対応出来たのでよかったです^^

まだまだ初学者ですので間違ってる可能性があります。
もし間違っている部分がありましたら指摘いただけるととてもありがたいと思いますのでその時はよろしくお願い致します。
長文になりましたがありがとうございました。

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

[Rails]credential.yml.encの編集方法

はじめに

Rails5.2以降でsecret.ymlファイルがない為、その記述の仕方などに苦戦したのでその記述方法について説明したいと思います。

credential.yml.encの編集方法

EDITOR=vim bin/rails credentials:editでcredential.yml.encを開く

EDITOR=vim bin/rails credentials:edit
# aws:
#   access_key_id: 123
#   secret_access_key: 345
以下略

記述方法

今回はgoogle apiのgoogle_client_idgoogle_client_secretを例に説明します。

# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: *******************************************************************************************************************************
development:
 google_client_id: ***************************.apps.googleusercontent.com
 google_client_secret: *********************

developmentと付けているのはローカルでのみ実装予定でしたので記述してあります。注意点としてはスペースの開け方に注意しないとエラーが出ますので気をつけましょう。最後に:wqで保存して終了です。

出来ない場合

もしcredential.yml.encがコマンドを入力しても編集出来ない場合、master.keyが違う場合があります。その場合はcredential.yml.encを削除しても問題無ければ削除し、新しくmaster.keyを生成し直します。
コマンドは先程と同じEDITOR=vim bin/rails credentials:editで生成出来ます。
そうする事で、master.keyが無ければ新しく生成する事が出来、編集も可能になります。
初期段階ならこの方法が早いかと思います。

まとめ

secrets.ymlで環境変数の定義など覚えていた為最初は苦戦しました。Versionが違うだけで仕様が変わる事のいい勉強になりました。
以下、参考にさせて頂いた資料です。
https://qiita.com/NaokiIshimura/items/2a179f2ab910992c4d39
https://qiita.com/scivola/items/cc06ddbfd94d3118f693#masterkey-%E3%82%92%E7%B4%9B%E5%A4%B1%E3%81%97%E3%81%9F%E3%82%89%E3%81%A9%E3%81%86%E3%81%AA%E3%82%8B2018-08-01-%E8%BF%BD%E8%A8%98

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

Rubyでクラスのメソッド呼び出しを全てロギングするには

  1. あるクラスの全てのメソッド呼び出しを、メソッドの処理を実行する直前にログに記録したい。しかし、すべてのメソッドの先頭にlogger.debugを追記したくはない。どうすれば良いか。

    • 書き出す内容は、クラス名・呼び出されたメソッド名・呼び出されたメソッドに渡された引数をinspectしたものとする
      • SomeClassのインスタンスメソッドsome_methodargsで呼び出した場合の出力例:
        • SomeClass#some_method(#{args.inspect相当の内容})
    • ロガーはinitializeメソッドの引数として注入されるものとし、ロガーのインターフェースはRubyの標準ライブラリのloggerに準ずるものとする。日時情報も出力されるため、自前でタイムスタンプを出力する必要はない
  2. 1.で作成したメソッド呼び出しデバッグの仕組みはたいそう有用だった。他のクラスにも使いたい。他のクラスで使うときに書き換える箇所を最小にできるよう、モジュール method_call_logger.rb として作成せよ。

    • 利用クラス側で書き換えるのは以下の箇所のみとする
      • A: ファイル先頭のファイルスコープのrequire
      • B: クラススコープ
      • C: initializeメソッド
  3. 2.までは、この機能をデバッグ用のものとしてログレベルがDEBUGの時のみ出力されるように実装してきた。しかし、一部のメソッドは非常に重要なため、ログレベルがINFOであっても出力したいという要望が挙げられた。指定した特定のメソッドのみの出力ログレベルを変更できるようにせよ。

    • 利用クラス側で出力ログレベルを変更するメソッドの指定は、B: クラススコープで行うものとする
require "method_call_logger" # A

class SomeClass
  # B

  def initialize(xxx, yyy, zzz, logger)
    # C
  end

  def some_method(arg)
    # ...
  end

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