- 投稿日:2019-02-28T23:52:55+09:00
railsでIndex name 'xxxxxxxxxxxxxxxxxxx' on table 'テーブル名' is too long; the limit is 64 characters
経緯
railsのmigrationで
Index name 'xxxxxxxxxxxxxxxxxxx' on table 'テーブル名' is too long; the limit is 64 characters
と怒られる
テーブル名、カラム名などなどが長くなり、自動付与されるインデックス名が長くなりすぎることが原因対応
t.references :my_field, index: { name: 'my_index_name' }
でindex名を指定してやればOK!add_indexでindexを別で設定する場合は以下の記事を参考
https://qiita.com/ezawa800/items/9a63a96fb36a7c1de04d参考
- 投稿日:2019-02-28T23:50:43+09:00
Railsチュートリアルに再挑戦する
前に挫折してしまったRailsチュートリアルに再挑戦してみようと思います。
過度に完璧主義にならずに、適度にサボりながら周回を重ねていこうと思います。
testは後回しにしたり、課題を後回しにしたり、後回しでもいいと言われたところは後回しにしたり。
まずは一周して全体を掴んでいこうと思います。
1周目はCloud9で、2周目以降はローカル開発に挑戦していきたいですね。
- 投稿日:2019-02-28T23:39:15+09:00
Rails開発の初期設定で参考になった記事まとめ
Railsのインストール
過去の記事をご覧ください(Railsインストール)
MySQLに変更する方法
過去の記事をご覧ください(DBをMySQLに変更)
日本語化
Rails5からは
application.rb
では設定できないので注意しよう。新しいファイルを追加して以下のように設定しよう。ja.yml
に関しては同じように設定できる。initializers/locals.rbI18n.config.available_locales = :ja I18n.default_locale = :jaRailsの基本的な概念
※viewは対応するコントローラーのアクションで定義された変数が使えてRubyが埋め込めることがわかればとりあえずいいと思うので省略。
GitHub関連
GitHubの使い方はこのあたりが良かった。ssh通信の公開鍵の登録についてはこのあたりが参考になった。また、パスワードなどの機密情報が書かれているファイルは、GitHubで公開することは避けよう(
.gitignore
をいじれば同期するものを制限できる)。Bootstrap
- 投稿日:2019-02-28T23:06:27+09:00
hevens_doorを使ってみた
はじめに
Rails/Rubyのコミッターであるa_matsudaさんが制作されているheavens_doorのチュートリアル記事です
実際のデモ
実際にはこんな感じで動作します
なお、実際に作ったものはこちら
チュートリアル
rails new
まずは、
rails new
でheavens_door
を試すサンプルアプリを作りますrails new heavens_doorcapybaraの導入
次に、
capybara
を導入しますGemfilegem 'capybara', '>= 2.15', group: :developmentそのあと、
bundle install
を実行しますbundle install
テスト用CRUD作成
テストするためのCRUDを作成します
rails g scaffold post title contentその後、
rails db:migrate
を実行しますrails db:migrate RAILS_ENV=testheavens_doorの導入
heavens_door
を導入したいと思います!
Gemfile
にheavens_door
を追加しますGemfilegem 'heavens_door', group: :development
bundle install
でgem
をインストールしますbundle install
heavens_doorを使う
最後に、
heavens_door
を使ってみましょう!まず、
test/intgration/posts_test.rb
を作成し、以下のようにしますtest/intgration/posts_test.rbrequire 'capybara/rails' require 'capybara/minitest' class ActionDispatch::IntegrationTest include Capybara::DSL include Capybara::Minitest::Assertions def heavens_door end endその後、
rails s
でローカルサーバを起動し、localhost:3000/posts
にアクセスしますrails sあとは画面右上に表示されているボタンをクリックするとUI操作の記録がはじまります
適当に操作したあと、バインダーマークをクリックするとUIテストのコードがクリップされます
あとは、
test/intgration/posts_test.rb
にクリップしたコードを貼り付けますtest/intgration/posts_test.rbrequire 'capybara/rails' require 'capybara/minitest' class ActionDispatch::IntegrationTest # Make the Capybara DSL available in all integration tests include Capybara::DSL # Make `assert_*` methods behave like Minitest assertions include Capybara::Minitest::Assertions # Reset sessions and driver between tests # Use super wherever this method is redefined in your individual test classes def heavens_door scenario 'GENERATED' do visit '/posts' click_link 'New Post' fill_in 'Title', with: 'test' fill_in 'Content', with: 'aaaaaaaaaaaaaaaaaaaaaaaaa' click_button 'Create Post' click_link 'Back' end end end最後に、
rails test
を実行してくださいrails test
テストが実行されていればOKです!
参考
- 投稿日:2019-02-28T23:06:27+09:00
heavens_doorを使ってみた
はじめに
Rails/Rubyのコミッターであるa_matsudaさんが制作されているheavens_doorのチュートリアル記事です
実際のデモ
実際にはこんな感じで動作します
なお、実際に作ったものはこちら
チュートリアル
rails new
まずは、
rails new
でheavens_door
を試すサンプルアプリを作りますrails new heavens_doorcapybaraの導入
次に、
capybara
を導入しますGemfilegem 'capybara', '>= 2.15', group: :developmentそのあと、
bundle install
を実行しますbundle install
テスト用CRUD作成
テストするためのCRUDを作成します
rails g scaffold post title contentその後、
rails db:migrate
を実行しますrails db:migrate RAILS_ENV=testheavens_doorの導入
heavens_door
を導入したいと思います!
Gemfile
にheavens_door
を追加しますGemfilegem 'heavens_door', group: :development
bundle install
でgem
をインストールしますbundle install
heavens_doorを使う
最後に、
heavens_door
を使ってみましょう!まず、
test/intgration/posts_test.rb
を作成し、以下のようにしますtest/intgration/posts_test.rbrequire 'capybara/rails' require 'capybara/minitest' class ActionDispatch::IntegrationTest include Capybara::DSL include Capybara::Minitest::Assertions def heavens_door end endその後、
rails s
でローカルサーバを起動し、localhost:3000/posts
にアクセスしますrails sあとは画面右上に表示されているボタンをクリックするとUI操作の記録がはじまります
適当に操作したあと、バインダーマークをクリックするとUIテストのコードがクリップされます
あとは、
test/intgration/posts_test.rb
にクリップしたコードを貼り付けますtest/intgration/posts_test.rbrequire 'capybara/rails' require 'capybara/minitest' class ActionDispatch::IntegrationTest # Make the Capybara DSL available in all integration tests include Capybara::DSL # Make `assert_*` methods behave like Minitest assertions include Capybara::Minitest::Assertions # Reset sessions and driver between tests # Use super wherever this method is redefined in your individual test classes def heavens_door scenario 'GENERATED' do visit '/posts' click_link 'New Post' fill_in 'Title', with: 'test' fill_in 'Content', with: 'aaaaaaaaaaaaaaaaaaaaaaaaa' click_button 'Create Post' click_link 'Back' end end end最後に、
rails test
を実行してくださいrails test
テストが実行されていればOKです!
参考
- 投稿日:2019-02-28T22:58:00+09:00
【OmniAuth + Devise】Twitterのログイン認証をテストする方法【Rspec】
はじめに
仕事でAuth認証のspecを書く場面があったので、いろいろハマったことも含め簡潔に書いていきたいと思います。
【実行環境】
・ Rails 5.1.4
・ RSpec 3.7
・ Ruby 2.4.3ざっくり実装の手順
- Rspecのセットアップ
- モックの作成
- Controllerの認証テスト
【前提】omniauthのルート設定
複数モデルで実装する方も多いと思うので、
Omniauthの認証処理はAuthenticationsController
でやるとします。config/routes.rbget "auth/:provider" => "authentications#new", as: :new_authentication get "auth/:provider/callback" => "authentications#create", as: :create_authentication参考: https://github.com/plataformatec/devise/wiki/OmniAuth-with-multiple-models
テストするもの
・Authが正常に渡ってきたときの処理(
create
アクション)
・Authが渡って来なかったときのエラーハンドリング(create
アクション)
・Auth認証に失敗した時の処理(failure
アクション)app/controllers/authentications_controller.rbclass AuthenticationsController < ApplicationController # get "auth/:provider" # def new ← omniauthにより、newアクションは自動生成される # end # get "auth/:provider/callback" def create raise "request.env[omniauth.auth]がありません" if auth_params.nil? @social_profile = SocialProfile.new.set_value(auth_params) @user = User.new(emial: @social_profile.email) if @user.save @social_profile.save! redirect_to edit_uer_registratiion_url else redirect_to new_user_registration_path end end # callbackに失敗したときに呼ばれるアクション def failure redirect_to user_setting_social_profiles_path if current_user end private # ユーザー情報の入った def auth_params request.env["omniauth.auth"] end end肝となるのはやはり
request.env["omniauth.auth"]
です。
今回テストすべきなのはauth/:provider/callback
を叩いた時に正常にユーザーデータが渡ってくるかなので、ここでいう、create
アクションのspecを主に書いていこうと思います。Rspecのセットアップ
まずは
OmniAuth
をテストモードに変えておきましょう。
また、devise
のヘルパーを使う場合は、それぞれ設定しておきます。spec/rails_helper.rb# OmniAuthをテストモードに変更 OmniAuth.config.test_mode = true RSpec.configure do |config| # FactoryBotの記述省略 config.include FactoryBot::Syntax::Methods # deviseで使うヘルパー config.include Devise::Test::ControllerHelpers, type: :controller config.include Devise::Test::IntegrationHelpers, type: :request endテストで用意するデータ
ユーザーデータのハッシュが入ってるのが、
request.env["omniauth.auth"]
なので、
そのユーザーデータを擬似的に作ってテストしてあげればOK。本来
request.env["omniauth.auth"]
にどんなハッシュが渡ってくるかは以下を参考に↓
https://github.com/arunagw/omniauth-twitter#authentication-hashそのために、認証用のモックを作っていきます。
モックの作成
request.env["omniauth.auth"]
に入れるモックを作成しましょう。どこでも使うので
spec/rails_helper.rb
に記述してもいいですが、結構長いので今回はspec/support/omniauth_mocks.rb
に書いて最後にincludeするようにします。spec/support/omniauth_mocks.rbmodule OmniauthMocks def twitter_mock OmniAuth.config.mock_auth[:twitter] = OmniAuth::AuthHash.new({ "provider" => "twitter", "uid" => "123456", "info" => { "name" => "Mock User", "image" => "http://mock_image_url.com", "location" => "", "email" => "mock@example.com", "urls" => { "Twitter" => "https://twitter.com/MockUser1234", "Website" => "" } }, "credentials" => { "token" => "mock_credentails_token", "secret" => "mock_credentails_secret" }, "extra" => { "raw_info" => { "name" => "Mock User", "id" => "123456", "followers_count" => 0, "friends_count" => 0, "statuses_count" => 0 } } }) end endspec/rails_helper.rbRSpec.configure do |config| config.include OmniauthMocks endコントローラで認証処理をテストする
コールバックが呼ばれたときに、以下の内容をテストします。
・ authが渡ってこなければエラーを起こす
・ authが渡ってこれば各モデルが作成されること
・ authにemailが含まれてなければ再度認証画面にリダイレクトさせることapp/controllers/authentications_controller.rbclass AuthenticationsController < ApplicationController # get "auth/:provider/callback" def create raise "request.env[omniauth.auth]がありません" if auth_params.nil? @social_profile = SocialProfile.new.set_value(auth_params) @user = User.new(emial: @social_profile.email) if @user.save @social_profile.save! redirect_to edit_uer_registratiion_url else redirect_to new_user_registration_path end private # ユーザー情報の入った def auth_params request.env["omniauth.auth"] end endRspec↓
spec/controllers/authentications_controller_spec.rbrequire 'rails_helper' RSpec.describe AuthenticationsController, type: :controller do before { request.env["omniauth.auth"] = twitter_mock } subject { get :create, params: { provider: "twitter" } } it "oauthが渡ってこない場合エラーになる" do request.env["omniauth.auth"] = nil expect { subject }.to raise_error("request.env[omniauth.auth]がありません") end context "emailがある場合" do it "新規作成" do expect { subject }.to change { User.count }.from(0).to(1) expect { subject }.to change { SocialProfile.count }.from(0).to(1) expect(subject).to redirect_to edit_user_registration_url end end context "emailがない場合" do it "登録画面へリダイレクト" do request.env["omniauth.auth"]["info"]["email"] = nil expect(subject).to redirect_to new_user_registration_path end end end①request.env["omniauth.auth"]に先ほど作ったユーザーデータの入ったハッシュ型のモック(
twitter_mockd
)が入る。②一つ目のexample →
request.env["omniauth.auth"] = nil
とすることで、authが渡って来なかったと判断し、エラーを吐く。③2つ目のexample →
auth_params
にモックが入ってるので、欲しいデータがしっかり入っていれば正常にsave(作成)される。④3つ目のexample →
request.env["omniauth.auth"]["info"]["email"] = nil
で、モックのeamilを空にする。この状態でリクエストを送ればモデルは作成されずリダイレクトされる.認証失敗時のテスト
callbackが失敗した時、どこにリダイレクトすればいいのかは
config/initializers/omniauth.rb
で設定できます。config/initializers/omniauth.rbRails.application.config.middleware.use OmniAuth::Builder do provider :twitter, Settings.oauth.twitter.consumer_key, Settings.oauth.twitter.consumer_secret on_failure do |env| AuthenticationsController.action(:failure).call(env) ##ここで設定 end end今回は
AuthenticationsController
のfailure
アクションが呼ばれるように設定したので、AuthenticationsController
でテストしてみることにします。app/controllers/authentications_controller.rbclass AuthenticationsController < ApplicationController # ...省略 def failure redirect_to user_setting_social_profiles_path if current_user end endじゃあコールバックを失敗させるにはどうすればいいかというと、失敗用のモックをまた別に作ってあげる必要があります。
spec/support/omniauth_mocks.rbmodule OmniauthMocks # ...省略 def twitter_invalid_mock OmniAuth.config.mock_auth[:twitter] = :invalid_credentails end endこのモックを使ってコールバックを叩けば
failure
にリダイレクトさせることができます。
参考: https://github.com/omniauth/omniauth/wiki/Integration-Testing#mocking-failureコールバック失敗時のテストコードを書いてみる
早速
failure
アクションのテストがしたいから、get :failure, params: { provider: "twitter" }みたいな感じに書いてみましたが、「そんなルートねぇよ!」と怒られました。。
なぜなら、failureは、コールバックに失敗した時にしか呼ばれないからです。
僕はこれにハマってしまい、なぜルートがないのに呼ばれるのだろう?と思っていたのですが、どうやらomniauthの方でcallbackに失敗したら自動的で呼ばれるようになっているらしい。
コードの中身: https://github.com/omniauth/omniauth/blob/c2380ae848ce4e0e39b4bb94c5b8e3fd0a544825/lib/omniauth/builder.rb#L22
Github : https://github.com/omniauth/omniauth/wiki/Integration-TestingGithub(翻訳): https://techracho.bpsinc.jp/hachi8833/2017_05_22/40297
というわけで、コールバックのURLを叩きにいって、失敗させて上げる必要があります。
今回コールバックのURLはconfig/routes.rbget "auth/:provider/callback" => "authentications#create", as: :create_authenticationとなっているため、
Authentications#create
にGETリクエストを投げてテストしてみました。spec/controllers/authentications_controller_spec.rbrequire "rails_helper" RSpec.describe "omniauth", type: :request do # ...省略 describe "GET #failure" do let(:user) { create(:user) } before { request.env["omniauth.auth"] = twitter_invalid_mock } subject { get :create, params: { provider: "twitter" } it "current_userが存在する" do sigin_in user expect(subject).to redirect_to user_setting_social_profiles_path end it "current_userが存在しない" do expect(subject).to render_template :failure end end endと、書きたいところですが、これでは
failure
アクションにはリダイレクトしてくれませんでした。
また、テスト用のparams(:invalid_credentails
)をアクション内で整形してしまいエラーを吐いてしまいます。これでは明示的に
failure
アクションに飛ばすしか方法がありません。アクションを介さずに直接リダイレクトするには、
spec/requests
以下に書きましょう。spec/requests/authentications_spec.rbrequire "rails_helper" RSpec.describe "omniauth", type: :request do describe "GET #failure" do before do Rails.application.env_config["omniauth.auth"] = twitter_invalid_mock end subject { get "/auth/twitter/callback" } it "current_userが存在する" do sigin_in user expect(subject).to redirect_to user_setting_social_profiles_path end it "current_userが存在しない" do expect(subject).to render_template :failure end end endこれで無事通すことができました。
参考: https://qiita.com/Apuruny/items/38dc94628f7b52bd172eまとめ
Twitter認証の仕組みなんてそもそもわからないし、ましてやテストコードをかけとは何事だと思ってましたが、いろんな記事に恵まれて無事実装することができました。
全て動作確認をしてるわけではないので、コピペする際はご注意ください(m_ _m)
- 投稿日:2019-02-28T22:28:40+09:00
[CarrierWave]RSpec実行後の画像ファイルを削除する
はじめに
RSpecでテストを何度も実施していたら画像ファイルが膨大に保存されており、自動で削除されるように設定したのでメモします。
参考にしたサイト
How to: Cleanup after your Rspec tests
Rspecのcarrierwaveを実行した後のファイルを削除
画像周りの扱い方
CarrierWave + RSpec ディレクトリ問題手順
1. 環境
ruby : 2.5.1 rails : 5.2.2 device : 4.6.1 carrierwave : 1.3.1 rspec-rails : 3.8.22. development時とtest時で画像が保存されるディレクトリを分ける
Carrierwaveをインストールした際に
rails g uploader Photo
をしてapp/uploaders/photo_uoloader.rbが作成されているので、ここに画像の保存場所を設定します。app/uploaders/photo_uoloader.rbclass PictureUploader < CarrierWave::Uploader::Base # 省略 def store_dir if Rails.env.test? "uploads_#{Rails.env}/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" else "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end end # 省略3. テスト終了後にファイルを削除する
spec/rails_helper.rbに以下を追加します。
spec/rails_helper.rbRSpec.configure do |config| # 省略 config.after(:all) do if Rails.env.test? FileUtils.rm_rf(Dir["#{Rails.root}/public/uploads_#{Rails.env}/"]) end end end
- 投稿日:2019-02-28T20:56:52+09:00
RailsでDBをMySQLに変更する方法(Ubuntu)
MySQLの設定
MySQLのインストール
以下のコマンドを順に実行。
$ sudo apt update $ sudo apt install mysql-server mysql-clientこれでMySQLのインストールが完了しました。
Railsで使うユーザーの設定
以下を実行しRailsで使うMySQLのユーザー名(user)とパスワード(password)を設定する。Railsには開発環境(development)、テスト環境(test)、本番環境(production)がある。それぞれに対してDBが割り当てられるので3つのユーザーを作るほうが管理が楽だと思う(以下のコマンドでは1人のユーザーを作っている)。
$ sudo mysql -u root -p # パスワードを要求されるが「Enter」をおせばよい mysql> CREATE USER 'user'@'localhost' IDENTIFIED BY 'password';RailsがMySQLにアクセスできるように権限を与える。特定のDBにだけ権限を絞ることができるが、この段階ではDBが生成されていないので制限をかけるのが難しいので、強めの権限を与えることにする。後にRails側の設定が終わってDBが作ってから変更することを推奨する。
GRANT ALL ON *.* TO 'user'@'localhost';Railsの設定
プロジェクトの作成とデーターベースの設定ファイルの編集
Railsのインストールができていない方はこちら。
Rails new -d mysql --skip-bundle
を実行することでDBをMySQLに指定してプロジェクトを作ることができる。上記のコマンドを実行したら、以下のようにファイルを編集しよう。config/database.yml# MySQL. Versions 5.1.10 and up are supported. # # Install the MySQL driver # gem install mysql2 # # Ensure the MySQL gem is defined in your Gemfile # gem 'mysql2' # # And be sure to use new-style password hashing: # https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html # default: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: MySQLで設定したuser password: MySQLで設定したpassword socket: /var/run/mysqld/mysqld.sock host: localhost development: <<: *default database: Math-Dictionary_development # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: <<: *default database: Math-Dictionary_test # As with config/secrets.yml, you never want to store sensitive information, # like your database password, in your source code. If your source code is # ever seen by anyone, they now have access to your database. # # Instead, provide the password as a unix environment variable when you boot # the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database # for a full rundown on how to provide these environment variables in a # production deployment. # # On Heroku and other platform providers, you may have a full connection URL # available as an environment variable. For example: # # DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase" # # You can use this database configuration with: # # production: # url: <%= ENV['DATABASE_URL'] %> # production: <<: *default database: Math-Dictionary_production password: <%= ENV['MATH-DICTIONARY_DATABASE_PASSWORD'] %>※もし、MySQLの設定で3つのユーザーを設定している場合は、それぞれの環境の設定のところに上書きして更新することができる。
bundle install のエラー対処法
次に
bundle install
を実行する。ここでAn error occurred while installing mysql2 (0.3.16), and Bundler cannot continue. Make sure that `gem install mysql2 -v '0.3.16' --source 'https://rubygems.org/'` succeeds before bundling.このようなエラーが出る場合はこのエラーメッセージ通り
gem install mysql2 -v '0.3.16'
を実行しよう。さらに、これでもエラーが出る場合は、そのエラーメッセージの上部にインストールするべきものがないかを確認しよう。私の場合は、sudo apt-get install libmysqlclient-dev
を実行せよとなっていた。これでgem install mysql2 -v '0.3.16'
が実行できて、無事bundle install
することができた。他にも、bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib --with-cppflags=-I/usr/local/opt/openssl/include"
を実行するといける場合もあるらしい(ググって出てきただけ)。実際にデーターベースを作成する
rake db:createこれでDBがMySQLになりました。
- 投稿日:2019-02-28T20:46:40+09:00
deviseを日本語化する方法の備忘録
deviseを日本語化する方法の備忘録です。
gemをインストール
gemfilegem 'devise-i18n' gem 'devise-i18n-views'$bundle installを実行する。
日本語翻訳ファイルを生成
$rails g devise:views:local ja
config/locales/devise.viwes.ja.ymlja: activerecord: attributes: user: current_password: "現在のパスワード" email: "メールアドレス" password: "パスワード" password_confirmation: "確認用パスワード" remember_me: "ログインを記憶" models: user: "ユーザ" devise: confirmations: new: resend_confirmation_instructions: "アカウント確認メール再送" mailer: confirmation_instructions: action: "アカウント確認" greeting: "ようこそ、%{recipient}さん!" instruction: "次のリンクでメールアドレスの確認が完了します:" reset_password_instructions: action: "パスワード変更" greeting: "こんにちは、%{recipient}さん!" instruction: "誰かがパスワードの再設定を希望しました。次のリンクでパスワードの再設定が出来ます。" instruction_2: "あなたが希望したのではないのなら、このメールは無視してください。" instruction_3: "上のリンクにアクセスして新しいパスワードを設定するまで、パスワードは変更されません。" unlock_instructions: action: "アカウントのロック解除" greeting: "こんにちは、%{recipient}さん!" instruction: "アカウントのロックを解除するには下のリンクをクリックしてください。" message: "ログイン失敗が繰り返されたため、アカウントはロックされています。" passwords: edit: change_my_password: "パスワードを変更する" change_your_password: "パスワードを変更" confirm_new_password: "確認用新しいパスワード" new_password: "新しいパスワード" new: forgot_your_password: "パスワードを忘れましたか?" send_me_reset_password_instructions: "パスワードの再設定方法を送信する" registrations: edit: are_you_sure: "本当に良いですか?" cancel_my_account: "アカウント削除" currently_waiting_confirmation_for_email: "%{email} の確認待ち" leave_blank_if_you_don_t_want_to_change_it: "空欄のままなら変更しません" title: "%{resource}編集" unhappy: "気に入りません" update: "更新" we_need_your_current_password_to_confirm_your_changes: "変更を反映するには現在のパスワードを入力してください" new: sign_up: "アカウント登録" sessions: new: sign_in: "ログイン" shared: links: back: "戻る" didn_t_receive_confirmation_instructions: "アカウント確認のメールを受け取っていませんか?" didn_t_receive_unlock_instructions: "アカウントの凍結解除方法のメールを受け取っていませんか?" forgot_your_password: "パスワードを忘れましたか?" sign_in: "ログイン" sign_in_with_provider: "%{provider}でログイン" sign_up: "アカウント登録" unlocks: new: resend_unlock_instructions: "アカウントの凍結解除方法を再送する"必要に応じてメッセージを変更する。
localeの設定
config/application.rbconfig.i18n.default_locale = :ja上のコードをconfig/application.rbに記述する。
localeを設定することで日本語化できるようです。まとめ
以上が今回私が実施したdeviseを日本語化する方法です。
- 投稿日:2019-02-28T19:06:40+09:00
Rails で Web API 開発(Part. 5 R(CRUD) の実装)
はじめに
本記事は、自身が今までの Ruby on Rails で開発してきた知識 / 知見の総まとめをおこなったものです。
「ここは、もっとこうしたほうがいいよ!こういうものがあるよ!」というようなことがあれば、随時おしらせください!
最終的なプロダクトは、 Rails API Sample に置いておきます。各記事
- Rails で Web API 開発(Part. 1 概要)
- Rails で Web API 開発(Part. 2 Docker 関連)
- Rails で Web API 開発(Part. 3 DB 関連)
- Rails で Web API 開発(Part. 4 CORS 関連)
- Rails で Web API 開発(Part. 5 R(CRUD) の実装)
記事の構成
前回の記事
前回は、CORS の設定を行いました。
今回の記事
今回は、実際に CRUD のうちの R の実装をおこなっていきたいと思います。
次回の記事
次回は、ひきつづき CRUD のうちの CUD の実装をおこなっていきたいと思います。
API 仕様書 の作成
Swagger Editor の起動
早速実装を…!といきたいのですが、ひとまず仕様書をちゃんと作ろうということで、 Swagger Editor を扱えるようにしていきましょう。
以下のコマンドを実行しましょう。
$ docker pull swaggerapi/swagger-editor
$ docker run -d --rm -p 80:8080 swaggerapi/swagger-editor
おそらく、
localhost
にブラウザ上からアクセスすれば Swagger Editor が起動しているのを確認できるはずです。
画面左部に以下を記述してみましょう。 swagger の記述方法については、解説しませんので今後記述していくうえで演繹的に感じていただけたらと思います。# This Docs Information swagger: "2.0" info: version: "0.0.1" title: "Rails API Sample" schemes: - "http" host: "localhost:40000" basePath: "/api" produces: - application/json paths: /users: get: tags: - "users - action" summary: "User 全体取得 API" responses: 200: description: "OK" schema: type: array items: type: object properties: id: type: integer name: type: string created_at: type: string updated_at: type: string /users/{id}: get: tags: - "users - action" summary: "User 全体取得 API" parameters: - in: path name: "id" type: integer required: true responses: 200: description: "OK" schema: type: object properties: id: type: integer name: type: string created_at: type: string updated_at: type: string以下のような画面になるはずです。
yaml ファイルの保存
また念の為、この yaml ファイル は、 docs 配下 に保存しておくことにします。
API の実装
さて、それでは実際に API を実装していきましょう。
エラー処理機構の実装
さっそく実装を!!といきたいのですが、まずは先にエラー処理機構を整えることにしましょう。
I18n で日本語化
Rails の I18n という機能を用いて、Message の管理をおこなっていきます。
まずは、以下のコマンドで、デフォルトの ja.yml ファイルをダウンロードしましょう。
Mac の場合は、$ brew install wget
とかうてば wget コマンド うてるようになるのかな?
$ wget https://raw.github.com/svenfuchs/rails-i18n/master/rails/locale/ja.yml -P config/locales/ja/default.yml
次に、 config/application.rb に追記し、起動時に locales 配下の *.yml が読み込まれるようにします。
# I18n の設定 config.i18n.default_locale = :ja config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s]最後に、 config/locales/ja/error.yml を作成しましょう。この部分に、各エラーの情報を記載していきます.
ja: errors: ApiErrors::FilterParamsError: status_code: 400 error_code: E001 error_description: リクエストパラメーターが異常です。 ApiErrors::GenerateJSONError: status_code: 500 error_code: E002 error_description: JSON 生成時にエラーが発生しました。 other: status_code: 500 error_code: E999 error_description: サーバー内でエラーが発生しました。エラー処理機構
app/controllers/application_controller.rb を以下のように編集しましょう。
この部分で、エラーを処理して response を返すようにします。また、先に記述した yml ファイル を読み込むような設定もこの部分でしています.class ApplicationController < ActionController::API rescue_from Exception, with: :render_error private def render_error(error) error_description = I18n.t("errors.#{error.class}", default: :'errors.other') response = { error_code: error_description[:error_code], error_description: error_description[:error_description] } render json: response, status: error_description[:status_code] end endエラークラス
最後に、今後発生するであろうエラークラスを app/errors/api_errors.rb に定義しておきます。
module ApiErrors class FilterParamsError < StandardError end class GenerateJSONError < StandardError end endModel の実装
それでは、以下のような app/models/user.rb と app/models/micropost.rb を作成しましょう。
class User < ApplicationRecord self.table_name = 'users' has_many :microposts endclass Micropost < ApplicationRecord self.table_name = 'microposts' belongs_to :user endValidation 等のビジネスロジック(ビジネスロジックとは何か…。はおいておきます…。)は、いっさいかきません。
Rails では、よく Controller 層 / Model 層の肥大化が問題となっているので、今回は Trailblazer という gem を扱います。Routing の設定
それでは、 config/routes.rb を以下のように編集しましょう。
Rails.application.routes.draw do namespace :api do resources :users, only: %i[show index] end endOperation(JSON 生成層) の実装
名付けがよくわからなかったので、とりあえず Operation(JSON 生成層)の実装をおこなっていきます。
以下のような全ての Operation が継承をする app/concepts/apprication_operation.rb を作成します。
ここでは、Operation で引き起こされるであろう Error について記述しておきます。ここで引き起こされた Error は、 application_controller.rb で処理されます。
また、日付を format する関数をここに記述しておきます.class ApplicationOperation < Trailblazer::Operation protected def handle_filter_params_error!(*) raise ApiErrors::FilterParamsError end def handle_generate_json_error!(*) raise ApiErrors::GenerateJSONError end def simple_format_time(time) time.strftime('%Y-%m-%d %H:%M:%S') end endそれでは、具体的に show / index method の実装をおこなっていきます。
以下のような app/concepts/users/operation/show.rb ・ app/concepts/users/operation/index.rb を作成します。class Users::Operation::Show < ApplicationOperation step :filter_params failure :handle_filter_params_error! step :generate_json failure :handle_generate_json_error! private def filter_params(options, params, **) options['user'] = User.find_by(id: params[:id]) end def generate_json(options, **) # 抽出するカラムを選択 response = options['user'].slice(:id, :name, :created_at, :updated_at) # value を整形 response[:created_at] = simple_format_time(response[:created_at]) response[:updated_at] = simple_format_time(response[:updated_at]) # json を生成 options['json'] = response.to_json end endclass Users::Operation::Index < ApplicationOperation step :generate_json failure :handle_generate_json_error! private def generate_json(options, **) # 抽出するカラムを選択 response = User.all.pluck(:id, :name, :created_at, :updated_at) # hash 形式に変更 keys = %i[id name created_at updated_at] response.map! do |response| Hash[*[keys, response].transpose.flatten] end # value を整形 response.map! do |response| response[:created_at] = simple_format_time(response[:created_at]) response[:updated_at] = simple_format_time(response[:updated_at]) response end # json を生成 options['json'] = response.to_json end endController の実装
最後に Controller を実装すれば、おしまいですね!
以下のような app/controllers/api/users_controller.rb を作成しましょう。class Api::UsersController < ApplicationController def show result = Users::Operation::Show.call( id: params[:id] ) render json: result['json'], status: 200 end def index result = Users::Operation::Index.call() render json: result['json'], status: 200 end endおわりに
今回は、 CRUD の R だけをとりあえず実装しようと思ったのですが、色々とやることがありましたね…。次回は、 Rails で Web API 開発(Part. 6 CUD(CRUD) の実装) をおこなっていきます!
- 投稿日:2019-02-28T19:04:56+09:00
Rails で Web API 開発(Part. 4 CORS 関連)
はじめに
本記事は、自身が今までの Ruby on Rails で開発してきた知識 / 知見の総まとめをおこなったものです。
「ここは、もっとこうしたほうがいいよ!こういうものがあるよ!」というようなことがあれば、随時おしらせください!
最終的なプロダクトは、 Rails API Sample に置いておきます。各記事
- Rails で Web API 開発(Part. 1 概要)
- Rails で Web API 開発(Part. 2 Docker 関連)
- Rails で Web API 開発(Part. 3 DB 関連)
- Rails で Web API 開発(Part. 4 CORS 関連)
- Rails で Web API 開発(Part. 5 R(CRUD) の実装)
記事の構成
前回の記事
前回は、DB の設定を行いました。
今回の記事
今回は、API を実装するうえで欠かせない CORS の設定をおこなっていきます。
次回の記事
次回は、実際に CRUD のうちの R の実装をおこなっていきたいと思います。
CORS の設定
Rack Cors
今回、CORS の設定を行うために、 Rack Cors という gem を扱います。最初の Gemfile に記述済みですので、今回新しくインストールのために何かやる必要はないです。
さて、おそらくすでに config/initializers/cors.rb というファイルがあるかと思います。このファイルを以下のように編集しましょう。
$ docker-compose down; docker-compose up
を行えば、設定が反映されるはずです。Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do # 全ての origin(Host) からの リクエストを許可する。 origins '*' # /api/ 以下全てのリソースに対して、 resource '/api/*', # 本サーバに対するリクエストにどんな header もつけてもよいとする。 headers: :any, # 本サーバに対するリクエストに以下の method であれば許可をする。 methods: %i[get, post, put, patch, delete, options, head], # 本サーバからのレスポンスの HTTP ヘッダとして公開することを許可する。 expose: %i[] end endおわりに
ちょっと今回は、はやくなりすぎてしまいました…。次回は、Rails で Web API 開発(Part. 5 R(CRUD) の実装)を行います。
- 投稿日:2019-02-28T19:04:35+09:00
Rails で Web API 開発(Part. 3 DB 関連)
はじめに
本記事は、自身が今までの Ruby on Rails で開発してきた知識 / 知見の総まとめをおこなったものです。
「ここは、もっとこうしたほうがいいよ!こういうものがあるよ!」というようなことがあれば、随時おしらせください!
最終的なプロダクトは、 Rails API Sample に置いておきます。各記事
- Rails で Web API 開発(Part. 1 概要)
- Rails で Web API 開発(Part. 2 Docker 関連)
- Rails で Web API 開発(Part. 3 DB 関連)
- Rails で Web API 開発(Part. 4 CORS 関連)
- Rails で Web API 開発(Part. 5 R(CRUD) の実装)
記事の構成
前回の記事
前回は、Docker 上で開発をするうえでの下準備を行いました。
今回の記事
今回は、前回開発した Docker 上で DB の設定を行い、実際に
curl コマンド
が通るところまで行います。次回の記事
次回は、API を実装するうえでかかせない CORS の設定をおこなっていきたいと思います。
ER 図の作成
MySQL Workbench
ER 図を作成するために、今回は MySQL Workbench を使用します。今回は、使用方法については控えますが(ごにょごにょして)以下のような ER 図を作成しました。(今後、設計図等はリポジトリの docs 配下 に置いておくことにします。)
- DB 名: rails_api_sample
また、MySQL Workbench の機能を利用して、以下のような SQL 文を作成しました。
-- MySQL Script generated by MySQL Workbench -- Wed Feb 27 15:05:04 2019 -- Model: New Model Version: 1.0 -- MySQL Workbench Forward Engineering SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES'; -- ----------------------------------------------------- -- Schema rails_api_sample -- ----------------------------------------------------- -- ----------------------------------------------------- -- Schema rails_api_sample -- ----------------------------------------------------- CREATE SCHEMA IF NOT EXISTS `rails_api_sample` DEFAULT CHARACTER SET utf8 ; USE `rails_api_sample` ; -- ----------------------------------------------------- -- Table `rails_api_sample`.`users` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `rails_api_sample`.`users` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `name` VARCHAR(64) NOT NULL, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE = InnoDB; -- ----------------------------------------------------- -- Table `rails_api_sample`.`microposts` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `rails_api_sample`.`microposts` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `content` TEXT NOT NULL, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `user_id` BIGINT NOT NULL, PRIMARY KEY (`id`), INDEX `fk_microposts_users_idx` (`user_id` ASC), CONSTRAINT `fk_microposts_users` FOREIGN KEY (`user_id`) REFERENCES `rails_api_sample`.`users` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB; SET SQL_MODE=@OLD_SQL_MODE; SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS; SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;テーブルの作成
実際に、Docker 上の DB に接続しテーブルを作成していきましょう。今回は、 Sequel Pro という MySQL の可視化ツールを用いたいと思います。
前回の作業をおこなっていれば、以下のような設定で疎通が確認できるはずです。先ほど作成した SQL 文を(Sequel Pro 上で)実際に入力することでテーブルが作成できることが確認できます。
以下は、 SQL 文 入力をし、実行をおこなった後の画面になります。database.yml の編集
Docker Compose 上で環境変数を流しているために、以下のような設定を行うことで疎通が行えるはずです。
記述した後に、再度$ docker-compose down; docker-compose up
を行えば、$ curl localhost:40000
で疎通確認が行えるはずです。default: &default adapter: mysql2 encoding: utf8 pool: 5 host: <%= ENV['MYSQL_HOST'] %> username: <%= ENV['MYSQL_USER'] %> password: <%= ENV['MYSQL_PASSWORD'] %> port: <%= ENV['MYSQL_PORT'] %> database: rails_api_sample development: <<: *default test: <<: *default database: rails_api_sample_test production: <<: *defaultMigration の管理
DB というものは、実装をしていくうえでよく変わりうるものです。上記の ER図 を用いて運用上でうまい感じにやっていくというのもできないこともないですが、ちょっと面倒です。
今回、Migration の管理を行うために、 Ridgepole という gem を扱います。最初の Gemfile に記述済みですので、今回新しくインストールのために何かやる必要はないです。Ridgepole タスクの作成
Ridgepole を扱うための Rake タスクを作成してきましょう。今回は、以下のようなファイルを作成します。
若干コメント文にもありますが 既存の DB から Schemafile を作成することと、またその逆ができるようになります。# (lib/tasks/ridgepole.rake) # Schema -> DB # ./bin/bundle exec rails ridgepole:apply "env" # # ex) ./bin/bundle exec rails ridgepole:apply RAILS_ENV=development # # DB -> Schema # ./bin/bundle exec rails ridgepole:export "env" # # ex) ./bin/bundle exec rails ridgepole:export RAILS_ENV=development namespace :ridgepole do task export: :environment do options = [ '--export', '--split', "--output #{schemafile_path}" ] exec_ridgepole(options) end task apply: :environment do options = [ '--apply', "--file #{schemafile_path}" ] exec_ridgepole(options) end def exec_ridgepole(options) yml_file_path = Rails.root.join('config', 'database.yml') default_options = [ "--env #{Rails.env}", "--config #{yml_file_path}" ] sh("bundle exec ridgepole #{default_options.join(' ')} #{options.join(' ')}") end def schemafile_path Rails.root.join('db', 'schemas', 'Schemafile') end end既存の DB から Schemafile を作成 / 更新
以下のコマンドを実行することで、DB の作成 / 更新を行えるようになっているはずです。作成された Schemafile は、 db/schemas に保存されているはずです。
$ docker-compose run --rm app ./bin/bundle exec rails ridgepole:export RAILS_ENV=development
既存の Schemafile から テーブル を作成 / 更新
以下のコマンドを実行することで、テーブルの作成 / 更新を行えるようになっているはずです。
$ docker-compose run --rm app ./bin/bundle exec rails ridgepole:apply RAILS_ENV=development
おわりに
今回は、DB 周りのことに関してお話しました。次回は、Rails で Web API 開発(Part. 4 CORS 関連)を行います。
- 投稿日:2019-02-28T19:04:13+09:00
Rails で Web API 開発(Part. 2 Docker 関連)
はじめに
本記事は、自身が今までの Ruby on Rails で開発してきた知識 / 知見の総まとめをおこなったものです。
「ここは、もっとこうしたほうがいいよ!こういうものがあるよ!」というようなことがあれば、随時おしらせください!
最終的なプロダクトは、 Rails API Sample に置いておきます。各記事
- Rails で Web API 開発(Part. 1 概要)
- Rails で Web API 開発(Part. 2 Docker 関連)
- Rails で Web API 開発(Part. 3 DB 関連)
- Rails で Web API 開発(Part. 4 CORS 関連)
- Rails で Web API 開発(Part. 5 R(CRUD) の実装)
記事の構成
前回の記事
前回は、Mac 上でとりあえず
$ rails server
が動くところまでやりました。今回の記事
今回は、Docker Container 上で
$ rails server
が動くようにします。次回の記事
次回は、しっかりと DB 部分の実装をおこなっていきます。
各種 Docker ファイルの作成
docker-compose.yaml の作成
以下のような docker-compose.yaml を作成します。
version: '3' services: db: image: mysql:5.7 volumes: - db_data:/var/lib/mysql ports: - "40050:3306" restart: always # 環境変数は、Docker 上から流すことにします。 environment: TZ: "Asia/Tokyo" MYSQL_ROOT_PASSWORD: rails_api_sample MYSQL_DATABASE: rails_api_sample MYSQL_USER: rails_api_sample MYSQL_PASSWORD: rails_api_sample app: build: . volumes: - .:/rails_api_sample depends_on: - db ports: - "40000:3000" tty: true stdin_open: true # 環境変数は、Docker 上から流すことにします。 environment: TZ: "Asia/Tokyo" MYSQL_HOST: db MYSQL_DB: rails_api_sample MYSQL_PORT: 3306 MYSQL_USER: rails_api_sample MYSQL_PASSWORD: rails_api_sample volumes: db_data: {}Dockerfile の作成
以下のような Dockerfile を作成します。
FROM ruby:2.6.1 RUN mkdir -p /rails_api_sample WORKDIR /rails_api_sample RUN apt-get update -qq && \ apt-get install -y build-essential mysql-client nodejs tzdata COPY Gemfile* /rails_api_sample/ RUN mkdir -p /rails_api_sample/bin COPY bin/* /rails_api_sample/bin/ RUN ./bin/bundle install --path vendor/bundle COPY . /rails_api_sample # Add a script to be executed every time the container starts. COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] EXPOSE 3000 CMD ["./bin/bundle", "exec", "rails", "server", "-p", "3000", "-b", "0.0.0.0", "-e", "development"]Docker 上で rails server
docker-compose up
以下のコマンドを実行します。
$ docker-compose build
次に、以下のコマンドを実行します。
$ docker-compose run --rm app ./bin/bundle install --path vendor/bundle
最後に、以下のコマンドを実行します。
$ docker-compose up
以下のようになったら、とりあえず完了です!( curl コマンド 等で確認してもおそらく DB 周りの設定ができていないのでちゃんとはかえってこないです…。)
各種コマンド
覚えておいたほうがよいコマンドに関して少しだけ記述しておきます。
$ docker-compose up
: docker-compose を起動します。
$ docker-compose down
: docker-compose を停止します。
$ docker-compose run --rm ${SERVICE_NAME} ${COMMAND}
: ${SERVICE_NAME} 内で、指定のコマンドを実行します。 ex)$ docker-compose run --rm app bash
$ docker attach ${CONTAINER_NAME}
: ${CONTAINER_NAME} 内に、入れます。次の例では、binding.pry
等を実行する際によく使います。 ex)$ docker attach rails_api_sample_app
おわりに
まだまだ DB 関連が整っていないです…。次回は、Rails で Web API 開発(Part. 3 DB 関連)を行います。
- 投稿日:2019-02-28T19:03:46+09:00
Rails で Web API 開発(Part. 1 概要)
はじめに
現在、執筆中です。
本記事は、自身が今までの Ruby on Rails で開発してきた知識 / 知見の総まとめをおこなったものです。
「ここは、もっとこうしたほうがいいよ!こういうものがあるよ!」というようなことがあれば、随時おしらせください!
最終的なプロダクトは、 Rails API Sample に置いておきます。対象
- Mac での開発者
- ある程度 Rails / Docker の知識があるとよいかな…。と
各記事
- Rails で Web API 開発(Part. 1 概要)
- Rails で Web API 開発(Part. 2 Docker 関連)
- Rails で Web API 開発(Part. 3 DB 関連)
- Rails で Web API 開発(Part. 4 CORS 関連)
- Rails で Web API 開発(Part. 5 R(CRUD) の実装)
記事の構成
今回の記事
今回は、全体の記事について記述します。また、とりあえずローカルで
$ rails server
コマンドが動くところまで記述します。次回の記事
Docker を用いた開発を行う上での下準備をおこなっていきます。
主に扱うもの
- Ruby(ver. 2.6.1) + Ruby on Rails(ver. 5.2.2)
- Docker + Docker-Compose(コンテナ 関連)
- MySQL + MySQL Workbench + Sequel Pro + Ridgepole (DB 関連)
- Rspec + Factory Girl + Shoulda Matcher(テスト 関連)
Rails プロジェクトの作成
Version
先述のとおり、Ruby / Ruby on Rails の各 Version は、以下の通りです。
rails new
以下のコマンドを実行しましょう。( DBには、MySQL を使用し 、 API モードで 、 Minitest は使わない ようにするオプション。)
$ rails new rails_api_sample --database=mysql --api -T
$ cd rails_api_sample
Gemfile の編集
今回扱う Gemfile は、以下のようにしています。
source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.6.1' gem 'rails', '5.2.2' # DB(MySQL) の設定に必要な gem gem 'mysql2' # JSON の管理に必要な gem gem 'jbuilder' # 'rails server' 起動時に必要な gem gem 'bootsnap', require: false gem 'puma' # CORS の設定に必要な gem gem 'rack-cors' # Migration の管理に必要な gem gem 'ridgepole' # Trailblazer を扱うのに必要な gem gem 'reform-rails' gem 'trailblazer-loader' gem 'trailblazer-rails' group :development, :test do # 便利コマンド 'binding.pry' を使用するのに必要な gem gem 'pry-byebug' gem 'pry-doc' gem 'pry-rails' # ソースコードが綺麗かどうか Check する gem gem 'rubocop' end group :development do # ファイルの変更を監視する gem gem 'listen' # 起動を早くするために必要な gem gem 'spring' gem 'spring-watcher-listen' end group :test do # TEST 用 DB の管理をする gem gem 'database_rewinder' # TEST 用 データの管理をする gem gem 'factory_bot_rails' gem 'faker' # Rspec で TEST をするために必要な gem gem 'rspec-json_matcher' gem 'rspec-rails' gem 'rspec_junit_formatter' # モデルの関連を TEST するために必要な gem gem 'shoulda-matchers' endbundle install
以下のコマンドを実行しましょう。( vendor/bundle 配下にインストール するオプション。)
$ bundle install --path vendor/bundle
rails server
以下のコマンドを実行しましょう。( $ rails s は $ rails server の省略コマンド。 -p はポート指定。-b はIP Address指定。-e は環境指定。)
$ bundle exec rails s -p 3000 -b '127.0.0.1' -e 'development'
以下のようになったら、とりあえず完了です!( curl コマンド 等で確認してもおそらく DB 周りの設定ができていないのでちゃんとはかえってこないです…。)
おわりに
今回は、とりあえず
$ rails server
コマンドまでを行いました。次回は、Rails で Web API 開発(Part. 2 Docker 関連)を行います。
- 投稿日:2019-02-28T17:27:45+09:00
RailsのMVCってなに?
フレームワークの構造についてメモ。
Railsに限らず他のフレームワークも、MVCの構造になっています。
この仕組を少し理解してからのほうが、一連の流れを理解しやすいかと思います。M:Model
V:View
C:Controller
- M データベースからデータを引っ張ってきます。
- V pe+tab で <%= >が補完。これを使うことでHTMLをブラウザに表示させることが出来ます。
つまり ERB {enbedded(埋め込み) Ruby} 出来ます。ファイル拡張子も .erb になってることが多いですが、ERBと繋がりますね!- C 管制!というイメージです。MとVに指示を出します。
下記サイトがとても噛み砕いて説明してあり分かりやすかったです。
(参考https://www.yuta-u.com/programing/rails_mvc)
- 投稿日:2019-02-28T16:36:16+09:00
Railsでaccets_nested_attributes_forを使わずに複数子レコードを同時保存
- 投稿日:2019-02-28T15:59:20+09:00
bundle installのmysql2 のエラー解決方法
【環境】
macOS Mojava
バージョン10.14.3・ruby -v
ruby 2.3.3p222 (2016-11-21 revision 56859) [x86_64-darwin18]・rbenv versions
system
2.2.2
2.3.0
2.3.1
* 2.3.3 (set by /Users/ユーザー名/サイト名/.ruby-version)
2.4.1
2.5.3mysql --version
/usr/local/opt/mysql@5.7/bin/mysql Ver 14.14 Distrib 5.7.25, for osx10.14 (x86_64) using EditLine wrapper
vi ~/.bash_profile
PATH=/usr/local/mysql/bin:$PATH
export PATH
export PATH="~/.rbenv/shims:/usr/local/bin:$PATH"eval "$(rbenv init -)"
vi ~/.bashrc
alias mysql=/usr/local/opt/mysql@5.7/bin/mysql
alias mysqladmin=/usr/local/opt/mysql@5.7/bin/mysqladmin
【エラー内容】
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
Gem files will remain installed in
/Users/ユーザー名/サイト名/vendor/bundle/ruby/2.3.0/gems/mysql2-0.4.5 for
inspection.
Results logged to
/Users/ユーザー名/サイト名/vendor/bundle/ruby/2.3.0/extensions/x86_64-darwin-18/2.3.0-static/mysql2-0.4.5/gem_make.outAn error occurred while installing mysql2 (0.4.5), and Bundler cannot
continue.
Make sure thatgem install mysql2 -v '0.4.5' --source 'https://rubygems.org/'
succeeds before bundling.In Gemfile:
mysql2
【試した事】
・パスを通す
https://nekonenene.hatenablog.com/entry/2016/10/31/061350
の解決方法①bundle config build.mysql2 --with-opt-lib=/usr/local/opt/openssl/lib --with-opt-include=-I/usr/local/opt/openssl/include
・インストール実行
gem install mysql2 -v '0.4.5' --source 'https://rubygems.org/'▼エラー内容
ERROR: Error installing mysql2:
ERROR: Failed to build gem native extension.
・gemfileのtherubyracerをコメントアウト
gem 'therubyracer'
・Xcodeの再インストール
xcode-select --install▼エラー内容(インストール済)
xcode-select: error: command line tools are already installed, use "Software Update" to install updates
- 投稿日:2019-02-28T15:22:40+09:00
リポジトリのURLって?
Gitにpushしたリポジトリを他の人へ共有したい時。
リポジトリのURLを送って!と言われますね(^^)リポジトリのURLはどこで分かるのだろう??とGitをポチポチしていて
分かったのでメモです。まずは
Gitの自分のリポジトリ(your repositories)画面に移動します。
URLを知りたいリポジトリを選んでください。リポジトリをクリックすると、
「Clone or download」という緑のボタンが画面右の方に有るので
そのボタンをクリックしてください。
クリックするとなにかアドレスが出てきますが、今回はHTTPSの方のURLが欲しいので
Use HTTPSをクリックすると、
いつものhttpsから始まる見慣れたURLが出てきます(^o^)ホッ
URL右横のコピーボタンを押せばコピーできます。
その後、困ったことがありました汗
今回の操作により、gitにpushする時の使用が変わってしまっていたようで、push時にパスワード聞かれるようになってしまいました。
HTTPSに変更した方は、SSHに戻しましょう。(参考https://qiita.com/rorensu2236/items/df7d4c2cf621eeddd468)
- 投稿日:2019-02-28T14:55:21+09:00
Ruby if文,case文
動作環境はMacとなります。
if文
条件によって処理を出し分けたいときに使う
記述方法
if 条件1
条件 1が真(true)だった場合の処理
elsif 条件2
条件2が真(true)だった場合の処理
elsif 条件3
条件3が真(true)だった場合の処理
else
上記のいずれにも当てはまらなかった場合の処理
end条件が真になったタイミングで処理を抜ける。
後の処理は実行されない。※elsifの綴りはelseifではないため、注意
実践1
テストの点数が
90点以上 大変よくできました
80点以上 よくできました
60点以上 普通です
60点未満 頑張りましょうと出力されるプログラムを実際に書いてみる
if.rbscore = x(任意の数字を入れる) if score >= 90 puts "大変よくできました" elsif score >= 80 puts "よくできました" elsif score >= 60 puts "普通です" else puts "頑張りましょう" end処理結果
$ruby if.rb 普通です #score60点以上 $ruby if.rb 頑張りましょう #score60点未満(59点以下) $ruby if.rb 大変よくできました #score90点以上 $ruby if.rb よくできました #score80点以上 kouya:ruby_proje #条件が真(true)になった段階でif文を抜けている。 #また、59点以下の場合はelse内の処理が実行されている。実践2
catならmeow
dogならbowwow
cowならmoomoo
上記以外ならNot foundと出力されるプログラム
if2.rbanimal = X(任意の変数が入る) if animal == "cat" puts "meow" elsif animal == "dog" puts "bowwow" elsif animal == "cow" puts "moomoo" else puts "Not found" end # =は右辺を左辺に代入するとき ==は右辺と左辺が等しいときに使用するので注意出力結果
$ ruby if2.rb meow #animalがcat $ ruby if2.rb bowwow #animalがdog $ ruby if2.rb moomoo #animalがcow $ ruby if2.rb Not found " #animalが上記以外実践3
遊園地の入場料のプログラム
12歳以上 入場料 5,000円
6歳以上12歳未満 入場料 2,500円
6歳未満 1,000円if3.rbage = x(任意の値が入る) if age >= 12 puts 5000 elsif age >= 6 puts 2500 else age < 6 puts 1000 end出力結果
kouya:ruby_projects toripurug884$ ruby if3.rb 1000 #6歳未満 kouya:ruby_projects toripurug884$ ruby if3.rb 5000 #12歳以上 kouya:ruby_projects toripurug884$ ruby if3.rb 2500 #6歳未満12歳以上
unless文
記述方法
unless 条件
条件が偽(false)だった場合の処理
else
上記に当てはまらなかった場合の処理
end※unlessにelsifは書かない。
条件が偽になったタイミングで処理を抜ける。
後の処理は実行されない。
nが0で無かった場合、出力するプログラムを書く
if文の場合
unless.rbn = 1 if !n.zero? puts "Not zero" endunless文の場合
unless.rbn = 1 unless n.zero? puts "This is zero" end$ ruby unless.rb Not zero Not zero0の場合に出力するプログラムを unless文で追加
unless.rbn = 0 unless n.zero? puts "Not zero" else puts "This is zero" end出力結果
unless.rb$ ruby unless.rb This is zerounlessは無理に使う必要はなく、ifでも読み易ければOK
case文
記述方法
case 対象のオブジェクトや式
when
値1に一致する場合の処理
when
値2に一致する場合の処理
when
値3に一致する場合の処理
else
上記のいずれにも該当しない場合
end
実践
下記のプログラムを実装
誕生石がrubyだった場合 July
誕生石がperidotだった場合 August
誕生石がsapphireだった場合 September
上記意外だった場合 Not foundifで書いた場合
case.rbstone = x(任意の値を代入) if stone == "ruby" puts "July" elsif stone == "peridot" puts "August" elsif stone == "sapphire" puts "September" else puts "Not Found" endcase.rb$ ruby case.rb July #ruby $ ruby case.rb August #peridot $ ruby case.rb September #sappire $ ruby case.rb Not Found #上記以外case文で書いた場合
case.rbstone = x (任意の値が入る) case stone when "ruby" puts "July" when "peridot" puts "August" when "sapphire" puts "September" else puts "Not found" end出力結果
$ ruby case.rb July #ruby $ ruby case.rb August #peridot $ ruby case.rb September #sapphire $ ruby case.rb Not found #上記以外
if文で書くより、caseで書いた方がシンプルでわかりやすいことがある。
特に、複数の条件に分岐する場合はcaseの方が見やすい場合が多い。まとめ
複数人で開発場合、特ににコードの見易さやメンテナンス性が重要視される
自分にしかわからないコードを書くのではなく、相手にわかりやすいコードを書くように心がける必要がある。
- 投稿日:2019-02-28T13:42:02+09:00
resourceとresourcesでは作られるroutesが違ってハマった
はじめに
UdemyでRuby on Rails入門中です。自分のコーディングミスで小一時間ほどハマったので簡単にまとめておきます。
The Complete Ruby on Rails Developer Course
https://www.udemy.com/the-complete-ruby-on-rails-developer-course/環境
- AWS Cloud9
- ruby 2.6.0p0
- Rails 5.0.7.1
resourceの場合
config/routes.rbRails.application.routes.draw do resource :articles endroutesは以下のようになります。
:id
パラメータが含まれず、想定と異なるルーティングとなりました。所々エラーも出てハマりました。$ rails routes Prefix Verb URI Pattern Controller#Action root GET / pages#home about GET /about(.:format) pages#about new_articles GET /articles/new(.:format) articles#new edit_articles GET /articles/edit(.:format) articles#edit articles GET /articles(.:format) articles#show PATCH /articles(.:format) articles#update PUT /articles(.:format) articles#update DELETE /articles(.:format) articles#destroy POST /articles(.:format) articles#createresourcesの場合
config/routes.rbRails.application.routes.draw do resources :articles end想定通り
:id
パラメータが含まれるroutesが作成されました。$ rails routes Prefix Verb URI Pattern Controller#Action root GET / pages#home about GET /about(.:format) pages#about articles GET /articles(.:format) articles#index POST /articles(.:format) articles#create new_article GET /articles/new(.:format) articles#new edit_article GET /articles/:id/edit(.:format) articles#edit article GET /articles/:id(.:format) articles#show PATCH /articles/:id(.:format) articles#update PUT /articles/:id(.:format) articles#update DELETE /articles/:id(.:format) articles#destroy参考
- 投稿日:2019-02-28T09:53:54+09:00
Ruby 演算子,真偽値
動作環境はMacとなります。
比較演算子
演算子による値の比較
2つの値の大小と同じ値かを調べる方法比較演算子の記号
※マークダウン方式の影響で、より大きいの記述がおかしくなってます。より大きい > ⇦これ
= 以上
< より小さい
<= 以下
== 等しい
!= 等しくない
式が成り立つ場合 true
式が成り立たない場合falseを返すirb#1(main):001:0> 1 < 2 => true irb#1(main):002:0> 1 <= 2 => true irb#1(main):003:0> 1 > 2 => false irb#1(main):004:0> 1 >= 2 => false irb#1(main):005:0> 1 == 2 => false irb#1(main):006:0> 1 != 2 => true演算子の優先順位
irb#1(main):007:0> 1.0 + 2.0 * 3.0 / 4.0 => 2.5 irb#1(main):008:0> (1.0 + 2.0) * 3.0 / 4.0 #()で優先順位を上げる => 2.25高い ::
[]
+(単項) ! ~
**
-(単項)
* / %
+ -
<< >>
&
| ^
> >= < <=
<=> == === != =~ !~
&&
||
.. ...
?:(条件演算子)
=(+=, -= ... )
not
低い and or
数値と文字列は暗黙的に変換されない
数値と文字列を連結するとエラー
irb#1(main):009:0> 1 + "1" TypeError: String can't be coerced into Integer from (irb#1):9:in `+' from (irb#1):9文字列を数値に変換
irb#1(main):011:0> 1 + "1".to_i #整数クラスに変換 => 2 irb#1(main):012:0> 1 + "1.1".to_f #浮動小数点クラスに変換 => 2.1出力された!
数値を文字列に変換
irb#1(main):015:0> num = 10 => 10 irb#1(main):021:0> "Number name is " + num TypeError: no implicit conversion of Integer into String from (irb#1):21:in `+' from (irb#1):21 #numが変数のため、わかりにくいが文字列と数値の足し算はエラー irb#1(main):020:0> "Number name is " + num.to_s => "Number name is 10" #数値を文字列に変換出力された!
インクリメントとディクリメント
・インクリメント
数値に1を足す・ディクリメント
数値から1を引く他のプログラミング言語のように++や--で表すことができない点に注意!
irb#1(main):022:0> n = 1 => 1 irb#1(main):023:0> n = n + 1 => 2 irb#1(main):024:0> n += 1 => 3 irb#1(main):025:0> n = n - 1 => 2 irb#1(main):026:0> n -= 1 => 1 #どちらの表記でも大丈夫だが、+=や-=で表した方がスマート真偽値
Rubyでは、nilかfalseの場合は偽(false)
それ以外は真(true)trueの例
- trueそのもの・・・true
- 全ての数値・・・1,1.5,2/3
- 全ての文字列 ・・・"false","true",""(空文字)
論理演算子
&&や||で複数の条件の式を真偽値で返すことが可能になる。
論理積
&&(かつ)=全ての条件が真の場合trueを返す論理和
||(または)=少なくとも一つの条件が当てはまれば真になり、trueを返すand,or,not
&&,||,!とほぼ同じ役割
ただし計算の優先順位が異なるため、式に混在させないこと
irb(main):001:0> t1 = true => true irb(main):002:0> t2 = true => true irb(main):003:0> f1 = false => false irb(main):004:0> f2 = false => false irb(main):005:0> t1 and t2 => true irb(main):006:0> t1 and f1 => false irb(main):007:0> t1 or t2 => true irb(main):008:0> f1 or f2 => false irb(main):009:0> !t1 || t1 #trueとfalse => true#混在させると非常にわかりにくくなるため注意 irb(main):010:0> not t1 || t1 => false irb(main):011:0> t1 || t2 && f1 #&&の方が優先順位が高いため、t2とf1の計算が先にされた後、t1との和が計算される。 => true irb(main):012:0> t1 or t2 and f1 #orとandの優先順位は等しいので、左から計算 => false#()で囲ったりわかりやすくすることは複数人で開発するときには欠かせないスキル irb(main):013:0> (t1 || t2) && f1 => falseまとめ
リファレンスに書いてある優先順位が高いものと低いものを混在させると非常にわかりにくい。
また、優先順位を上げたいときは()でくくるなど、直感的でわかりやすいプログラムを書くことが重要。シンプルに記述するように心がけよう!
参考文献
- 投稿日:2019-02-28T08:14:48+09:00
Ruby オブジェクト指向、数値、文字列
動作環境はMacとなります。
主に自分の勉強用メモとして残しています。オブジェクト指向プログラミング言語
- コンピュータ・プログラミングの概念の一つ。
- オブジェクト指向の概念や手法を取り入れたもの。
- プログラムを、データとその振る舞いが結びつけられたオブジェクトの集まりとして構成する。
オブジェクトとは?
データと処理の集まりのこと。文字列、配列、数値、nilなど全てオブジェクト。オブジェクト指向とは?
オブジェクト同士が相互に関係しあうことで、システムの振る舞いを捉える考え方。クラス
オブジェクトの設計図インスタンス
クラス(設計図)から作成した、実態。メソッド
- クラスの中に定義されていて、複数の処理を1つにまとめて、扱いやすくしたもの
- クラスに所属する関数のようなもの
数値(Numeric)
Numericは親クラス
- Numeric ・・・ 数値クラス
- Integer ・・・ 整数クラス(整数を扱うクラス)
- Float ・・・浮動小数点クラス(小数点以下を扱うクラス)
動的型付け
変数に格納した時に自動的に型が設定されるため、明示的にクラスを書く必要はない。
例)
i = 1はOK
int i = 0はNG
四則演算
irb(main):045:0> 1 + 1 => 2 irb(main):046:0> 10 - 1 => 9 irb(main):047:0> 13 * 2 #掛け算 => 26 irb(main):048:0> 100 / 5 #割り算 => 20irb(main):049:0> x = 1 #xに1を代入 => 1 irb(main):050:0> - x #入れた変数に-をつけると符号を反転させることができる => -1割り算の注意点
irb(main):053:0* 3 / 2 #小数点の計算がされない => 1 #どちらかまたはどちらの数値にも小数点をつける必要がある irb(main):054:0> 3.0 / 2 => 1.5 irb(main):055:0> 3 / 2.0 => 1.5 irb(main):056:0> 3.0 / 2.0 => 1.5irb(main):001:0> 10 % 3 #剰余 => 1 irb(main):002:0> 10 ** 3 #べき乗 => 1000irb(main):004:0> x = 5 #5を代入 => 5 irb(main):005:0> x.to_f #小数に変換 => 5.0 irb(main):006:0> x.to_f / 7 #5を小数に変換し、7で割る => 0.7142857142857143 irb(main):007:0> x / 7 #5 / 7の出力結果 ※小数点は出力されない => 0#クラスの確認 irb(main):008:0> 1.class => Integer irb(main):009:0> 1.1.class => Float #クラスのメソッドの確認 irb(main):010:0> 1.methods => [:%, :&, :*, :+, :-, :/, :<, :>, :^, :|, :~, :-@, :**, :<=>, :<<, :>>, :<=, :>=, :==, :===, :[], :inspect, :size, :succ, :to_int, :to_s, :to_i, :to_f, :next, :div, :upto, :chr, :ord, :coerce, :divmod, :fdiv, :modulo, :remainder, :abs, :magnitude, :integer?, :floor, :ceil, :round, :truncate, :odd?, :even?, :downto, :times, :pred, :bit_length, :digits, :to_r, :numerator, :denominator, :rationalize, :gcd, :lcm, :gcdlcm, :+@, :eql?, :singleton_method_added, :i, :real?, :zero?, :nonzero?, :finite?, :infinite?, :step, :positive?, :negative?, :quo, :arg, :rectangular, :rect, :polar, :real, :imaginary, :imag, :abs2, :angle, :phase, :conjugate, :conj, :to_c, :between?, :clamp, :instance_of?, :kind_of?, :is_a?, :tap, :public_send, :public_method, :singleton_method, :remove_instance_variable, :define_singleton_method, :method, :instance_variable_set, :extend, :to_enum, :enum_for, :=~, :!~, :respond_to?, :freeze, :object_id, :send, :display, :nil?, :hash, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variable_get, :instance_variables, :instance_variable_defined?, :!, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]文字列(String)
文字列はシングルクオートかダブルクオートで囲む。
挙動の違い
irb(main):006:0> "abcde" => "abcde" irb(main):007:0> 'abcde' => "abcde" #この時点での違いはない。irb(main):001:0> puts "Ruby\nProgramming" Ruby Programming => nil irb(main):002:0> puts 'Ruby\nProgramming' Ruby\nProgramming => nil #ダブルクオートで囲むと、文字列の途中で改行される #シングルクオートで囲むと、改行されない ※バックスラッシュはoptionキー+¥キーirb(main):003:0> first_name = "Yuta" => "Yuta" irb(main):004:0> last_name = "Nakamura" => "Nakamura" irb(main):006:0> "My name is #{first_name} #{last_name}" => "My name is Yuta Nakamura" irb(main):007:0> 'My name is #{first_name} #{last_name}' => "My name is \#{first_name} \#{last_name}" #ダブクオートで囲むと#{}で囲んだ文字列が式展開される #シングルクオートではそのまま表示されるまとめ
ダブルクオートを使う場合・・・式展開、改行したい時
シングルクオートを使う場合・・・それ以外
その他文字列の使い方
irb(main):010:0> puts "kengo" + "kaneki" kengokaneki => nil irb(main):011:0> puts "kengo" + " " + "kaneki" kengo kaneki #スペースを開けたい場合、" "を連結破壊的メソッド メソッド名の最後に!を記述
irb(main):017:0> name = 'ken' => "ken" irb(main):018:0> puts name ken => nil #upcaseメソッドの破壊的メソッド irb(main):019:0> name.upcase => "KEN" irb(main):020:0> name => "ken" #変数の中身に変化はない irb(main):021:0> name.upcase! => "KEN" irb(main):022:0> name => "KEN" #変数の中身自体が大文字に書き換わるクラスの確認
irb(main):023:0> "ken".class => Stringメソッドの確認
irb(main):024:0> "ken".methods => [:include?, :%, :*, :+, :to_c, :unicode_normalize, :unicode_normalize!, :unicode_normalized?, :count, :partition, :unpack, :unpack1, :sum, :next, :casecmp, :casecmp?, :insert, :bytesize, :match, :match?, :succ!, :+@, :-@, :index, :rindex, :<=>, :replace, :clear, :upto, :getbyte, :==, :===, :setbyte, :=~, :scrub, :[], :[]=, :chr, :scrub!, :dump, :byteslice, :upcase, :next!, :empty?, :eql?, :downcase, :capitalize, :swapcase, :upcase!, :downcase!, :capitalize!, :swapcase!, :hex, :oct, :split, :lines, :reverse, :chars, :codepoints, :prepend, :bytes, :concat, :<<, :freeze, :inspect, :intern, :end_with?, :crypt, :ljust, :reverse!, :chop, :scan, :gsub, :ord, :start_with?, :length, :size, :rstrip, :succ, :center, :sub, :chomp!, :sub!, :chomp, :rjust, :lstrip!, :gsub!, :chop!, :strip, :to_str, :to_sym, :rstrip!, :tr, :tr_s, :delete, :to_s, :to_i, :tr_s!, :delete!, :squeeze!, :each_line, :squeeze, :strip!, :each_codepoint, :lstrip, :slice!, :rpartition, :each_byte, :each_char, :to_f, :slice, :ascii_only?, :encoding, :force_encoding, :b, :valid_encoding?, :tr!, :encode, :encode!, :hash, :to_r, :<, :>, :<=, :>=, :between?, :clamp, :instance_of?, :kind_of?, :is_a?, :tap, :public_send, :public_method, :singleton_method, :remove_instance_variable, :define_singleton_method, :method, :instance_variable_set, :extend, :to_enum, :enum_for, :!~, :respond_to?, :object_id, :send, :display, :nil?, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variable_get, :instance_variables, :instance_variable_defined?, :!, :!=, :__send__, :
空白文字の使い方
irb(main):025:0> 1 + 2 => 3 irb(main):026:0> 1+2 => 3 irb(main):027:0> 1 +2 + 3 => 6 #スペースはいくら開けても開けなくても挙動に違いはない。 基本的にはスペースを一文字ずつ空けるのが定説