- 投稿日:2019-09-09T23:13:05+09:00
ActiveRecordのvalidatesで表示されるエラーメッセージのフォーマットを変更する
何に困っているか
ActiveRecordのvalidatesでエラーになった時に表示されるメッセージを
%{attribute}%{message}
ではないフォーマットにしたい。
例えば、User.nameのvalidatesエラーでこの名前は1文字以上入力してください。
みたいなエラーメッセージを表示したい。
さらに、そのフォーマットを適用するスコープを限定したい。validatesのエラーメッセージを変更するには
0. サンプルアプリの概要
今回の環境は
ruby:2.5.2
、rails: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
を実行します。Gemfilegem 'rails-i18n`次に
config/application.rb
にi18nの設定を追加します。config/application.rbmodule 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.ymlja: 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.rbclass 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.rbclass 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 endconfig.active_model.i18n_customize_full_messageはデフォルトがfalseなので、この設定を実施しておかないと機能しません。(これに気づかずにハマりました・・・)
エラーメッセージのフォーマットを以下の通り設定します。
config/local/models/ja.ymlja: activerecord: models: user: ユーザー attributes: user: name: 名前 errors: models: user: attributes: name: format: '%{message}' blank: この%{attribute}は1文字以上入力してください。ちなみにUserモデルは下の通りです。
app/models/user.rbclass 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文字以上入力してください。"]遂に目的を達成する実装にたどり着くことが出来ました
![]()
一応、サンプルコードをGitHubに置いてます。
参考文献
https://qiita.com/Ushinji/items/242bfba84df7a5a67d5b
https://qiita.com/suketa/items/5af12acd88ebc8a2a1a5
- 投稿日:2019-09-09T22:58:32+09:00
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
を実行すれば、通常通りコンテナが生成されるようになります。
- 投稿日:2019-09-09T21:49:52+09:00
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.yamlruntime: 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_configsGCPサービスのAPI
Rubyがスタンダード環境で動かせると言ってもGCPの各種サービスにアクセスできなければ意味がない、まあ究極的にはWeb APIなので自力で書くことはできますがライブラリがあるなら使いたい。
はい、あります。これも公式サンプルに用意されています。フレキシブル環境使ってますがスタンダード環境を使うように直すのは容易です。
https://github.com/GoogleCloudPlatform/ruby-docs-samples/tree/master/appengine/datastoreapp.yamlを以下のように直して
gcloud app deploy
するだけです。app.yamlruntime: ruby25 #env: flex entrypoint: bundle exec ruby app.rbRailsの動かし方
SinatraはいいからRailsはどう動かすんだという声が聞こえてきそうですが、あらかじめ言っておくと結構大変です(笑)
Railsなんだから当然データベース使いますよね。
ここで「無課金で動かす」は諦めてください。
GCPにはCloud SQLというRDBMS(MySQL or PostgreSQL)動かすサービスが提供されていますがお金かかります。
Cloud SQLはGCEのインスタンス立ててDB専用にするみたいな感じ、値段はそこそこのお値段になります3。現時点ではフレキシブル環境のサンプルしかありません。スタンダード環境とフレキシブル環境の違いがわかっていればこれを参考にして動かすことは可能です。ということで以下その方法です。
https://cloud.google.com/ruby/rails/using-cloudsql-postgresRails / 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でアプリを作りました。Gemfilesource '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.ymlproduction: 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.yamlentrypoint: 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/assets6. デプロイ(まだ終わりじゃないよ)
App Engineアプリを作り、アセットをコンパイルし、デプロイします。チュートリアルでは--no-promoteが付いていますが初デプロイの場合は結局それがメインのバージョンになるので違いはありません。
$ gcloud app create $ bundle exec bin/rails assets:precompile $ gcloud app deploy7. データベースマイグレーション
上で一度デプロイをしているのは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の話があります。
ここで起動しているアプリサーバが直接リクエストを受けるわけではなくロードバランサがいてリクエストがフォワードされるわけですが、まあWEBrickよりはPumaの方がいいですよね。 ↩
素のSinatraの場合は環境変数PORTを見ているのでentrypointで指定はされていませんでした。 ↩
MySQLはインスタンスのスペックを落とせますがPostgreSQLは最低スペックがメモリ3.75GBのようです。asia-northeastだと$64/月かかります。 ↩
tmp/pids/server.pidがない、ていうか、tmp/pidsがないというエラー。もう少し調べれば動かせるのかもしれませんが。 ↩
具体的にはSecureRandom.alphanumeric。他にもあるかもしれません。 ↩
- 投稿日:2019-09-09T19:29:11+09:00
Ruby on Rails ページ 作成 する コマンド
目的
- Ruby on Railsを使用したWebアプリ作成で新しいページを作成する際にコントローラファイルとアクションを新規作成するコマンドを知る
抑えるポイント
- 紹介するコマンドはコントローラファイルが存在しない状態で新しくページを作成する際に使用できる。
- コントローラファイルが既に存在していて、ビューファイルを作成したいときはコマンドでの作成はできない。
書き方の例
- 下記コマンドを使用して新規ページを作成する。
rails g controller コントロールファイル名 記載されるアクション名より具体的な例
- uersコントローラファイルの中にeditアクションを新規追加したいときのコマンドを入力する。
rails g controller uers edit
- 投稿日:2019-09-09T17:42:56+09:00
Railsのスキーマダンプを作成してみた
rails db:migrate
で作成されるスキーマダンプは2種類あるということで、
作成してみました。スキーマダンプの設定の仕方
config/application.rb
で、下記を設定をする
config.active_record.schema_format = :ruby
config.active_record.schema_format = :sql
(デフォルトは
:ruby
)config/application.rbrequire_relative 'boot' require 'rails/all' # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) module Myapp class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. config.load_defaults 5.2 # Settings in config/environments/* take precedence over those specified here. # Application configuration can go into files in config/initializers # -- all .rb files in that directory are automatically loaded after loading # the framework and any gems in your application. config.active_record.schema_format = :ruby <- これを追加する end end実行するマイグレーションファイル
マイグレーションファイルclass CreateUsers < ActiveRecord::Migration[5.2] def change create_table :users do |t| t.string :name t.integer :age t.timestamps end end end
config.active_record.schema_format = :ruby
でdb:magrate
するdb/schema.rb# This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. # # Note that this schema.rb definition is the authoritative source for your # database schema. If you need to create the application database on another # system, you should be using db:schema:load, not running all the migrations # from scratch. The latter is a flawed and unsustainable approach (the more migrations # you'll amass, the slower it'll run and the greater likelihood for issues). # # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema.define(version: 2019_09_09_065249) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" create_table "users", force: :cascade do |t| t.string "name" t.integer "age" t.datetime "created_at", null: false t.datetime "updated_at", null: false end end
- テーブルを作成する部分が
ruby
で書かれてすごくシンプルcreate_table "users", force: :cascade do |t| t.string "name" t.integer "age" t.datetime "created_at", null: false t.datetime "updated_at", null: false end
config.active_record.schema_format = :sql
でdb:migrate
するstructure.sqlSET statement_timeout = 0; SET lock_timeout = 0; SET idle_in_transaction_session_timeout = 0; SET client_encoding = 'UTF8'; SET standard_conforming_strings = on; SELECT pg_catalog.set_config('search_path', '', false); SET check_function_bodies = false; SET xmloption = content; SET client_min_messages = warning; SET row_security = off; SET default_tablespace = ''; SET default_with_oids = false; -- -- Name: ar_internal_metadata; Type: TABLE; Schema: public; Owner: - -- CREATE TABLE public.ar_internal_metadata ( key character varying NOT NULL, value character varying, created_at timestamp without time zone NOT NULL, updated_at timestamp without time zone NOT NULL ); -- -- Name: schema_migrations; Type: TABLE; Schema: public; Owner: - -- CREATE TABLE public.schema_migrations ( version character varying NOT NULL ); -- -- Name: users; Type: TABLE; Schema: public; Owner: - -- CREATE TABLE public.users ( id bigint NOT NULL, name character varying, age integer, created_at timestamp without time zone NOT NULL, updated_at timestamp without time zone NOT NULL ); -- -- Name: users_id_seq; Type: SEQUENCE; Schema: public; Owner: - -- CREATE SEQUENCE public.users_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; -- -- Name: users_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - -- ALTER SEQUENCE public.users_id_seq OWNED BY public.users.id; -- -- Name: users id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY public.users ALTER COLUMN id SET DEFAULT nextval('public.users_id_seq'::regclass); -- -- Name: ar_internal_metadata ar_internal_metadata_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY public.ar_internal_metadata ADD CONSTRAINT ar_internal_metadata_pkey PRIMARY KEY (key); -- -- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY public.schema_migrations ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version); -- -- Name: users users_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY public.users ADD CONSTRAINT users_pkey PRIMARY KEY (id); -- -- PostgreSQL database dump complete -- SET search_path TO "$user", public; INSERT INTO "schema_migrations" (version) VALUES ('20190909065249');すごくながい…
:ruby
と違って、DBの設定やシーケンスまで、記載されている。終わり
みんなはどうやって使い分けているんだろう?
- 投稿日:2019-09-09T17:05:38+09:00
[Rails]devise機能でログインIDをusernameにしたらエラーになった
deviseでログインIDをusernameにしたらエラー
Railsで新規登録&ログイン実装をするのに便利な機能であるdeviseを使用するにあたって、ログインIDがデフォルトではEmailとなっているので、これをusernameにしたい。
ということで、こちらの記事を参考に変更していった。
Railsのログイン認証gemのDeviseのカスタマイズ方法これで簡単にusernameをログインID に設定できたと思いきや、
新規登録の際にこんなエラーが。。
全項目しっかり埋めても
Email can’t be blank
となってしまう。Validateは
validates :username, presence: true, uniqueness: true
だけなので、Emailに関して特に変更した記憶はない。※usernameのカラムを追加する前はEmailで異常なく新規登録できていた。
なんとか解決できたので、解決策を自分のメモとして残しておきます。
解決策
devise
can’t be blank
で検索をかけるとStrongParameterの設定に関しての情報がやたら出てくる。しかし、その書き方は多種多様。
そして、どれを試しても結果変わらずであったり、別のエラーを引き起こしたりで、上手くいかないなぁと感じていたところで
こちらのStrongParameterを実装してみた。
※Publifyでユーザー登録するとCan’t be blankエラーの対応参照controllers/application_controller.rbclass ApplicationController < ActionController::Base protect_from_forgery with: :exception before_action :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters added_attrs = [:user_name, :email, :password, :password_confirmation, :remember_me] devise_parameter_sanitizer.permit :sign_up, keys: added_attrs devise_parameter_sanitizer.permit :account_update, keys: added_attrs end endこれだとエラーを起こすことなく、無事登録できました。
- 投稿日:2019-09-09T16:59:30+09:00
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.
- 投稿日:2019-09-09T16:17:19+09:00
[Rails] or を inject でチェーンする
例
app/models/character.rbclass Character < ApplicationRecord enum sex: { male: 1, female: 2 } scope :by_name, (lambda do |*names| names.inject(none) do |relation, name| relation.or(where("#{table_name}.name LIKE ?", "%#{name}%")) end end) endCharacter.female.by_name('さ', '杏').pluck(:name) # SELECT characters.name FROM characters # WHERE characters.sex = 2 # AND (((characters.name LIKE '%さ%') OR ((characters.name LIKE '%杏%')) #=> ["百江なぎさ", "美樹さやか", "佐倉杏子"]解説
Enumerable#inject の第 1 引数の
none
がポイント。none
をself
にすると# ALL or 条件 1 or 条件 2 or ... Character.all.or(Character.where('条件 1')).or(Character.where('条件 2'))).or(...)と解釈されて、その結果 OR 条件が消えてしまう。
- 投稿日:2019-09-09T16:03:03+09:00
初心者が初めてrailsアプリをherokuにデプロイしてつまずいた所
環境
Rails 5.2.3
Ruby 2.4.1つまずいた所
背景画像が表示されない
url
をimage-url
に変えたら反映されました。background-image:image-url('main.jpg');assetが更新されない
herokuは自動でprecompileしてくれるので、
bundle exec rake assets:precompile RAILS_ENV=production
をする必要はありません。反対に一度このコマンドを実行すると、毎回行う必要があります。その際は作成されたpublic/assets
を削除してしまいましょう。データベースが存在しない
当たり前ですが、本番環境用のdatabaseは違うので、migarationファイルを実行する必要があります。
$ git push heroku $ heroku run rails db:migrate $ heroku run rails db:seed (初期データある場合)本番環境ではsqliteは使えない事も注意です!!
コードの変更が反映されない
単純にコミットできていなだけでした。。。
みなさんもこういう初歩的なミスに気をつけてください。以上です。とりあえずなんとかデプロイできてよかった...
- 投稿日:2019-09-09T12:37:26+09:00
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.rbUser.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.rbclass 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 endseed データの投入
DB マイグレーションを実行しデータを登録します。
bin/rails db:create db:migrate db:seedRails 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参考情報
- 投稿日:2019-09-09T12:12:40+09:00
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)について
- 投稿日:2019-09-09T10:47:22+09:00
Ruby on Rails コマンドコンソールの使い分け
目的
- Ruby on Railsで使用するコマンドの実行場所をまとめる
- WindowsでのRuby on Railsの環境でのコマンド実行環境の使い分けをまとめる
※ほぼ自分用のメモです。もし間違えてる箇所ありましたら教えていただきたいです。押さえるポイント
- コマンドの実行環境はコマンドプロンプトとrailsコンソールの二種類がある。
- Railsコンソールの起動はコマンドプロンプトにてコマンド
rails console
を実行すると起動する。- Webアプリ作成時のコマンドやファイル作成のコマンドはコマンドプロンプトで実行する。
- Webアプリ内のデータのやり取りはrailsコンソールを使用する。
- 投稿日:2019-09-09T09:46:55+09:00
config.hosts Rails 6
この記事ではRails6でのconfig.hostsの追加方法を記載します。
バージョン情報
rails 6.0.0
Ruby 2.6.3config.hostsの追加
"hostname"の箇所はドメイン名に読み替えてください。
config/application.rbに追加しました。
config/environments/development.rbに追加する方法も他の記事で紹介してありましたが、私の環境では上手く動作しませんでした。example-app/config/application.rbmodule ExampleApp class Application < Rails::Application config.load_defaults 6.0 config.hosts << "hostname" end下記の記事を参考にしました。
https://www.fngtps.com/2019/rails6-blocked-host/
https://qiita.com/taiteam/items/a37c60fc15c1aa5bb606
https://github.com/rails/rails/pull/33145
- 投稿日:2019-09-09T06:18:31+09:00
Rails6 のAction Textで保存した内容を文字列で読み出す
- 投稿日:2019-09-09T06:18:31+09:00
Rails6 のAction Textで保存したリッチテキストを文字列で読み出す
- 投稿日:2019-09-09T05:08:31+09:00
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の気まぐれ日記
- 投稿日:2019-09-09T04:59:00+09:00
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 .
- 投稿日:2019-09-09T04:52:10+09:00
bootstrap.self- Uncaught TypeError: Cannot read property 'fn' of undefined
エラー文bootstrap.self- Uncaught TypeError: Cannot read property 'fn' of undefinedapp/assets/javascripts/application.js//= require jquery //= require popper //= require bootstrap # 順番を入れ替えて、これを一番したに書くようにする # 読み込む順番があるらしい //= require_tree .
- 投稿日:2019-09-09T03:33:04+09:00
[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_id
とgoogle_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