- 投稿日:2021-02-28T23:37:41+09:00
Association ; 1対1、1対多、多対多について
Association
Rails には関連 (Association) という仕組みがある。関連付けを用いて二つのモデルをつなぐことで、コードをシンプル、かつ簡単に書くことができる。
関連付けの関係は大きく分けて以下の三種類に分類される。
- 1 対 1
- 1 対 多
- 多 対 多
1 対 1 (has_one, belongs_to)
例えば、Teacher, Class, Student, Subject のモデルで以下の図のような関係性があったとします。
ここで表されているのは、
- 原田先生 は 2-1 を
- 山川先生 は 2-2 を
担任しているということがわかります。
この場合、Teacherモデルのデータひとつに対し、Classモデルのデータがひとつだけ割り当てられているため、1対1の関係性となっているということになります。
この関係性をコードで表すと以下のようになります。class Teacher < ApplicationRecord has_one :Class end class Class < ApplicationRecord belongs_to :Teacher end1 対 多 (has_many, belongs_to)
ここで表されているのは
- 2-1 には 田中さんと矢島さん
- 2-2 には 中村さんと木下さん
が属しているということがわかります。
この場合、Classモデルのデータひとつに対し、Studentモデルのデータが複数割り当てられているため、1対多の関係性になっているということになります。
この関係性をコードで表すと以下のようになります。class Class < ApplicationRecord has_many :Students end class Student < ApplicationRecord belongs_to :Class end多 対 多 (has_and_belongs_to_many)
最後に、StudentとSubjectの関係性を見てみます。
線が多いため、Studentモデルのデータごとに色分けしております。
ここで表されているのは
- 田中さんは 国語、英語、数学 を受講する
- 矢島さんは 国語、英語、数学 を受講する
- 中村さんは 国語、英語、数学 を受講する
- 木下さんは 国語、英語、数学 を受講する
ということがわかります。
ここで、線の色分けをSubjectモデルのデータごとに変えてみます。
この場合、表されているのは
- 国語を受講するのは 田中さん、矢島さん、中村さん、木下さん
- 英語を受講するのは 田中さん、矢島さん、中村さん、木下さん
- 数学を受講するのは 田中さん、矢島さん、中村さん、木下さん
ということになります。
つまり、Studentモデルのデータひとつに対し、Subjectモデルのデータが複数割り当てられており、またSubjectモデルのデータひとつに対し、Studentモデルのデータが複数割り当てられています。そのため、この関係性は多対多ということになります。
この関係性をコードで表すと以下のようになります。class Student < ApplicationRecord has_and_belongs_to_many :Subjects end class Subject < ApplicationRecord has_and_belongs_to_many :Students end
- 投稿日:2021-02-28T23:34:09+09:00
【Rails】 Deviseを複数導入する場合
はじめに
deviseを導入すると、簡単に認証機能が実装できて本当に便利なgemですよね!
Ruby on Railsを学び始めて2ヶ月目の頃、ユーザーと管理者に分けてdevise機能を2つ実装したい、こういった時はどうしたら良いのか、また複数のdevise間で両者とも使用するモデルに関してはどうしたら良いのか、と少し悩んだことがありましたので、今回の記事のテーマに選定致しました。
前提
今回説明するモデルを以下の三点に絞らせて頂いております。
● devise User
● devise Admin
● 両者に共通してItemモデルを使用
開発環境
ruby 2.6.3
Rails 5.2.4.4
gemを導入
Gemfile.gem 'devise'terminal.$ bundle install
ユーザー用、管理者用のdevise機能実装
deviseを複数実装することは意外と簡単です!
User、Adminのように適宜名前を付け、各コマンドを実行すればモデル、ビュー、コントローラーは作成出来ます。terminal.$ rails g devise:install # ユーザー用のdevise作成 $ rails g devise User name:string $ rails db:migrate $ rails g devise:views users $ rails g devise:controllers users # 管理者用のdevise作成 $ rails g devise Admin $ rails db:migrate $ rails g devise:views admins $ rails g devise:controllers admins
model / controller
ここで少し頭を悩ませることになります。
ECサイトを例にあげると、Item(商品)モデルを必ず作成するかと思います。このItemモデルの働きをユーザーと管理者それぞれの立場で考えてみましょう。● ユーザー
(例)商品を閲覧する、商品の詳細画面へ飛ぶ、注文画面へ遷移する● 管理者
(例)商品を登録するつまり、Itemモデルひとつをとっても、ユーザーと管理者で見る画面も違ければ、コントローラーの記述も異なるわけです。では、ビューとコントローラーをそれぞれで作成するにはどうしたら良いのかをご説明致します。答えは、ビューとコントローラーで「
user
」、「admin
」という親ディレクトリを用意して、その中に各モデルのビューやコントローラーを作成するという形になります。※ 「users」、「admins」というディレクト名だと先ほど作成したdivise用のものと被ってしまい作成できません。そのため単数形の名称にしてあります。どうしても違和感があり気に入らないという場合でしたら、userの代わりに「customers」、「members」などにしても良いかと思います。
terminal.$ rails g model Item $ rails g controller user::items $ rails g controller admin::items(補足)
● モデルは共通で使用できるので、1つのみの作成で大丈夫です。●
rails g controller (親ディレクトリ名)::(その中に作成するディレクトリ名)
上記のように記述することで、自動的に親ディレクトを作成し、その中にコントローラーを作成してくれます。user/items_controller.rbclass User::ItemsController < ApplicationController endコントローラーのディレクトリを確認すると、userディレクトリ内にitems_controller.rb、adminディレクトリ内にitems_controller.rbとひとつのモデルに対し、2つのコントローラーを作成することが出来ました。
ちなみに、コントローラーを作成するときのコマンドでコロンを2つ(::)入力しましたが、これらはコントローラーのファイルのClass名の部分にもきちんと反映されています。どのディレクトリに準ずるコントローラーか、ということが明確になっております。
View
先ほどコントローラーを作成した際に自動的に
userディレクトリ
とadminディレクトリ
が作成されましたが、それに伴い、viewの方にも空のuser/itemsディレクトリ
とadmin/itemsディレクトリ
が作成されています。
それぞれのディレクトリの上で右クリックを押し、必要なファイルを作成してください。
ルーティング
次に悩んだポイントがルーティングの作成です。
共通で使用しているモデルのルーティングに関しても、別々に作成する必要があります。
ルーティング作成時のポイントを3つ簡単に押さえておきます。●
scope
URL: 変える (例) user/items, user/item/:id
ファイル構成: 変えない●
namespace
URL: 変える (例) user/items, user/item/:id
ファイル構成: 指定のパスに変える●
module
URL: 変えない (例) /items, /item/:id
ファイル構成: 指定のパスに変えるconfig/routes.rbRails.application.routes.draw do root 'homes#top' devise_for :admins namespace :admin do resources :items end devise_for :users namespace: :user do resources :items end end(補足)
今回は、自分自身が分かりやすようにディレクトリを分け、またURLにもuserとadminと表示させ分かりやすくしたかった為、namespaceを採用しました。
ご自身の用途に合わせて選択していただければ良いかと思います。
scope
、namespace
、module
について分かりやすくまとめてくださっているサイトがあり、参考にさせていただきましたので、下記にURLを掲載しておきます。(参考)
・Railsのroutingにおけるscope / namespace / module の違い
https://qiita.com/ryosuketter/items/9240d8c2561b5989f049
終わり
今回は以上になります。
ざっくりとした説明で分かりにくい点もあるかと思いますが、申し訳ありません。
私自身もプログラミング初心者ですが、同じ様な立場の方に少しでも参考になればと思っています。
また、もし内容に誤りなどがございましたら、ご指摘いただけますと幸いです。
- 投稿日:2021-02-28T22:46:34+09:00
【Ruby on Rails】before_actionを使って全てのアクションで同じ処理を行う
同じ処理をbefore_actionで定義する。
あるコントローラー内の全てのアクションで1つの処理を使い回したい時。
class Api::V1::Admin::CompanyAdminsController < ApplicationController def index company_admins = CompanyAdmin.where(company_id: params[:company_id]) json_response(200, CompanyAdminIndexSerializer.new(company_admins).to_h) end def show company_admin = CompanyAdmin.find params[:id] json_response(:ok, serialize_data(CompanyAdminIndexSerializer, company_admin)) end def destroy company_admin = CompanyAdmin.find params[:id] company_admin.destroy! json_response(204) end endこのコントローラー内を見てみると、show・destroyアクションで同じ処理が書かれている。
company_admin = CompanyAdmin.find params[:id]これをまとめるために、before_actionと記述する。
これによって、全てのアクションで最初に行いたい処理を実行できる。def load_company_admin @company_admin = CompanyAdmin.find params[:id] end end例えば、上のようなメソッドをコントローラー内に記述する。
そして、コントローラー内の一番上にbefore_actionの記述を加える。最終的なコード
class Api::V1::Admin::CompanyAdminsController < ApplicationController before_action :load_company_admin, only: [:show, :destroy] ##onlyオプションを付け加えることで、showとdestroyアクションのときと指定ができる。 def index company_admins = CompanyAdmin.where(company_id: params[:company_id]) json_response(200, CompanyAdminIndexSerializer.new(company_admins).to_h) end def show json_response(:ok, serialize_data(CompanyAdminIndexSerializer, @company_admin)) end def destroy @company_admin.destroy! json_response(204) end private def load_company_admin ##処理の名前を定義する。 @company_admin = CompanyAdmin.find params[:id] end ##ここで同じ処理を記述する。 end少しだけ、このファイルの記述がスッキリした気がする。
何度も同じ記述を書くのはエンジニアとして、あまり優秀ではない気がしているので、できるだけ同じ処理はまとめていきましょう。
- 投稿日:2021-02-28T22:08:26+09:00
【Railsチュートリアル】第10章 ユーザーの更新・表示・削除②
10.3 すべてのユーザーを表示する
index
アクションを追加して、すべてのユーザーを一覧表示する。データベースにサンプルデータを追加する方法や、将来ユーザー数が膨大になってもindexページを問題なく表示できるようにするためのユーザー出力のページネーション(pagination=ページ分割)の方法を学ぶ。10.3.1 ユーザーの一覧ページ
ユーザーのindexページはログインしたユーザーにしか見せないようにし、未登録のユーザーがデフォルトで表示できるページを制限する。
indexアクションが正しくリダイレクトするか検証するテストを書く。
test/controllers/users_controller_test.rbrequire 'test_helper' class UsersControllerTest < ActionDispatch::IntegrationTest def setup @user = users(:michael) @other_user = users(:archer) end test "should get new" do get signup_path assert_response :success end test "should redirect index when not logged in" do # ログインしていない場合はインデックスをリダイレクトするテストを行う get users_path assert_redirected_to login_url end . . .beforeフィルターのlogged_in_userにindexアクションを追加して、このアクションを保護。
app/controllers/users_controller.rbclass UsersController < ApplicationController before_action :logged_in_user, only: [:index, :edit, :update] # 「indexアクションが呼び出されたらlogged_in_userアクションを実行する」を追加 before_action :correct_user, only: [:edit, :update] def index end def show @user = User.find(params[:id]) end . . . endindexビューの実装。User.allを使ってデータベース上の全ユーザーを取得し、ビューで使えるインスタンス変数@usersに代入する。
app/controllers/users_controller.rbclass UsersController < ApplicationController before_action :logged_in_user, only: [:index, :edit, :update] . . . def index @users = User.all end . . . endapp/views/users/index.html.erb<% provide(:title, 'All users') %> <h1>All users</h1> <ul class="users"> <% @users.each do |user| %> <li> <%= gravatar_for user, size: 50 %> <%= link_to user.name, user %> </li> <% end %> </ul>
users_helper.rb
,custom.scss
,_header.html.erb
にコードを追加してrails.test
演習 1
レイアウトにあるすべてのリンクに対して統合テストを書いてみましょう。ログイン済みユーザーとそうでないユーザーのそれぞれに対して、正しい振る舞いを考えてください。ヒント: log_in_asヘルパーを使ってリスト 5.32にテストを追加してみましょう。
test/integration/site_layout_test.rbrequire 'test_helper' class SiteLayoutTest < ActionDispatch::IntegrationTest test "layout links" do get root_path assert_template 'static_pages/home' assert_select "a[href=?]", root_path, count: 2 assert_select "a[href=?]", help_path assert_select "a[href=?]", about_path assert_select "a[href=?]", contact_path assert_select "a[href=?]", login_path get contact_path assert_select "title", full_title("Contact") get signup_path assert_select "title", full_title("Sign up") end def setup @user = users(:michael) end test "layout links when loged in" do log_in_as(@user) # => テストユーザーでログイン get root_path assert_template 'static_pages/home' assert_select "a[href=?]", users_path # => /users ユーザー一覧ページ assert_select "a[href=?]", user_path(@user) # => /users/:id Profileページ assert_select "a[href=?]", edit_user_path(@user) # => /users/1/:id Settingsページ assert_select "a[href=?]", logout_path end end10.3.2 サンプルのユーザー
indexページに複数のユーザーを表示させる。
演習 1
試しに他人の編集ページにアクセスしてみて、10.2.2で実装したようにリダイレクトされるかどうかを確かめてみましょう。
確認のみなので省略。10.3.3 ページネーション
1つのページに一度に30人だけユーザーを表示するというようなページネーション(pagination)を実装する。
演習 1
Railsコンソールを開き、pageオプションにnilをセットして実行すると、1ページ目のユーザーが取得できることを確認してみましょう。
>> User.paginate(page: nil) (0.1ms) begin transaction User Load (2.9ms) SELECT "users".* FROM "users" LIMIT ? OFFSET ? [["LIMIT", 11], ["OFFSET", 0]] (1.7ms) SELECT COUNT(*) FROM "users" => #<ActiveRecord::Relation [#<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2021-02-26 14:35:28", updated_at: "2021-02-26 14:35:28", password_digest: [FILTERED], remember_digest: nil>, #<User id: 2, name: "William Bartell", email: "example-1@railstutorial.org", created_at: "2021-02-26 14:35:30", updated_at: "2021-02-26 14:35:30", password_digest: [FILTERED], remember_digest: nil>, #<User id: 3, name: "Carter Feest", email: "example-2@railstutorial.org", created_at: "2021-02-26 14:35:30", updated_at: "2021-02-26 14:35:30", password_digest: [FILTERED], remember_digest: nil>, #<User id: 4, name: "Arlinda Douglas Sr.", email: "example-3@railstutorial.org", created_at: "2021-02-26 14:35:30", updated_at: "2021-02-26 14:35:30", password_digest: [FILTERED], remember_digest: nil>, #<User id: 5, name: "Dr. Monika Goyette", email: "example-4@railstutorial.org", created_at: "2021-02-26 14:35:31", updated_at: "2021-02-26 14:35:31", password_digest: [FILTERED], remember_digest: nil>, #<User id: 6, name: "Mr. Hilda Prohaska", email: "example-5@railstutorial.org", created_at: "2021-02-26 14:35:31", updated_at: "2021-02-26 14:35:31", password_digest: [FILTERED], remember_digest: nil>, #<User id: 7, name: "Theo Russel", email: "example-6@railstutorial.org", created_at: "2021-02-26 14:35:31", updated_at: "2021-02-26 14:35:31", password_digest: [FILTERED], remember_digest: nil>, #<User id: 8, name: "Robbie Littel", email: "example-7@railstutorial.org", created_at: "2021-02-26 14:35:31", updated_at: "2021-02-26 14:35:31", password_digest: [FILTERED], remember_digest: nil>, #<User id: 9, name: "Azzie Walter", email: "example-8@railstutorial.org", created_at: "2021-02-26 14:35:32", updated_at: "2021-02-26 14:35:32", password_digest: [FILTERED], remember_digest: nil>, #<User id: 10, name: "Shanell Nicolas", email: "example-9@railstutorial.org", created_at: "2021-02-26 14:35:32", updated_at: "2021-02-26 14:35:32", password_digest: [FILTERED], remember_digest: nil>, ...]>演習 2
先ほどの演習課題で取得したpaginationオブジェクトは、何クラスでしょうか? また、User.allのクラスとどこが違うでしょうか? 比較してみてください。
class: User::ActiveRecord_Relation
User.allと同じ。10.3.4 ユーザー一覧のテスト
ページネーションに対する簡単なテストも書いておく。
ログイン→indexページにアクセス→最初のページにユーザーがいることを確認→ページネーションのリンクがあることを確認の手順でテストしていく。演習 1
試しにリスト 10.45にあるページネーションのリンク(will_paginateの部分)を2つともコメントアウトしてみて、リスト 10.48のテストが red に変わるかどうか確かめてみましょう。
FAIL["test_index_including_pagination", #<Minitest::Reporters::Suite:0x000056137403b7a8 @name="UsersIndexTest">, 14.158692726000027] test_index_including_pagination#UsersIndexTest (14.16s) Expected at least 1 element matching "div.pagination", found 0.. Expected 0 to be >= 1. test/integration/users_index_test.rb:13:in `block in <class:UsersIndexTest>'red
演習 2
先ほどは2つともコメントアウトしましたが、1つだけコメントアウトした場合、テストが green のままであることを確認してみましょう。will_paginateのリンクが2つとも存在していることをテストしたい場合は、どのようなテストを追加すれば良いでしょうか? ヒント: 表 5.2を参考にして、数をカウントするテストを追加してみましょう。
test/integration/users_index_test.rbrequire 'test_helper' class UsersIndexTest < ActionDispatch::IntegrationTest def setup @user = users(:michael) end test "index including pagination" do log_in_as(@user) get users_path assert_template 'users/index' assert_select 'div.pagination', count: 2 # 「count: 2」を追記 User.paginate(page: 1).each do |user| assert_select 'a[href=?]', user_path(user), text: user.name end end endFAIL["test_index_including_pagination", #<Minitest::Reporters::Suite:0x0000561374244360 @name="UsersIndexTest">, 16.980905499999608] test_index_including_pagination#UsersIndexTest (16.98s) Expected exactly 2 elements matching "div.pagination", found 1.. Expected: 2 Actual: 1 test/integration/users_index_test.rb:13:in `block in <class:UsersIndexTest>'10.3.5 パーシャルのリファクタリング
一覧ページのリファクタリングを行う。
演習 1
リスト 10.52にあるrenderの行をコメントアウトし、テストの結果が red に変わることを確認してみましょう。
REDになりました。
10.4 ユーザーを削除する
削除を実行できる権限を持つ管理(admin)ユーザーのクラスを作成する。
次にユーザーを削除するためのリンクを追加し、削除を行うのに必要なdestroyアクションも実装する。10.4.1 管理ユーザー
Boolean型 とは?
真理値の「真 = true」と「偽 = false」という2値をとるデータ型のこと。toggle!メソッド とは?
toggle!(:flag)と書き、属性(:flag)を反転し保存するメソッド。saveに成功したらtrueを返す。演習 1
Web経由でadmin属性を変更できないことを確認してみましょう。具体的には、リスト 10.56に示したように、PATCHを直接ユーザーのURL(/users/:id)に送信するテストを作成してみてください。テストが正しい振る舞いをしているかどうか確信を得るために、まずはadminをuser_paramsメソッド内の許可されたパラメータ一覧に追加するところから始めてみましょう。最初のテストの結果は red になるはずです。最後の行では、更新済みのユーザー情報をデータベースから読み込めることを確認します( 6.1.5)。
test/controllers/users_controller_test.rbtest "should not allow the admin attribute to be edited via the web" do log_in_as(@other_user) # テストユーザー(@other_user)でログイン assert_not @other_user.admin? # @other_userは管理者か?=> 管理者ではない => false # @other_user.admin?がfalse => 成功 patch user_path(@other_user), params: { user: { password: "password", password_confirmation: "password", admin: true } } # @other_userに管理者権限を持たせる => admin: true assert_not @other_user.reload.admin? # 更新した@other_userは管理者か? => 管理者ではない => false # @other_user.reload.admin?がfalse => 成功 endassert_not とは?
assert_not hogeの場合 => hoge が trueなら失敗、falseなら成功。10.4.2 destroyアクション
destroyアクションへのリンクを追加する。
ユーザーindexページの各ユーザーに削除用のリンクを追加し、続いて管理ユーザーへのアクセスを制限する。演習 1
管理者ユーザーとしてログインし、試しにサンプルユーザを2〜3人削除してみましょう。ユーザーを削除すると、Railsサーバーのログにはどのような情報が表示されるでしょうか?
Started DELETE "/users/4" for 10.0.2.2 at 2021-02-28 19:28:49 +0900 Cannot render console from 10.0.2.2! Allowed networks: 127.0.0.0/127.255.255.255, ::1 Processing by UsersController#destroy as HTML Parameters: {"authenticity_token"=>"ZUaUvmxMfqGHERKzsE1flF1BHJkxUkLesSKKx047CAkzYAOz6jB3wQrDRQ2xHloAba4P/r9CRI1XAATfArRZTw==", "id"=>"4"} User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] ↳ app/helpers/sessions_helper.rb:18:in `current_user' User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 4], ["LIMIT", 1]] ↳ app/controllers/users_controller.rb:52:in `destroy' (0.1ms) begin transaction ↳ app/controllers/users_controller.rb:52:in `destroy' User Destroy (7.1ms) DELETE FROM "users" WHERE "users"."id" = ? [["id", 4]] ↳ app/controllers/users_controller.rb:52:in `destroy' (13.6ms) commit transaction ↳ app/controllers/users_controller.rb:52:in `destroy' Redirected to http://localhost:3000/users Completed 302 Found in 46ms (ActiveRecord: 22.7ms | Allocations: 4317)10.4.3 ユーザー削除のテスト
演習 1
試しにリスト 10.59にある管理者ユーザーのbeforeフィルターをコメントアウトしてみて、テストの結果が red に変わることを確認してみましょう。
確認のみなので省略。
さいごに
Webアプリケーションとしての基礎を整えられたようです。
Railsチュートリアルをはじめたばかりの頃はエラーが出ただけで焦っていました。
ですが今では冷静にエラーを読む、わからなければ検索するというのが自然とできるようになりました。
コードもだんだんと読み下せるようになってきました。一歩ずつ前に進んでいる気がします。次章もがんばります!
- 投稿日:2021-02-28T21:52:57+09:00
一覧表示での進捗率ゲージの作成
はじめに
オリジナルアプリでクラウドファンディングサイトを作成した際に、
jQueryを使って進捗率ゲージを作成したので紹介します。
前回、詳細画面での作成方法を紹介しましたが
今回は一覧表示画面での作成方法です。詳細画面での作成はこちら→
https://qiita.com/takiguchiharuna1221/items/df517f2a9e4b74299328#comment-bd0d8efa2c7c3dc7651e
※こちらではlinear-gradientを使った別の方法も投稿していただいています。初学者なのでより良い方法が他にもあるかもしれませんが、どなたかの参考になれば嬉しいです。
環境
・Rails 6.0.0
・Ruby 2.6.5
・jQuery作成手順
【view】
index.html.haml.Contents__projects - @projects.each do |project| # 一部省略 .Projects = link_to display_project_path(project.id) , class: "Box3"do .Box1 = image_tag project.image.url.to_s, class: "Box1__image" .Box2 %p.Box2__title= project.title %p.Box2__percent__contents 進捗率 - @percent = number_to_percentage(@total.to_f/project.target_amount*100,precision: 1) = @percent .contents-pacent__box2__graph1 .contents-pacent__box2__graph2 %input{name: "percent", type: "hidden", value:@percent, class: 'percent' }①ゲージを挿入したい部分にクラスを設定します。
→.contents-pacent_box2_graph2の部分②inptを用いてDBのインスタンス変数の値を取得します。
→inputのvalueに変数を設定することでjQueryで変数を使えるようにします。
※今回は変数の詳細は割愛します。
参考記事:https://qiita.com/Kohei_Kishimoto0214/items/d919b00d75dec0699cf0【CSS】
_project.scss.contents-pacent__box2__graph2{ background-color: #ea662d; height: 15px; border-radius: 6px; max-width: 100%; }③CSSは以上の通りです。
進捗率が100%以上になっても突き抜けてしまわないように
max-width: 100%;を設定しています。【jQuery】
project.js$(function() { $('.percent').each(function(i){ $(this).attr('id', `percent_${i}`); }); $('.contents-pacent__box2__graph2').each(function(i){ $(this).attr('id', `graph_${i}`); }); (window.onload = function() { var ele = document.getElementsByClassName("Projects"); for(var i = 0; i < ele.length; i++){ $("#graph_"+i).css({ 'width' : $( "#percent_"+ i).val() } ); }; }); });④.percentと.contents-pacent_box2_graph2のそれぞれにidを振ります。
⑤リロードのタイミングでProjectsの数を数え、その回数だけ
”.contents-pacent_box2_graph2のwidthの値を@percentからとる”
を繰り返すように①で付与したidを使ってfor文で設定します。最後に
idの使い方やfor文の設定が自分では使ったことがなかったので苦労しました。
日々勉強します。
- 投稿日:2021-02-28T21:45:10+09:00
RSpec:モデルの単体テストの記述例
今回は前回の記事「RSpecの導入&関係の深いgemについて」の続きで、モデルの単体テストを行います。
前回の記事の各gemのインストール、初期設定が完了していることを前提としています。
モデルのテストファイルを作成
ターミナルで
rails g rspec model モデル名
コマンドを入力してテストファイルを生成します。ターミナル$ rails g rspec model モデル名 #以下のように表示されればテストファイルの生成が成功しています。 Running via Spring preloader in process 1234 create spec/models/モデル名_spec.rb invoke factory_bot create spec/factories/モデル名の複数形.rbたとえばuserモデルのテストファイルを生成するとこうなります。
ターミナル$ rails g rspec:model user Running via Spring preloader in process 1234 create spec/models/user_spec.rb invoke factory_bot create spec/factories/users.rb #Factory Botをインストールしておくと自動生成されるちなみに事前にFactory Botもインストールしておくと、
spec/factories/users.rb
は自動生成されます。生成した
user_spec.rb
にはこのような記述がされています。spec/models/user_spec.rbrequire 'rails_helper' RSpec.describe User, type: :model do pending "add some examples to (or delete) #{__FILE__}" end
do〜end
の間にテストコードを記述していきます。また1行目の
require 'rails_helper
は、前回の記事で行ったrails g rspec:install
コマンドで生成したrails_helper.rb
を読み込んでいます。FactoryBotの設定
まずは、FactoryBotでUserモデルのテストで使用するインスタンスを設定してまとめます。
spec/factories/users.rbFactoryBot.define do factory :user do name { Faker::Name } email { Faker::Internet.free_email } password = Faker::Internet.password(min_length: 6) password { password } password_confirmation { password } end endpasswordカラムとpassword_confirmationカラムは同じ値を入れるため、変数
password
に値を代入して、各カラムに変数password
を入れます。
Faker::
の後ろに続くName
やInternet.free_email
でどんな値をランダムに生成するかを指定しています。前者なら名前、後者ならメールアドレスですね。Fakerでは色んなタイプの値を生成してくれるので、Fakerの公式GitHubで見てみてください。
テストコードの設定
Userモデル(usersテーブル)にnameカラム、emailカラム、passwordカラムがあると想定して、
たとえば以下のようにユーザー新規登録機能のテストコードを記述します。spec/models/user_spec.rbrequire 'rails_helper' RSpec.describe User, type: :model do before do # 各テストコードが実行される前にFactoryBotで生成したインスタンスを@userに代入 @user = FactoryBot.build(:user) end # describeでテスト対象をグループ分け describe '新規登録' do # contextでどのような状況なのかをグループ分け context '新規登録できるとき' do # itで何をテストしているのかをグループ分け it '全ての項目が入力されていれば登録できる' do expect(@user).to be_valid end end context '新規登録できないとき' do it 'nameが空では登録できない' do @user.name = '' @user.valid? expect(@user.errors.full_messages).to include("Name can't be blank") end it 'emailが空では登録できない' do @user.email = '' @user.valid? expect(@user.errors.full_messages).to include("Email can't be blank") end it '重複したemailが存在する場合登録できない' do @user.save another_user = FactoryBot.build(:user) another_user.email = @user.email another_user.valid? expect(another_user.errors.full_messages).to include('Email has already been taken') end it 'emailに@が含まれていないと登録できない' do @user.email.slice!('@') @user.valid? expect(@user.errors.full_messages).to include('Email is invalid') end it 'passwordが空では登録できない' do @user.password = '' @user.valid? expect(@user.errors.full_messages).to include("Password can't be blank") end it 'passwordが5文字以下では登録できない' do @user.password = '123ab' @user.valid? expect(@user.errors.full_messages).to include('Password is too short (minimum is 6 characters)') end it 'passwordが存在してもpassword_confirmationが空では登録できない' do @user.password_confirmation = '' @user.valid? expect(@user.errors.full_messages).to include("Password confirmation doesn't match Password") end end end endbefore do ~ end
テストコードの最初の
before do ~ end
は、describe以下の各テストコードが実行される前に処理される共通の内容を記述します。
今回の場合は登録するユーザー情報を変数@user
に代入する処理を記述しています。
これで各テストコードでユーザー情報が入った変数@user
を使えるようになりました。describeメソッド、contextメソッド、itメソッド
テストコードのグループ分けに使用するメソッドで、
describe
メソッドはどのような機能なのか(テスト対象)context
メソッドはどのような状況なのかit
メソッドは何をテストしているのかをそれぞれグループ分けしています。
expectation(エクスペクテーション)
一番最初の「
describe
新規登録、context
新規登録できるとき、it
全ての項目が入力されていれば登録できる」の中にあるような以下のような記述の部分をexpectation
といい、テストで得られた結果が期待通りなのかを確認する構文です。expect(@user).to be_valid上記の記述のうち、
be_valid
の部分をmatcher(マッチャ)
といいます。matcher
「expectの引数(カッコの中の記述)」と「想定した挙動」が一致しているか判断します。
expectの引数にはテストで得られた実際の挙動を指定し、matcherにはどのような挙動を想定しているかを記述します単体テストでよく使うmatcherの例
matcher 想定する挙動 記述例 include Xの中にYという文字列が含まれているか expect(X).to include(Y) be_valid expectのインスタンスが正しく保存される expect(X).to be_valid テストコードの実行
少し補足説明がなりましたが、上記のテストコードの実行をします。
ターミナルで以下のコマンドを入力します。ターミナル$ bundle exec rspec spec/models/user_spec.rb # 実行結果 User 新規登録 新規登録できるとき 全ての項目が入力されていれば登録できる passwordが6文字以上の半角英数字であれば登録できる identityが空で登録できる 新規登録できないとき nameが空では登録できない emailが空では登録できない 重複したemailが存在する場合登録できない emailに@が含まれていないと登録できない passwordが空では登録できない passwordが5文字以下では登録できない passwordが存在してもpassword_confirmationが空では登録できない Finished in 0.07492 seconds (files took 1.3 seconds to load) 10 examples, 0 failures上記ではエラーなくテストが完了しましたが、expectationに記述されているmatcherのエラーメッセージなどに記述ミスがある場合は修正する必要があります。
テストコードの修正には
pry-rails
というデバッグ用のgemを使用するのですが、それは別の記事で紹介したいと思います。RSpecのシリーズ記事
第1回:RSpecの導入&関係の深いgemについて
第2回:RSpec:モデルの単体テストの記述例 ※この記事参考資料
RSpec: Behaviour Driven Development for Ruby
Qiita:
使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」
- 投稿日:2021-02-28T21:44:47+09:00
[解決] Railsの言語設定エラー 'translation missing: ja.datetime.distance_in_words.x_days ago'
現状確認
ruby 2.6.6
Rails 6.1.0インスタンス変数は、正しく定義されている。
[1] pry(#<#<Class:0x00007ff69c4e9978>>)> @post.created_at => Sun, 31 Jan 2021 08:28:26.434149000 UTC +00:00 [2] pry(#<#<Class:0x00007ff69c4e9978>>)> time_ago_in_words(@post.created_at) => "translation missing: ja.datetime.distance_in_words.x_days"ファイルを見ると、日本語になっている(自分がen→jaに変えたことに気づいていなかった)
application.rbconfig.i18n.default_locale = :ja解決
今までtime_ago_in_wordsは英語設定だったから、上記の日本語変更でエラーが起きたっぽい
time_ago_in_wordsを日本語化するする
locales/ja.ymlにこれを書く
ja: datetime: distance_in_words: half_a_minute: "30秒前後" less_than_x_seconds: one: "1秒" other: "%{count}秒" x_seconds: one: "1秒" other: "%{count}秒" less_than_x_minutes: one: "1分" other: "%{count}分" x_minutes: one: "約1分" other: "%{count}分" about_x_hours: one: "約1時間" other: "約%{count}時間" x_days: one: "1日" other: "%{count}日" about_x_months: one: "約1ヶ月" other: "約%{count}ヶ月" x_months: one: "1ヶ月" other: "%{count}ヶ月" almost_x_years: one: "1年弱" other: "%{count}年弱" about_x_years: one: "約1年" other: "約%{count}年" over_x_years: one: "1年以上" other: "%{count}年以上"ブラウザで確認した、エラーは無くなっていた。
参考
【Rails】time_ago_in_words メソッドで created_atを「〜前」と表示する | RemoNote
- 投稿日:2021-02-28T21:11:10+09:00
【Rails】Capistrano main以外のブランチをデプロイする方法
通常、mainブランチをcapistranoでデプロイする時、このように入力すると思います。
$ bundle exec cap production deployただ、開発中にmain以外のブランチをデプロイして確認したい時もあると思います。
そんな時は、config/deploy.rbに追記して
$ set :branch, ENV['BRANCH'] || "main"デプロイする。
bundle exec cap production deploy BRANCH=ブランチ名
特に指定しなければmainが、main以外ならブランチ名を指定してやれば、それぞれデプロイできます。
- 投稿日:2021-02-28T21:01:42+09:00
ActiveRecord includesとselectの別名カラム
概要
ActiveRecord includesを使う際、selectに別名カラムの記述があると
その別名カラムの参照ができない事象があったので、記事にしました。開発環境
- ruby 2.6.5
- Rails 5.2.4.4
ActiveRecordクラス 定義
class User < ApplicationRecord has_one :house end class House < ApplicationRecord belongs_to :user belongs_to :house_info end class HouseInfo < ApplicationRecord has_one :house end問題ない場合のincludes構文
- 問題なくuserインスタンスが取得できた (preloadの挙動になる)
User.includes(house: :house_info).select('users.id, users.created_at as user_registed_at') SELECT users.id, users.created_at as user_registed_at FROM "users" SELECT "houses".* FROM "houses" WHERE "houses"."user_id" = $1 [#<User:0x000055a87e374e58 id: 1>, #<User:0x000055a87e3742c8 id: 2>, #<User:0x000055a87e37f858 id: 3>, #<User:0x000055a87e37ecc8 id: 4>, #<User:0x000055a87e37e1b0 id: 5>]
- selectで指定した別名カラムの値も取得できる
User.includes(house: :house_info).select('users.id, users.created_at as user_registed_at').first.user_registed_at SELECT users.id, users.created_at as user_registed_at FROM "users" SELECT "houses".* FROM "houses" WHERE "houses"."user_id" = $1 => "2021-02-05T13:02:17.754+09:00"問題ありのincludes構文
includesしたテーブルに対し、検索条件(where)を追記してみた
- house_infoのownerカラムをwhere条件にいれると left outter joinとなり、テーブルそれぞれのカラムが別名のsqlが発行される(eager_loadの挙動になる)
User.includes(house: :house_info).where(house_infos: { owner: '太郎' }).select('users.id, users.created_at as user_registed_at') SELECT users.id, users.created_at as user_registed_at, "users"."id" AS t0_r0, "users"."name" AS t0_r1, "interviews"."creator_id" AS t0_r2, "houses"."user_id" AS t0_r3, "houses"."house_info_id" AS t0_r4, "house_infos"."address" AS t0_r5, "house_infos"."owner" AS t0_r6 FROM "users" LEFT OUTER JOIN "houses" ON "houses"."interview_id" = "users"."id" LEFT OUTER JOIN "house_infos" ON "house_infos"."id" = "houses"."house_info_id" WHERE "house_infos"."owner" = '太郎' [#<User:0x000055a879e296c8 id: 1, created_at: 2020/12/12> ]
- select で別名指定した
user_registed_at
はsql上、存在するが、モデルから参照できない。User.includes(house: :house_info).where(house_infos: { owner: '太郎' }).select('users.id, users.created_at as user_registed_at').first.user_registed_at NoMethodError: undefined method `user_registed_at' for #<User:0x000055a87c1a93c8> from /bundle/gems/activemodel-5.2.4.4/lib/active_model/attribute_methods.rb:430:in `method_missing'includesをやめて解決
house
とhouse_info
を joinし、preloadでキャッシュするようにしたUser.joins(house: :house_info).preload(house: :house_info).where(house_infos: { owner: '太郎' }).select('users.id, users.created_at as user_registed_at') SELECT users.id, users.created_at as user_registed_at FROM "users" INNER JOIN "houses" ON "houses"."user_id" = "users"."id" INNER JOIN "house_infos" ON "house_infos"."id" = "houses"."house_info_id" WHERE "house_infos"."owner" = '太郎' SELECT "houses".* FROM "houses" WHERE "houses"."user_id" IN ($1, $2, $3, $4, $5) SELECT "house_infos".* FROM "house_infos" WHERE "house_infos"."id" IN ($1, $2, $3, $4, $5) [#<User:0x000055a87d6fb410 id: 1>, #<User:0x000055a87d6fa8f8 id: 2>, #<User:0x000055a87d6f9de0 id: 3>, . .
- 各モデルから
user_registed_at
が参照できるようになった。User.joins(house: :house_info).preload(house: :house_info).where(house_infos: { owner: '太郎' }).select('users.id, users.created_at as user_registed_at').first.user_registed_at => "2021-02-05T13:05:47.225+09:00"includesの挙動について調べてみた
- includesはjoinsがなければpreloadと同じ挙動となる
- 明示的にeager_loadと同じ挙動にするためにはreferencesというメソッドを併用する必要
User.includes(house: :house_info).references(house: :house_info).select('users.id, users.created_at as user_registed_at') SELECT users.id, users.created_at as user_registed_at, "users"."id" AS t0_r0, "users"."name" AS t0_r1, "interviews"."creator_id" AS t0_r2, "houses"."user_id" AS t0_r3, "houses"."house_info_id" AS t0_r4, "house_infos"."address" AS t0_r5, "house_infos"."owner" AS t0_r6 FROM "users" LEFT OUTER JOIN "houses" ON "houses"."interview_id" = "users"."id" LEFT OUTER JOIN "house_infos" ON "house_infos"."id" = "houses"."house_info_id"なぜ?別名カラムをモデルから参照できなかったのか?
https://github.com/rails/rails/issues/34889
バグだったらしく、Rails6.0.3で治っているよう。最後に
includesはケースによって
preloadまたはeager_loadの挙動をするのは知っていたが、
selectで指定した別名カラムの参照問題は知らず、、1日ハマっていた。
やっぱり、ActiveRecordはハマりポイントが多そう。
- 投稿日:2021-02-28T19:42:37+09:00
RubyでHit&Blow書いてみた
ここの数当てゲーム2を解いてみました
コード
class Answer def initialize(digits) num = %w[1 2 3 4 5 6 7 8 9] first_num = num.delete(num.sample) remaining_num = num.push("0").sample(digits - 1) @answer = [first_num, *remaining_num] @count_hit_and_blow = Hash.new(0) @digits = digits end def judge_hit(entry) entry_judeged_hit = entry.dup entry.zip(@answer) do |n| if n.uniq! @count_hit_and_blow[:hit] += 1 entry_judeged_hit.delete(n[0]) end end entry_judeged_hit end def judge_blow(entry_judeged_hit) blow_count = entry_judeged_hit.intersection(@answer).size entry_has_blow = blow_count != 0 @count_hit_and_blow[:blow] = blow_count if entry_has_blow end def judge_game @count_hit_and_blow.each { |k, v| print "#{v}#{k} " } print "\n" if @count_hit_and_blow[:hit] == @digits sleep 0.5 puts "game clear", "congratulations!!!!!" exit end @count_hit_and_blow.clear end end def input_digits loop do print "答えの桁数を入力してください: " digits = gets unless digits.match?(/^[0-9]+$/) && digits.to_i <= 10 puts "不正な値であるか""別の値を入力してください\n\n" next end break digits.to_i end end def input_entry(digits) loop do print "回答を入力してください: " entry = gets.chomp exit if entry.empty? entry_is_suitable_number = entry.match?(/^[0-9]+$/) && entry.size == digits entry_is_uniqe = (ary_entry = entry.chars) && !ary_entry.uniq! unless entry_is_suitable_number && entry_is_uniqe puts "不正なであるか重複した数字がある値です", "別の値を入力して下さい\n\n" next end break ary_entry end end # --------------実行部分-------------- puts "数当てゲーム、Hit&Blowを始めます(空行を入力すると終了します)\n\n" sleep 1 digits = input_digits answer = Answer.new(digits) puts "\nゲームスタート!\n\n" loop do entry = input_entry(digits) entry_judeged_hit = answer.judge_hit(entry) answer.judge_blow(entry_judeged_hit) answer.judge_game end完走した感想
難しかった(小並感)
num = %w[1 2 3 4 5 6 7 8 9] first_num = num.delete(num.sample) remaining_num = num.push("0").sample(digits - 1) @answer = [first_num, *remaining_num]簡単にググってみた所、答えの生成にこれよりスリムなコードが無かったので嬉しかった
- 投稿日:2021-02-28T18:02:09+09:00
【Rubyで検証】普通な人はあまり存在しない件 〜 普通の人とマッチングする確率とは?な話
「私、結婚する人の条件はふつうな人(年収700万)でいいの〜」
(なお、サラリーマンの平均年収は約400万)みたいな話は有名かと思いますが、ほんとうに普通の人ってなかなかいないよねというお話です
(半分真面目に、半分ふざけて計算してみた)今回のメインテーマ
ざっくり話をまとめると、次のようなことをお伝えする記事となっております
- 普通の人ってどのくらいの確率で存在するの?
- ↑の計算するのにRubyでどうプログラムすれば良いの?
この記事をきっかけに、
統計
やRuby
について親しみを持ってもらえればと思います前提
まずは前提条件を整理しておかないと変な文句を言われかねないので、整理しておきます(というかこれをしないと計算できない)
普通の人の定義
以下の各項目の偏差値が50以上とします(これは普通ぐらいでいてほしいとみんなが思いそうなことをあげてみました)
- 身長
- 顔
- 頭脳(学歴とも言う)
- 性格
- 年収
- ファッション
分布
全てのステータスは正規分布に従うと仮定するその他補足
それぞれのステータスは独立しており、他のステータスに影響を与えない
(高身長だと高年収になるというような関係は無視する)計算してみる
各ステータスについて、偏差値50以下と50以上で数が半々になるので、偏差値50以上となる確率は1/2です
ステータスは6つを想定しているので、全て50以上となる確率は単純に
\frac{1}{2}^6=\frac{1}{64}≒0.0156=1.56 [\%]つまりたったの2%程度です?
普通というぐらいだから最低でも40〜50%程度には落ち着いてもらいたいところ
ではどこまで妥協すれば良いのでしょうか?
やり方としては、次の2つがありそうです?
1. 普通であってほしいステータスを絞る
2. 普通という基準を下げる(基準の偏差値を50より小さくする)検証①
1つ目の方法は一瞬で終わります
ステータスが1つの場合は確率が50%
ステータスが2つの場合は50% × 50%
で25%25%(4人に1人)を普通というのは苦しいので、この方法を取る場合は、普通であって欲しいステータスは1つまでということになります(うーん厳しい)?
検証②
こちらは期待する偏差値をどこまで下げたら良いの?ということですが、やや面倒です?
計算で出そうとすると、次のような手順になりましょう
(話が多少面倒なので、(ここから)
〜(ここまで)
間は読み飛ばしてもOKです)
(ここから)
ある偏差値s
以上の確率をp
としたときに、全てのステータスがある偏差値s
以上になる確率が50%になれば良い全てのステータスが
s
以上になる確率は次のように計算できる\begin{align} \qquad &p^6 = 0.5\\ \therefore &p = 0.89 = 89 [\%] \end{align}つまり存在確率が
89%
となる偏差値s
を求めれば良いということになるこれを計算するには正規分布の確率密度関数を
s
から無限大の範囲で積分したときに89%
となるs
を求めれば良いということになる(タブン)
(ここまで)
しかしそんな計算したくない(というか自分には多分ムリ)
なのでプログラミングで概算値をざっと算出してみることにしました
※ この手の計算は
Python
やR
を使ったほうが楽に計算できるのかと思いますが、あいにく筆者はそのへん使い慣れてないので、今回はRubyで無理やりやることにしています(汗)プログラムの概要
次の手順で算出していこうと思います
(ゴールはここまでは妥協すべきという偏差値を求めることです)
- 人物のモデルを作成
- インスタンス作成時に6つのステータスを付与
- ステータスは正規分布にしたがってランダムに与えられる
- 10000人分のインスタンスを作成し、全てのステータスが偏差値50以上となる人数をカウントし、その存在確率を算出する
- 存在確率が50%を下回ったら、期待する偏差値を1下げて再び存在確率を算出
- 50%以上となる偏差値を求める
※ 10000という試行回数については、このぐらいやれば問題ないだろうという勝手な数値としています。何度かこの条件で計算して、そこまで数値がぶれなかったのでまあ問題ないと判断しています
プログラムの内容
まずはPersonモデルを作成します
person.rbrequire './rand' class Person attr_accessor :height, :face, :brain, :personality, :income, :fashion MU_SIGMA = { mu: 50, sigma: 10 } def initialize(expectation) @height = Random.new.normal_rand(**MU_SIGMA) @face = Random.new.normal_rand(**MU_SIGMA) @brain = Random.new.normal_rand(**MU_SIGMA) @personality = Random.new.normal_rand(**MU_SIGMA) @income = Random.new.normal_rand(**MU_SIGMA) @fashion = Random.new.normal_rand(**MU_SIGMA) @expectation = expectation end def nomal? height >= @expectation && face >= @expectation && brain >= @expectation && personality >= @expectation && income >= @expectation && fashion >= @expectation end end
- initialize内ではRandomクラス(後述)によって、単純な乱数から正規分布に従う確率変数を発生させ、偏差値を付与しています。あと期待する偏差値をインスタンス変数として生成しています。
↑良い感じのライブラリがあればよかったんですが、見つからなかったのでこのような手法をとっています。
- normal?メソッドでは、全てのステータスが期待する偏差値(expectation)以上かどうかの判定をしています
↑ちなみに
mu
は母集団の平均値、sigma
は標準偏差であり、偏差値の定義上平均が50、標準偏差を10にしております続いて実際に計算するプログラムです(以下)
calc_expectation.rbequire './person' SAMPLE_NUMBER = 10_000 def main expectation = 50 hit_count = 0 probability = calc_probability(SAMPLE_NUMBER, expectation) while probability < 50 do puts "確率が#{probability}%なので再計算します(偏差値: #{expectation})" expectation -= 1 probability = calc_probability(SAMPLE_NUMBER, expectation) end puts '計算が完了しました' puts "期待する偏差値が #{expectation}以上であれば、#{probability}%の確率で存在します" end def calc_probability(sample_number, expectation) hit_count = 0 sample_number.times do hit_count += 1 if Person.new(expectation).nomal? end (hit_count.to_f / sample_number.to_f * 100).round(4) end main概要にも書いたとおり、試行回数を1万回として、期待する偏差値の人が存在する確率を求め、50%以下であれば期待値を1下げて再度確率を求めています
いずれ存在確率が50%以上になったところで計算をやめるようにしています
補足的に、正規分布を発生させるクラスを載せておきます(以下)
rand.rbclass Random include Math # ボックス―ミューラー法による正規分布乱数発生 def normal_rand(mu: 0, sigma: 1.0) a, b = self.rand(), self.rand() (sqrt(-2 * log(a)) * sin(2 * PI * b) * sigma) + mu end endボックス―ミューラー法なるもので、正規分布に従う乱数を作っています
以下Wikipedia参照
ボックス=ミュラー法(ボックス=ミュラーほう、英: Box–Muller's method)とは、一様分布に従う確率変数から標準正規分布に従う確率変数を生成させる手法。計算機シミュレーションにおいて、正規分布に従う擬似乱数の発生に応用される。統計学者ジョージ・ボックス(英語版)とマーヴィン・マラー(ミュラー)によって考案された。
実行結果
スクリプトを実行すると以下の結果が得られました
$ ruby calc_expectation.rb 確率が1.65%なので再計算します(偏差値: 50) 確率が2.52%なので再計算します(偏差値: 49) 確率が3.88%なので再計算します(偏差値: 48) 確率が5.64%なので再計算します(偏差値: 47) 確率が7.52%なので再計算します(偏差値: 46) 確率が11.28%なので再計算します(偏差値: 45) 確率が14.9%なので再計算します(偏差値: 44) 確率が19.08%なので再計算します(偏差値: 43) 確率が23.47%なので再計算します(偏差値: 42) 確率が29.69%なので再計算します(偏差値: 41) 確率が35.24%なので再計算します(偏差値: 40) 確率が41.68%なので再計算します(偏差値: 39) 確率が48.16%なので再計算します(偏差値: 38) 計算が完了しました 期待する偏差値が 37以上であれば、53.84%の確率で存在します
50%くらいとなると偏差値37~38あたりという結果となりました
40%でも偏差値39ぐらいですね?つまりステータスが6つの場合であれば、期待する偏差値は37〜40ぐらいになりましょう
まとめ
ふつうの人という存在がいかに稀有であるかお分かりいただけたでしょうか?
今回はステータスが6つを仮定しましたが、今回想定していないステータス(例えば体型や趣味・嗜好など)を追加すればするだけ、存在確率は天文学的な確率に近づいていきます?
とはいえ頭が良ければ年収が高くなるなど、お互い相関する部分もあるので、実際にはもう少しマシな確率にはなると思いますが・・・
普通の人はたくさんいるだろうという夢から覚めて、現実を見つめる一助となれば幸いです
(Rubyの学習にも一役買ってくれると幸いです)
参考
- 投稿日:2021-02-28T17:14:19+09:00
2重ハッシュ
user_data = [ {user: {profile: {name: 'Choco'}}}, {user: {profile: {name: 'Ramune'}}}, {user: {profile: {name: 'Sakura'}}}, ]ここからeachメソッドを使って全てのユーザーの名前を出力したいと思います。
ハッシュから特定の値を取得する場合はその値に対応するキーを指定します。
ハッシュ[取得したい値のキー]2重ハッシュから特定の値を取得する場合は、取得したい値のキーまでを連続して指定します。
ハッシュ[取得したい値のキー][取得したい値のキー]冒頭の記述では配列の中にハッシュが格納されています。
ハッシュの1つ1つを取り出すためにeach文を用いて記述します。user_data.each do |x| puts x[:user][:profile][:name] endブロック変数をxとしました。
Rubyファイルの記述をまとめるとこのようになります。user_data = [ {user: {profile: {name: 'Choco'}}}, {user: {profile: {name: 'Ramune'}}}, {user: {profile: {name: 'Sakura'}}}, ] user_data.each do |x| puts x[:user][:profile][:name] endターミナルでファイルを実行すると、順番にブロック変数xに代入されていき、全てのユーザーの名前が出力されます。
Choco Ramune Sakura補足
※digメソッドを使って取り出す方法もあります。その場合は以下のような記述になります。
user_data.each{ |x| puts x.dig(:user, :profile, :name) }
- 投稿日:2021-02-28T17:01:03+09:00
renderにおけるlocalsとcollectionについて
localsとcollectionのオプションについての理解を深めようとこの記事を書くことにしました。
1.localsについて
仮にposts_controllersに以下の記述があるとして
posts_controllers.rbdef show @post = Post.find(params[:id) endposts/foobar.html.erb<%= render partial: 'post_partial', locals: { post: @post } %> または省略形で <%= rendner 'post_partial', post: @post %>posts/_post_partila.html.erb<%= post.title%> <%= post.body %>公式(省略形) <%= render 'パーシャル名', ローカル変数: インスタンス変数名 %>つまりlocalsオプションを使用することで
@postというインスタンス変数をpostというローカル変数に変換することができる。2.collectionについて
仮にposts_controllersに以下の記述があるとして
posts_controllers.rbdef index @posts = Post.all endposts/index.html.erb<%= render partial: 'each_post', collection: @posts %> 応用形 asオプションでローカル変数を指定することができる <%= render partial: 'each_post', collection: @posts, as: :post%>collectionオプションを使用しなかった場合は以下の記述になるが
posts/_each_post.html.erb#collectionを使わなければ <% @posts.each do |post| %> <%= post.body%> <% end %>collectionオプションを使用するで
eachメソッドを省くことができるため簡潔に記述することができるposts/_each_post.html.erb#collectionを使用することで <%= post.body%>
- 投稿日:2021-02-28T17:00:44+09:00
文字列のなかで変数を
html.erb形式にて、
文字列のなかに変数を含めたい例えばpost変数の作成日を書くとき、
<%= "作成日:#{post.create_at}" %>
初心者にとってはこれでもすごい
- 投稿日:2021-02-28T17:00:44+09:00
文字列のなかで変数を使いたい
html.erb形式にて、
文字列のなかに変数を含めたい例えばpost変数の作成日を書くとき、
<%= "作成日:#{post.create_at}" %>
初心者にとってはこれでもすごい
- 投稿日:2021-02-28T15:55:30+09:00
Railsでリンクを押すとなぜかcssが適用されてしまう??
概要
現在Railsでアプリを作成しているのですが、
Vue.jsを導入してから、リンクを押すとcssのスタイルが適用されてしまうバグが起きるようになりました。試したこと
HTML,CSS,Vue.jsを少しずつ削って、どこが原因か探る作業を行いました。
(めちゃくちゃ時間かかった、、、)結局解決できず。
解決策
application.jsのTurbolinksを無効化することで解決しました。
application.js// This file is automatically compiled by Webpack, along with any other files // present in this directory. You're encouraged to place your actual application logic in // a relevant structure within app/javascript and only use these pack files to reference // that code so it'll be compiled. import Rails from "@rails/ujs" import Turbolinks from "turbolinks" import * as ActiveStorage from "@rails/activestorage" import "channels" import "bootstrap/dist/js/bootstrap" Rails.start() // ↓Turbolinksを無効化 // Turbolinks.start() ActiveStorage.start() require("../stylesheets/application.scss")参考文献の方のように、自分も「turbolinks」と仲良くならないとなと実感しました。
参考文献
- 投稿日:2021-02-28T15:46:43+09:00
Boolean型からString型にする方法
- 投稿日:2021-02-28T15:38:41+09:00
Railsのdeviseを使用して複数のログイン画面を実装する方法
deviseとは
Railsのgem(ライブラリ)の1つ。
ログイン機能の実装を簡単にしてくれるgemです。
これからdeviseを使用して複数のログイン画面を実装していきます。インストール・準備
Gemfileに追記
Gemfilegem 'devise'bundleまたはbundle install実行
$ bundle installdeviseを使用できるようにインストールします。
$ rails g devise:install上記のコマンドを実行すると、ターミナルに下記の文字が表示されます。
=============================================================================== Depending on your application's configuration some manual setup may be required: 1. Ensure you have defined default url options in your environments files. Here is an example of default_url_options appropriate for a development environment in config/environments/development.rb: config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } In production, :host should be set to the actual host of your application. * Required for all applications. * 2. Ensure you have defined root_url to *something* in your config/routes.rb. For example: root to: "home#index" * Not required for API-only Applications * 3. Ensure you have flash messages in app/views/layouts/application.html.erb. For example: <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> * Not required for API-only Applications * 4. You can copy Devise views (for customization) to your app by running: rails g devise:views * Not required * ===============================================================================では1から順に見ていきましょう!
config/environments/development.rbのendの上に記述してください。config/environments/development.rbconfig.action_mailer.default_url_options = { host: 'localhost', port: 3000 }続いて2です。ルーティングを指定しましょう。
config/routes.rbroot to: "home#index"続いて3です。こちらはログインした時にお知らせをしてくれます。
app/views/layouts/application.html.erb<p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p>ここで一つ注意なのですが、複数のログイン画面を実装するときは4は実行しないようにしましょう。
Modelを生成する
ここで2つのモデルを生成します。
モデルを生成するときは$ rails g devise モデル名
です。$ rails g devise A $ rails g devise Bdb/migrateに2つのファイルが生成されます。
設定を加えたい場合は今のうちに書き換えておきましょう。
そして$ rails db:migrate
をお忘れなく!Controllerを生成する
$ rails g devise:controllers As(複数形) $ rails g devise:controllers Bs(複数形)複数形にするのをお忘れなく!
設定ファイルを変更する
config/initializers/development.rbを開いて下記を見つけ出す。Macの方はコマンド⌘ + Fで簡単に探せますよ!
config/initializers/devise.rb# config.scoped_views = false上記のコメントアウトを外して、falseをtrueに書き換えます。
config/initializers/devise.rbconfig.scoped_views = trueこうすることで複数モデルを可能にするようです。
Viewを生成する
rails g devise:views As(複数形) rails g devise:views Bs(複数形)ルーティングを生成する
config/routes.rbを以下のように書き換えてください。
config/routes.rbRails.application.routes.draw do devise_for :B, controllers: { sessions: "Bs/sessions", passwords: "Bs/passwords", registrations: "Bs/registrations", } devise_for :As, controllers: { sessions: "As/sessions", passwords: "As/passwords", registrations: "As/registrations", } root to: "home#index" endその他
それぞれの新規登録画面・ログイン画面を編集したい場合は、
[Aの新規登録画面]
app/views/As/registrations/new.html.rb
[Aのログイン画面]
app/views/As/sessions/new.html.rb
[Bの新規登録画面]
app/views/Bs/registrations/new.html.rb
[Bのログイン画面]
app/views/Bs/sessions/new.html.rb
rails routes
でを見たらURLの指定もわかりやすいかと思います。rails sでサーバーを起動して以下のようにURLを打ち込んで確認してください。
[Aの新規登録画面]
http://localhost:3000/As/sign_up
[Aのログイン画面]
http://localhost:3000/As/sign_in
[Bの新規登録画面]
http://localhost:3000/Bs/sign_up
[Bのログイン画面]
http://localhost:3000/Bs/sign_in参照
https://qiita.com/4npei/items/9066afb75d6a2ad9c661
https://qiita.com/Densetsu/items/2dc6a010809ae70c079e
- 投稿日:2021-02-28T15:21:55+09:00
Ruby 基本 コメントについて
- 投稿日:2021-02-28T14:45:34+09:00
【Ruby】Hashをまとめてみた
Hashまとめ
PaizaでHashを使うことがあったので、整理がてらまとめました。
Hashとは
- みなさんお馴染みのKey,Value配列
- なんだかんだでよく使う。実務でも割と。
- 2次元配列が個人的には嫌いなので、Hashに逃げがち
- Hash使えたら、Rubyを「完全に理解した」レベル。チョットデキルには程遠い。
Hash作成
hash = {}要素の検索
Key検索
hash = { "Apple" => 1, "Orange" => 5 } print hash.find {|k,v| k == "Apple"} # { "Apple" => 1 }Value検索
- やり方は上と同じなので割愛。気が向いたら書く
要素の追加
hash = { "Apple" => 1, "Orange" => 5 } hash.store( "Grape" , 3 ) print hash # { "Apple" => 1, "Orange" => 5, "Grape" => 3 }要素の削除
hash = { "Apple" => 1, "Orange" => 5 } hash.delete("Apple") print hash # { "Orange" => 5}
- 投稿日:2021-02-28T14:45:34+09:00
【Ruby】Hashまとめ
Hashまとめ
PaizaでHashを使うことがあったので、整理がてらまとめました。
Hashとは
- みなさんお馴染みのKey,Value配列
- なんだかんだでよく使う。実務でも割と。
- 2次元配列が個人的には嫌いなので、Hashに逃げがち
- Hash使えたら、Rubyを「完全に理解した」レベル。チョットデキルには程遠い。
Hash作成
hash = {}要素の検索
Key検索
hash = { "Apple" => 1, "Orange" => 5 } print hash.find {|k,v| k == "Apple"} # { "Apple" => 1 }Value検索
- やり方は上と同じなので割愛。気が向いたら書く
要素の追加
hash = { "Apple" => 1, "Orange" => 5 } hash.store( "Grape" , 3 ) print hash # { "Apple" => 1, "Orange" => 5, "Grape" => 3 }要素の削除
hash = { "Apple" => 1, "Orange" => 5 } hash.delete("Apple") print hash # { "Orange" => 5}
- 投稿日:2021-02-28T14:44:17+09:00
heroku上にアプリケーションをアップする
herokuへアップする!
まず自身のherokuアカウントへログインします。
% heroku login --interactive
カレントディレクトリがアップするアプリケーション上であることを確認。
% heroku create アプリケーション名
% git config --list | grep heroku
上記のコマンドで正しく設定できていることを確認する
% heroku addons:add cleardb
MySQLを使うためにアドオンを追加します。
% heroku_cleardb=`heroku config:get CLEARDB_DATABASE_URL`
MySQLを使うためにGemに考慮した設定の変更を行います。
% heroku config:set DATABASE_URL=mysql2${heroku_cleardb:5}ClearDBデータベースのURLを変数heroku_cleardbに格納。
config/credentials.yml.encの中身を確認します。
% EDITOR="vi" bin/rails credentials:edit
確認後esc, :qで脱出できます。
環境変数をセットしていきます。環境変数
外部に漏らしたくない情報を環境変数にセットします。% heroku config:set RAILS_MASTER_KEY=`cat config/master.key`
上記の記述でRAILS_MASTER_KEYを設定。この時公開鍵や秘密鍵を扱う場合は一緒にセットしておきます。
% heroku config:set PAYJP_SECRET_KEY= 'sk_test_-----' % heroku config:set PAYJP_PUBLIC_KEY= 'pk_test_-----'
今回はpayjpを用いた開発だったので環境変数上にセットします。
% heroku config
上記で環境変数が正しく反映されているかを確認します。
アプリケーション情報をプッシュする
% git push heroku master
上記でherokuにアプリケーションを追加。
マイグレーションファイルを実行
この段階ではデータベースにはマイグレーションの情報が反映されていません。% heroku run rails db:migrate
ここまでで正しい情報になっているかを確認します。
% heroku apps:info
この時表示されるURLへアクセス!
変更をプッシュする
その後変更などを加える必要がある場合は以下の処理を行う% git add . % git commit -m "コミット名" % git push heroku master
処理を反映します。
stackの変更を加える必要がある場合
% heroku stack:set heroku-18 -a アプリケーション
今回の場合だとheroku-18に変更。
Stackとは、Herokuにおけるアプリケーションの動作環境のこと。Stackはデプロイされたアプリケーションを読み取り正常に稼働させるために用意されています。以上で無事herokuへのデプロイ完了しました。
- 投稿日:2021-02-28T14:28:47+09:00
「action_args」Gemから学ぶ「Ruby」③ ソース分析2日目
本日はparams_handler.rbのstrengthen_params!メソッド分析
「action_args」Gem分析2日目です。
strengthen_params!メソッドソースを見てみます〜
Railsのストロングパラメーターについて知らない方は事前に読んだ方がいいです。学習ポイント1
Object#instance_variable_defined?(var)
インスタンス変数varが定義されていたら真を返すObject#instance_variable_get(var)
オブジェクトのインスタンス変数の値を取得して返します。
インスタンス変数が定義されていなければnilを返しますstrengthen_params!permitting_model_name = self.class.instance_variable_defined?(:@permitting_model_name) && self.class.instance_variable_get(:@permitting_model_name)
self.class.instance_variable_get(:@permitting_model_name)
だけでもいい気がしているがなぜself.class.instance_variable_defined?
も条件に追加されているのか気になる。学習ポイント2
singularize
:複数形で書かれた英語表記の文字列を単数形に変換singularizeirb(main):009:0> "words".singularize => "word"
pluralize
:単数形で書かれた英語表記の文字列を複数形に変換pluralizeirb(main):010:0> "word".pluralize => "words"
underscore
:キャメルケース文字列をスネークケース文字列に変更underscoreirb(main):015:0> "ApplicationController".underscore => "application_controller"tr(pattern, replace): pattern文字列に含まれる文字を検索し、それを replace文字列の対応する文字に置き換えます。
trirb(main):019:1* "applications_controller/test".tr('/','_') => "applications_controller_test"strengthen_params!target_model_name = (permitting_model_name || self.class.name.sub(/.+::/, '').sub(/Controller$/, '')).singularize.underscore.tr('/', '_').to_sym
Controller名
からController
文字列を削除してキャメルケースをアンダースコアに変更したらモデル名になる。学習ポイント3
%i
: 要素がシンボルの配列を作るirb(main):001:0> %i[req keyreq] => [:req, :keyreq]require, permitについてはこちら
tryメソッド
:オブジェクトがnilでない場合のみ、そのオブジェクトのメソッドを実行したい時に使うメソッドtryメソッドirb(main):005:0> user => #<User id: 1, uuid: nil, name: "tester", created_at: "2021-02-28 03:57:31.626363000 +0000", updated_at: "2021-02-28 03:57:31.626363000 +0000"> irb(main):006:0> user.try(:name) || 'なし' => "tester"strengthen_params!method_parameters.each do |type, key| trimmed_key = key.to_s.sub(/_params\z/, '').to_sym if (trimmed_key == target_model_name) && permitted_attributes # ストロングパラメータの場合 # メソッドのパラメーターが必須の引数・必須のキーワード引数 params.require(trimmed_key) if %i[req keyreq].include?(type) # paramsハッシュで宣言されたモデル属性を許可してる params[trimmed_key] = params[trimmed_key].try :permit, *permitted_attributes if params.key? trimmed_key end endテストコード
学習ポイント4
params生成方法
@params = ActionController::Parameters.new(x: '1', y: '2', foo: {a: 'a', b: 'b'}, bar: {a: 'a', b: 'b'}, baz: {a: 'a', b: 'b'}, hoge: {a: 'a', b: 'b'}, fuga: {a: 'a', b: 'b'}, foo_foo: {a: 'a', b: 'b'}, hoge_hoge: {a: 'a', b: 'b'}, fuga_fuga: {a: 'a', b: 'b'})Class.new: 新しく名前の付いていない superclass のサブクラスを生成
test_case# params生成 setup do @params = ActionController::Parameters.new(x: '1', y: '2', foo: {a: 'a', b: 'b'}, bar: {a: 'a', b: 'b'}, baz: {a: 'a', b: 'b'}, hoge: {a: 'a', b: 'b'}, fuga: {a: 'a', b: 'b'}, foo_foo: {a: 'a', b: 'b'}, hoge_hoge: {a: 'a', b: 'b'}, fuga_fuga: {a: 'a', b: 'b'}) end # strengthen_params!を実行するメソッド def execute_strengthen_params!(controller) c = controller.new c.instance_variable_set :@_params, @params #メソッド名パラメータに:aを渡してParamsのRequire,Permit処理 c.strengthen_params! :a end test 'requiring via :req, permitting all scalars' do execute_strengthen_params! FooController ||= Class.new(ApplicationController) { permits :a, :b; def a(foo) end } # params[:foo] => {a: 'a', b: 'b'} assert @params[:foo].permitted? assert_not_nil @params[:foo][:a] # 'a' assert_not_nil @params[:foo][:b] # 'b' end
- 投稿日:2021-02-28T12:53:28+09:00
ポートフォリオ要件定義
ポートフォリオ事前レビュー
【テーマ】
働く上で発生する様々な悩みを解決する。【ターゲット】
悩みをもつ働く人々【サービス内容】
・悩みを投稿して、それに対してコメント(解決方法)をいただき、悩みを解決することができる。
・過去に同じような悩みを経験した人や、同じような悩みを解決した人に対して、個別相談することができる。
・悩み検索によって、過去の悩みから自分が抱えている悩みと似通った悩みを探すことができる。
・悩みへの解決方法が浮かばず、ユーザーの力になってあげることができなくても、悩みを応援することで、「よく応援されている悩み一覧」へ表示され、他のユーザーの目にとまりやすくなり、悩み解決率を上げることができる。【テーマ背景】
私は現在、金融及び保険の営業をしています。しかし、先日、右膝の古傷が悪化したことで歩くことが難しくなり、営業活動が長期間できないという状態です。そんな時に色々と悩みが出てきました。
①怪我した状態で出勤してよいのか?
②出勤しない場合、どういった休暇扱いになるのか?
③補助金のような援助はでるのか?
④有給を使い切ってしまった場合はどうなるのか?
⑤結局どのように活動するのが、会社と自分にとって一番よいのか?
もちろん会社の人たちにも相談はしましたが、私のように仕事が長期間できなくなるという経験した方はいないので、解決方法を見出すことはできませんでした。
このような時に、自分の会社内の方だけではなく、会社外の方からも意見を頂戴することができれば、一番ベストな解決方法にたどり着くことができるのでは?と思いました。
その他にも、転職を考えている方であれば、具体的な退職手続きや退職前後の流れなど、社内の方には相談しにくいことが多々出てくると思います。そんなとき、自社とは全く関係のない社外の方であれば、気軽に相談することができると思います。
まとめると、悩みを解決する時に、情報収集の一つとしてご活用いただけるようなサービスになればと思い、今回「働く上で発生する様々な悩みを解決する。」というテーマに決定いたしました。
また、「悩み 社会人」とGoogleで検索したとき、転職サービスを運営している企業が作成したまとめサイトのようなものしかなく、生のユーザーの声をそのまま使ったサイトはあまり見られませんでした。なので、生のユーザーの声を大切にしたサービスにしたいと強く思っています。【機能一覧】
《基本機能》
・ユーザー新規登録/ログイン/ログアウト(devise)
・ユーザープロフィール登録/編集/詳細機能(名前/プロフィール文)
・プロフィール画像アップロード機能(carrierwave)
・悩み新規投稿/編集/削除/詳細機能
・悩みへのタグ付け機能
・この悩み応援します機能(いいね)
・よく応援されている悩み順に一覧表示
・悩みを新着順に一覧表示
・悩みへのコメント機能
・個別相談機能(非同期通信)
・悩みキーワード検索機能(ransack)
・悩みをタグから検索できる機能(ransack)《応用機能》
・かんたんログイン
・悩み一覧にページネーションを使う
・レスポンシブ対応
・通知機能《その他》
・単体テスト
・結合テスト【使用技術一覧】
《フロントエンド》
・HTML/CSS
・JavaScript
・Bootstrap(5.0)(カスタマイズして使用する)《バックエンド》
・Ruby(3.0.0)
・Ruby on Rails(6.0.3.1)
・MySQL(8.0)《インフラ》
・heroku(開発初期)
・AWS(VPC/EC2/S3/RDS)
・Nginx(Webサーバー)
・Puma(アプリケーションサーバー)《テスト》
・RSpec《CI/CD》
・CircleCI(自動テスト)
・Capistrano(自動デプロイ)
・Rubocop(コーディングチェック)《バージョン管理》
・Git/GitHub《開発環境》
・VScode
・Docker【開発フェーズ】
《第一段階》
・基本機能実装
・テストの作成
・UI/UXのブラッシュアップ
・コーディングチェック
・herokuへのデプロイ《第二段階》
・応用機能実装
・UI/UXのブラッシュアップ
・コーディングチェック《第三段階》
・インフラをherokuからAWSに変更(VPC/EC2/S3/RDS)
・Docker/docker-composeの導入
・CI/CDの導入《第四段階》
・EC2からECSに変更
- 投稿日:2021-02-28T12:26:02+09:00
ActiveRecordまとめメモ
はじめに
最近Railsの独学をはじめたので備忘録として記事にしていきます。普段は業務でphpを使っていて、データのやりとりにはSQL文を書いてるんですが、SQLを書かずに簡単にデータ操作ができる「ActiveRecord」に感動しました!!その感動が伝わるように記事を書いていきたいと思います。アドバイスなどがあればコメントお願いします。
ActiveRecordとは?
結論から言うとActiveRecordとは、「DB操作を行うSQLを使わず、Rubyでデータ操作を可能にする仕組み」です。例えば、Userテーブルからidが1の顧客を取得する場合、SQLでは
「SELECT * FROM users WHERE id = 1」
と長いコードを書かなければいけないんですが、ActiveRecordであれば
「User.find(1)」
と書けばID=1のユーザー情報を簡単に取得することができます。
ActiveRecordを使用するメリット
■短いコードで直感的に書くことができる
上記の例のように、ActiveRecordのメソッドを使えば簡単にDB操作を行うことができ、僕みたいな駆け出しエンジニアや初学者の方の心理的なハードルは下がると思います。まずはActiveRecordを使えばこういうことができるというのを経験的に学んで、そこから深く掘り下げてSQLなどを学んでいくと理解が深まると思うのでおすすめです。
よく使うメソッド
作成系(Create)
■newメソッド
インスタンスの生成を行う。newメソッドは新しいオブジェクトを作成するだけで、データベースへの保存はできない。
# インスタンスの生成 user = User.new user.name = "yamada" user.email = "example@mail.co.jp"■saveメソッド
上記のnewメソッドでインスタンスを作成し、代入した値をデータベースに保存するのがsaveメソッド。
保存に成功すればtrue、失敗すればfalseを返す。# 作成したオブジェクトの保存 user.save■createメソッド
インスタンスの生成とデータベースの保存を行うメソッド。newメソッドとsaveメソッドが行なっている処理を一括で行う。Userモデルにnameとemail属性があればデータベースに新しいレコードを作成する。
# インスタンスの生成 + オブジェクトの保存 user = User.create(name: "yamada", email: "example@mail.co.jp")取得系(Read)
■allメソッド
指定したモデルの全てのオブジェクトを取得する。
# ユーザーモデルの全てのレコードを取得 users = User.all■findメソッド
指定したidから一件のレコードを取得する。
# ユーザーモデルからidが1のレコードを取得 user = User.find(1)■find_byメソッド
指定した属性、値の最初のレコードを一件取得する。
# ユーザーモデルからname属性が山田のレコードの最初の一件を取得 user = User.find_by(name: "yamada")■firstメソッド
指定したモデルの最初のレコードを一件取得する。
# ユーザーモデルの最初のレコードを取得 user = User.first■whereメソッド
指定した属性、値に一致するレコードを全て取得する。先ほどのfind_byメソッドは一致するレコードを一件取得するが、whereメソッドは全て取得する。
# ユーザーモデルのname属性で値が山田のレコードを全て取得 users = User.where(name: "yamada")更新系(Update)
■updateメソッド
指定したレコードの値を変更する。
# idが1のレコードのname属性を田中に変更する user = User.find(1) user.update(name: "tanaka")下記のコードと上記のコードは同じ意味。
user = User.find(1) user.name = 'tanaka' user.save■update_all
指定した属性のレコードを全て更新する。一回のSQLで全て更新できるので一括で値を更新する場合に便利。
# ユーザーモデルの性別属性を全て男に更新 user.update_all(sex: "male")削除系(Delete)
■destroyメソッド
指定したレコードを削除する。
# idが1のレコードを削除 user = User.find(1) user.destroy■destroy_byメソッド
指定した属性、値と一致するレコードを全て削除する。
# name属性の値が山田のレコードを全て削除 User.destroy_by(name: "yamada")■destroy_all
指定したモデルの全てのレコードを削除する。
# ユーザーモデルのレコードを全て削除 User.destroy_all参考記事
- 投稿日:2021-02-28T12:00:21+09:00
Ruby on Railsの環境構築
私の今現在の環境の構築方法を忘れないためのメモです。
参考記事
- MacOSでCommand line tools for XcodeとHomebrewのインストール
- 【完全版】MacでRails環境構築する手順の全て
- Ruby初学者のRuby On Rails 環境構築【Mac】
ありがとうございます!
バージョン
Mac OS Catalina 10.15.17
MojaveやM1だと違う可能性があるのでご注意ください。
準備
Catalinaではzshというシェルを利用するので以下コマンドをターミナルで実行し、zshをデフォルトに設定します。
パスワードを求められる場合はPCのパスワードを入力します。% chsh -s /bin/zsh以下のコマンドでログインシェルを確認します。
% echo $SHELL # 以下のように表示されればOK /bin/zshCommand Line Toolsをインストール
開発に必要なもろもろのソフトウェアをダウンロードするためには
Command Line Tools
が必要なためインストールしていきます。ターミナルに以下コマンドを入力します。
% xcode-select --install下記画像のような画面になるので
インストール
を選択します。下記画像のような画面になるので
同意する
を選択します。ちょっと時間かかりますので待ちます。
Homebrewのインストール
ソフトウェア管理ツールであるHomebrewをインストールします。
以下の公式サイトの
インストール
の下のスクリプトをコピーし貼り付けします。
Homebrew私の場合は以下です。
# ホームディレクトリで行います % /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"パスワードを求められたり、注意書きが出たりします。
Press RETURN to continue or any other key to abort
と出たら続けるにはエンターキーを、やめるにはそれ以外の入力を
という意味なのでエンターキーを押下します。以下コマンドでインストールできたか確認できます。
% brew -v # 以下のようになればOK(数字は違う可能性があります) Homebrew 2.5.1以下コマンドで最新バージョンにします。
% brew update以下コマンドで権限を変更します。
% sudo chown -R `whoami`:admin /usr/local/binパスワードを求められるのでPCのパスワードを入力します。
Rubyをインストール
Rubyをインストールしていきます。
このためにHomebrewが必要でした。以下のコマンドでRubyの土台となる
rbenv
とruby-build
をHomebrewを用いてインストールします。% brew install rbenv ruby-build以下のコマンドでPCのどこからでも
rbenv
を利用できるようにします。% echo 'eval "$(rbenv init -)"' >> ~/.zshrc以下のコマンドでzshrcを再読み込みし変更を反映させます。
% source ~/.zshrc以下のコマンドでターミナルのirb上で日本語入力を可能にする設定を行います。readlineをインストールします。
% brew install readline以下のコマンドでreadlineをPCのどこからでも利用できるようにします。
% brew link readline --force以下のコマンドでrbenvを利用してRubyをインストールします。
今回は2.6.5
のバージョンです。% RUBY_CONFIGURE_OPTS="--with-readline-dir=$(brew --prefix readline)" # バージョンを指定しインストール % rbenv install 2.6.5 # インストールしたRuby 2.6.5を使用するために以下コマンドを実行 % rbenv global 2.6.5 # 以下コマンドでrbenvを読み込む % rbenv rehash # 以下コマンドでバージョンの確認ができる % ruby -vMySQLのインストール
以下のコマンドを実行して、MySQLをインストールします。
% brew install mysql@5.6以下のコマンドで自動で起動するように設定します。
% mkdir ~/Library/LaunchAgents % ln -sfv /usr/local/opt/mysql\@5.6/*.plist ~/Library/LaunchAgents % launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql\@5.6.plist以下のコマンドでPCのどこからでもMySQLが使えるようにします。
# mysqlのコマンドを実行できるようにする設定 % echo 'export PATH="/usr/local/opt/mysql@5.6/bin:$PATH"' >> ~/.zshrc # 設定を読み込むコマンド % source ~/.zshrc # mysqlのコマンドが打てるか確認する % which mysql # 以下のように表示されればOK /usr/local/opt/mysql@5.6/bin/mysql # MySQLの状態を確認するコマンド % mysql.server status # 以下のように表示されればOK SUCCESS! MySQL runningRailsのインストール
以下コマンドでgemを管理するためのbundlerバンドラーをインストールします。
% gem install bundler --version='2.1.4'以下コマンドでRailsをインストールします。
% gem install rails --version='6.0.0' # rbenvの再読み込みをして設定を反映させる % rbenv rehash # バージョン確認 % rails -v # 以下のように表示されればOK Rails 6.0.0Node.jsのインストール
RailsでJavaScriptを動かすために必要なNode.jsをインストールします。
以下コマンドを実行します。% brew install node@14 # パスを設定する % echo 'export PATH="/usr/local/opt/node@14/bin:$PATH"' >> ~/.zshrc % source ~/.zshrc # バージョンを確認 % node -v #以下のように表示されればOK v14.15.3yarnをインストール
yarnについてよくわかっていなかったのですが、以下の記事がわかりやすかったです。
ありがとうございます!
npmとはyarnとは以下コマンドを実行します。
% brew install yarn # バージョンを確認 % yarn -v以上です。
- 投稿日:2021-02-28T11:47:38+09:00
【Ruby】【paiza】繰り返し処理
- 投稿日:2021-02-28T11:32:53+09:00
Rails I18nを便利に使おう
アプリケーションを色々な国に展開する場合やメッセージを日本語化する際にI18nを使用すると思います。
下記のようなパターンでは
user_name
をtranslateに渡すと、"太郎"
が返ってきます。config/locales/ja.ymlja: user_name: "太郎"> I18n.t(:user_name) => "太郎"しかし、
user
が、太郎
だけであればこれでも良いのですが、複数いる場合がたいていのパターンだと思います。
これを少し拡張させて、どのuserでも対応できるようにしていきます。config/locales/ja.ymlja: user_name: "%{name}"> I18n.t(:user_name, name: "太郎") => "太郎"> I18n.t(:user_name, name: "次郎") => "次郎"上記のように変更すると、引数に名前を渡せば、どんな名前でも表示できるようになりました。
これで使いやすくなりました。さらにtranslateではこのようなこともできます。
config/locales/ja.ymlja: user_name_html: <span class="user">"%{name}"</span>このように最後に
_html
をつけることで、htmlごと(今回はspanタグごと)返すこともできます。
view自体が複雑でごちゃごちゃしている場合,こうゆうパターンで書くのも一つの手かもしれません。translateは調べるといろんなことができるので、色々試してやってみましょう!!
案外今やりたいことと合致するかもしれません参考記事