20200729のRailsに関する記事は12件です。

【Rails】i18nによる日本語化

はじめに

  • Railsのデフォルト言語の日本語化(2パターン)
  • 多言語のymlファイルを導入(2パターン)
  • config/localesで階層的に多言語ファイルの管理

  • 筆者のスペック
    • Rails学習歴:4ヶ月
  • 条件
    • Rails 6.0.3.2
    • Ruby 2.6.6

そのため間違いなどがある可能性があるので鵜呑み厳禁!

Railsのデフォルト言語の日本語化(2パターン)

どちらか片方の設定で日本語の言語設定は完了します。

1. config/application.rbに設定情報を追加

  • config/application.rbconfig.i18n.default_locale = :jaを記入することで日本語を利用できます。
  • :jaの部分を他をローケルキーに変えることで他の言語に設定することもできます。
config/application.rb
module App
  class Application < Rails::Application
...
    config.i18n.default_locale = :ja
...
  end
end

2.config/initializers/locale.rbに設定情報を追加

  • config/initializers/locale.rbRails.application.config.i18n.default_locale = :jaを記入することで日本語を利用できます。
config/initializers/locale.rb
Rails.application.config.i18n.default_locale = :ja

結局どちらの方法で設定するべきなのか

結果どちらでもいい
まずRailsの実行の順序としconfig/application.rbが先に実行されて、その後にconfig/initializersが実行されます。
もっと具体的に言うとconfig/initializers以下は全てのフレームワークとgemが読み込まれた後に実行されます。
そのため完璧を期すために、何らかの理由でapplication.rbファイルを使用したくない場合には後者を使った方がいいということですね。

参考文献
Railsの設定 Ruby STUDIO
Railsの多言語対応 Ruby STUDIO

多言語の言語ファイルを導入(**.yml)(2パターン)

1.Gemの導入(Rails-i18n 等)

Rails-i18nをGemfileに追加してbundle(※bundle installの省略形)でOKです。
Gemで導入するとファイルが圧迫しない&手軽に数十種類の言語を導入できるのでオススメです。

Gemfile
 gem 'rails-i18n'
ターミナル
$ bundle install

2.手動で言語ファイル(**.yml)をダウンロードしてくるor作成する

今回はGithubからRails-i18nのja.ymlをダウンロードしてくる。
※Github上からファイルを取ってくる際はRawボタンを押すと出てくるURLを使用する。

ターミナル
## wget 【ダウンロードしたいファイルのURL】 -P 【ダウンロードしたファイルを格納したい場所】
$ wget https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/ja.yml -P config/locales/default

参考文献
Rails-i18nの使用例(英語)
[初学者]Railsのi18nによる日本語化対応(Qiita)

config/localesで階層的に多言語ファイルの管理

  • config/application.rbconfig.i18n.load_pathの設定を行う。

デフォルトの設定だとI18n.load_path += Dir[Rails.root.join('config', 'locale', '*.{rb,yml}')]になっています。
この設定だとconfig/localesに存在する**.ymlファイルしか読み込みません。
そのためconfig/locales以下のすべてのディレクトリに入ってる**.ymlを読み込むようにします。

config/application.rb
module Myapp
  class Application < Rails::Application
...
    # 言語ファイルを階層ごとに設定するための記述
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s]
...
  end
end

設定が完了すると、下記のディレクトリ構造を読み込むことができるようになります。

config/locales
|-00_defaults
|---es.rb
|---ja.rb
|-01_models
|---book
|-----es.rb
|-----ja.rb
|-99_views
|---defaults
|-----es.rb
|-----ja.rb

参考文献
Rails 国際化 (i18n) API Railsガイド

補足

引用:Railsで日本語サービスを作るときのテンプレート

各言語用ymlファイルは、01_modelsというように数値のprefixをつけたディレクトリに入れ、以下の様な構成にする。

  • config/locales/00_defaults/ja.yml
  • config/locales/01_models/ja.yml
  • config/locales/02_views/ja.yml

YAMLは同じキーがあった場合は内容を上書きするので、00などをつけて順番を選べるようにしておくと都合が良い。
辞書順に上から読み込まれて行くので、内容がコンフリクト(競合)した場合は数値が大きいほうの設定が使われる様になる。

参考するべき文献

特定のviewファイル専用の訳文を簡単に参照する
Ruby on RailsのI18nで使用する名前空間に関してのまとめと、ベストプラクティスの検討。

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

RailsプロジェクトのRubyバージョンを変更する

はじめに

Railsの既に作成済みのプロジェクトのRubyバージョンが誤っており、Rubyを再度インストールしたが途中エラーが発生したので、備忘録として残しておきます。

今回は、プロジェクトのバージョンを「2.6.3」→「2.5.3」にバージョン変更しました。
もし「間違っている」とか「もっと簡単にできる」とかあれば、ご指摘いただけますと助かります。:bow_tone1:

環境

  • macOS Catalina 10.15.6(19G73)
  • Rails 5.2.4.3
  • Ruby 2.6.3 (※変更前)
  • Ruby 2.5.3 (※変更後)

Rubyのバージョンを確認する

$ ruby -v
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]

バージョンが2.6.3であることを確認。

Rubyをインストールする

$ rvm install 2.5.3

インストールが完了するまで待ちます。

RVMのRubyバージョンを設定

rvm --default use 2.5.3
Using /home/ec2-user/.rvm/gems/ruby-2.5.3

RVMのデフォルトバージョンを2.5.3に変更しておきます。

Railsサーバーを立ち上げてみる

$ rails s
Your Ruby version is 2.5.3, but your Gemfile specified 2.6.3

どうやら、「Rubyのバージョンは2.5.3やのにGemfileは2.6.3やぞ?」と言うてるみたいですね。
Gemfileのバージョンを合わせます。

Gemfileを修正

Gemfile
 source 'https://rubygems.org'
 -ruby '2.6.3'
 +ruby '2.5.3'

ファイル上部のRubyバージョンを書き換え。

bundle installする

$ bundle install

無事にインストールが完了すれば、再度動作確認をします。
「Rails s」」でサーバーが立ち上がればOK。

ちなみにダメな場合「Rails」と付くコマンドは全部アウトです。

最後に

思ったよりも簡単にバージョンを変更することができて、ちょっぴり驚き。
Railsのエラーは内容が分かりやすくて、ちょっと英語が分かる人ならだいたい解決できてしまうからスゴイ。

無事バージョンを変更できたので良かったですが、できれば初めからバージョンを確認してプロジェクトをスタートさせるに越したことはない笑
今後は気をつけていこう(戒め

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

【備忘録】add_indexでrollbackエラー

現象

データベースのrollbackをしようとしたら、下記のエラーが発生。

実行処理
rails db:rollback 
エラー
== 20200726224558 DeviseCreateUsers: reverting ================================
-- remove_index(:users, {:column=>:reset_password_token})
rails aborted!
StandardError: An error has occurred, all later migrations canceled:

解決方法

db/migrate/devise_create_users.rbにある以下の表記をコメントアウトした。

変更前
    add_index :users, :name,                 unique: true
    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
変更後
    # add_index :users, :name,                 unique: true
    # add_index :users, :email,                unique: true
    # add_index :users, :reset_password_token, unique: true

結果

rollbackがエラーなく実行できた。

-- drop_table(:users)
   -> 0.0034s
== 20200726224558 DeviseCreateUsers: reverted (0.0071s) =======================
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

resourcesとresourceの違いについてまとめてみた

Railsで何らかのリソースに対するCRUD処理を行うためのルーティングを生成する方法として、resourcesメソッドとresourceメソッドがあるので、今回はその違いについてまとめてみました。

resourcesとは

resourcesメソッドは、コントローラーの7つのアクション(index、show、new、create、edit、update、destroy)をひとまとめにしたメソッドで、複数のリソースに対するCRUD処理を行うためのルーティングを生成します。

config/routes.rb
Rails.application.routes.draw do
 resources :games
end

#リソース名が複数形

上記のように記載すると、7つのアクション(index、show、new、create、edit、update、destroy)全てを設定したことと同じになります。
確認のため、ターミナルにてrails routesコマンドを入力してみると、以下のルーティングが生成されています。

ターミナル
   Prefix Verb   URI Pattern               Controller#Action
    games GET    /games(.:format)          games#index
          POST   /games(.:format)          games#create
 new_game GET    /games/new(.:format)      games#new
edit_game GET    /games/:id/edit(.:format) games#edit
     game GET    /games/:id(.:format)      games#show
          PATCH  /games/:id(.:format)      games#update
          PUT    /games/:id(.:format)      games#update
          DELETE /games/:id(.:format)      games#destroy

リソースが複数なので、/gamesに対するGETリクエストが返すのはリソースの一覧画面(indexアクション)であることが分かると思います。

resourceとは

resourceメソッドは、コントローラの7つのアクション(index、show、new、create、edit、update、destroy)に対して、indexとid付きのパスが生成されません。
resourceは、ただ1つのリソースに対するCRUD処理を行うためのルーティングを生成します。

config/routes.rb
Rails.application.routes.draw do
 resource :game
end

#リソース名が単数形

こちらも確認のため、ターミナルにてrails routesコマンドを入力してみると、以下のルーティングが生成されています。

ターミナル
   Prefix Verb   URI Pattern          Controller#Action
 new_game GET    /game/new(.:format)  games#new
edit_game GET    /game/edit(.:format) games#edit
     game GET    /game(.:format)      games#show
          PATCH  /game(.:format)      games#update
          PUT    /game(.:format)      games#update
          DELETE /game(.:format)      games#destroy
          POST   /game(.:format)      games#create

こちらの場合は、リソースは1つだけなのでurlに:idを含む必要がありません。そして、一覧画面(indexアクション)が必要ないので、/gameに対するGETリクエストはそのリソースの表示(showアクション)であることが分かると思います。

まとめ

「resourcesメソッド」はidが付与されているので、複数あるリソースの中からidを用いて特定のリソースを絞り込むことができます。

その一方で「resourceメソッド」にはidが付与されないので、リソースを絞り込まない状況で使用します。

まとめると、複数存在するリソース(商品やユーザーなど)では「resources」を使用し、1つしか存在しないリソースには「resouece」を使用します。

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

複数モデルにデータを保存したい

某メルカリのコピーサイトを作成中。
商品の画像登録にて、複数の画像登録となるとカラムが増えて美しくないので
別モデルでimageテーブルを作成することに

fields_for

form_for内で異なるモデルを編集できるようになる。

例:Productモデルに紐付くImageモデル

これを使うとform_withとかで別モデルに保存とかできるようになるっぽい
アソシエーションとかで紐づいてることが前提

Model

product(商品)とimageは1対多
accepts_nested_attributes_for で一緒に保存したいモデルを指定

product.rb
class Product < ApplicationRecord
  has_many :images
  accepts_nested_attributes_for :images
end



imageとproduct(商品)は多対一となってます
複数保存する場合は mount_uploaders と複数形にする必要があるので注意

image.rb
class Image < ApplicationRecord
  belongs_to :product
  mount_uploaders :image, ImageUploader
end

Controller

newアクションで build を使用することでfield_forが使用可能に

build

親モデルとアソシエーションを組んでいる子モデルのインスタンスを生成できるメソッド

みたいです。ちなみにhas_many(1対多)であれば

インスタンス変数.子モデル.build

で問題ありませんが、belongs_to や has_one では .build の表記では使えないらしく

親モデル.build_子モデル  例) @product.build_image

となるそうです

products.controller.rb
  def new
    @product = Product.new
    @product.images.build
  end

  def create
    @product = Product.create(product_params)
  end

  def product_params
    params.require(:product).permit(images_attributes: {image: []})
  end

またパラメーター内では
モデル名_attributes: と記述します

これも送るデータが一つか複数かで記述が変わり、一つの場合は

images_attributes: [:image]

こんな感じ

View

html.haml
    .Contents
      = form_with model: @product, html: {class: "Form"}, local: true do |f|
        .InputPhoto
          .InputPhoto__DropArea
            = f.fields_for :images do |c|
              = c.label :image
              = c.file_field :image, multiple: true

これでとりあえず画像の保存は完了!

次はjqueryか...


参考記事
https://qiita.com/kouuuki/items/5daf2b5f34273d8457f7
https://qiita.com/nakasato_minami/items/5015319292c9f8a93f34
https://qiita.com/mihou/items/2d7504c0bf98d07a95c3
ありがとうございました!!!

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

思わぬ事故防止!開発時やテスト時に使用するメアドのドメインは example.com に統一しよう

はじめに

Webアプリケーションの開発時やテスト時にはテスト用のユーザーを作成するために適当なメールアドレスとパスワードを登録することが多いと思います。

このとき、みなさんはこんなふうにデタラメなドメインをメアドに使ってないでしょうか?

hoge@hoge.com
test@testmail.com
aaaa@bbb.com
etc...

「こんなデタラメなドメイン、あるわけないやろ!」と思うかもしれませんが、自分はデタラメに付けたつもりでも意外とかなりの高確率でそのドメインは実在します。

実際、上の例で挙げたドメインをブラウザに入力すると、いずれも何かしらページが表示されます。
つまり、そのドメインは現在誰かが使っているということがわかります。

https://hoge.com/
Screen Shot 2020-07-29 at 15.15.59.png

http://testmail.com/
Screen Shot 2020-07-29 at 15.16.59.png

https://www.bbb.org (bbb.com から転送される)
Screen Shot 2020-07-29 at 15.16.39.png

実在するドメインだと何が困るの?

何らかの間違いでその実在するドメインに向けてメールが送信される可能性があります。
特に、ステージング環境などではSMTPの設定がバッチリ整っていて、実際にメールが送信されるリスクが高いかもしれません。

もちろん、メールが送信されても一致するユーザーがいないとそのまま破棄されるかもしれません。
ですが、送信先でどんな処理が行われているのかはこちらではわかりません。

最悪の場合、

  • パスワード変更用のURLが含まれるメールが意図しないドメインに送信される
  • そのメールを受け取った悪意ある第三者がパスワード変更画面経由でステージング環境に侵入する
  • ステージング環境に本番環境とほぼ同等のデータが入っていたため、間接的に情報漏えいインシデントに発展する

・・・みたいなことが起きるかもしれません。

開発環境やテストコード上だったらいいんじゃない?

ローカルマシン上の開発環境やテストコード上では実際にメール送信が行われる可能性は低いかもしれませんが、どんな状況下でも絶対にないとは言い切れません。
ですので、やはり「デタラメなドメインのメアド」を登録するのはなるべく避けた方が良いと思います。

というか、開発環境やテストコード上では事故を防ぐというよりもむしろ、「無意識にデタラメなドメインを付けてしまう」という悪いクセを無くす目的で、僕はコードレビュー時によく指摘しています。

そんなあなたのための example.com

では、どんなドメインを使えばいいのでしょうか?
こういうときにピッタリなのが example.com です。
example.com であれば万一誤送信してしまっても問題が起きません。

example.com, example.net, example.org, example.eduは、ソフトウェアドキュメンテーションやドメイン名の例示のために予約されているセカンドレベルドメインである。
(中略)
これらのドメイン名が予約されていることによって、マニュアルやソフトウェア構成のサンプルでこれらのドメインを使用することが可能である。すなわち、エンドユーザーがサンプルの設定や例示をそのまま使用してしまったとしても、第三者に悪影響が及ばないことが保障されている。

引用元 https://ja.wikipedia.org/wiki/Example.com

上の説明にあるように、example.com に加えて example.net や example.org 、example.edu 使うのもOKです。

というわけで、これからは「開発時に使うデタラメなメールアドレス」は次のように example.com (または example.net や example.org 、example.edu )を使いましょう。

hoge@example.com
test@example.com
aaaa@example.com

自社のドメインもOKかも

example.com 以外で誤送信しても大きな問題に発展しにくそうなのは自社のドメインでしょう。

ですので、「開発時のテストユーザーには example.com か自社のドメインを使う」というルールにしても良いかもしれません。

ただし、「自社のドメインが変わって、旧ドメインが別の第三者に取得された」とか「誤送信が多すぎて、自社ドメインのreputationが低下し、迷惑メールと判定されやすくなってしまった」みたいな問題は発生するかもしれないので、その点はくれぐれもご注意ください。

テストコードの修正例

以下はrspec-railsで書いたテストコードを修正する例です。
心当たりがある人はテストコードを修正しましょう!

 require 'rails_helper'

 RSpec.feature 'ログインとログアウト' do
   background do
     # ユーザを作成する
-    User.create!(email: 'foo@hoge.com', password: '123456')
+    User.create!(email: 'foo@example.com', password: '123456')
   end
   scenario 'ログインする' do
     # トップページを開く
     visit root_path
     # ログインフォームにEmailとパスワードを入力する
-    fill_in 'Email', with: 'foo@hoge.com'
+    fill_in 'Email', with: 'foo@example.com'
     fill_in 'Password', with: '123456'
     # ログインボタンをクリックする
     click_on 'ログイン'
     # ログインに成功したことを検証する
     expect(page).to have_content 'ログインしました'
   end
 end

他にもある例示/実験用ドメイン

(2020.7.30追記)

この記事では僕がふだんよく使っている example.com を取り上げましたが、.test など、予約済みの例示/実験用ドメインは他にもあります。

詳しくは以下のページを参考にしてみてください。

まとめ

@example.com で安全安心なシステム開発を!

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

Rails 5 cloud9で誤って作成したマイグレーションファイルを削除する方法

記事の趣旨 ※あくまで個人で開発されている方を対象としています

削除したマイグレーションファイルが生きている
編集してマイグレーションファイルを作成しなおした

対処

299b83e2ab2fec0c25f32edba537db10.png

どうしよう。。。。強行手段

1.$ rails db:migrate:status

a51f3909b9dfe0d66a0e5c910853ba46.png

1.モデルに作成されたファイルを削除しましょう。(例です)
 
(例)complete.rb  削除

2.不要なマイグレーションファイル削除

(例)20200729035325_create_complete.rb 削除

補足
削除はファイルを選択し削除してください

658fb17c679b9dcd39054c5d26cf884a.png

3.再度作り直したマイグレーションファイルを作成

(例)$ rails g model Complete user:references task:references

4.不要なファイルを削除しリセット

$ rails db:migrate:reset

補足 もしそれでもできなければ1~4の手順の後でデータベースをリセットし再度リセット

$ rails db:reset

$ rails db:migrate:reset

1ff2a9671ba84f19a7f238ce246b20d0.png

No-Fileは削除され必要なファイルが更新されました。

適切な方法は一度不要なファイルを落とし、確認した後に削除されることをお勧めします。

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

Effective Rubyを読んで勉強になったこと

はじめに

Effective Rubyを私が読んで勉強になったことを書いてます。

本書を読んだのは2回目ですが、1回目は何がどう役立つのか全くわかりませんでした。
2回目の今回もいまだに「これって一体どういった場面で効果的なの?」、「そもそも何いってんのこれ?」って部分は多数というかそっちの方が多い気もしますが、以前より「なるほど!」と思った部分があったので、「なんかコーディング力上がってない気がする」って悶々としている人は読んでみると発見があるかもしれません。

本全体の内容を紹介するものではなく
RoRを書いていて、「あ〜こう書けば良かったんだ!」と自分のアンテナに引っかかったところだけを書いていくので、本全体の内容を知りたい方は以下の記事など参照すると良いと思います。
https://qiita.com/fujigaki/items/9d64fa49efcbe7017d8c

勉強になったこと

項目2 オブジェクトを扱うときにはnilかもしれないことを忘れないようにしよう

undefined method 'XXXX' for nil:NilClass(NoMethodError)

以前は、RoRしか経験がなく特に気になってませんでしたが、Typescriptではじめて静的型付き言語を触ってから嫌いになったエラーの1つです。
上記のエラーが意図せず発生しないように、nilになる可能性をできる限り排除しましょうってことが大事で、すぐにできることとして

[4] pry(main)> nil.to_a
=> []
[5] pry(main)> nil.to_s
=> ""
[6] pry(main)> nil.to_i
=> 0

があげられます。
このように型付けがないのをカバーするためにto_aやto_sに代表される変換メソッドを入れておくことでnilが排除されるので、よりエラーが発生しにくいコードになるってことですね。

項目8 サブクラスを初期化するときはsuperを呼び出そう

[7] pry(main)> class Parent
[7] pry(main)*   attr_accessor(:name)  
[7] pry(main)*   def initialize  
[7] pry(main)*     @name = "サンプル太郎"    
[7] pry(main)*   end    
[7] pry(main)* end  
=> :initialize
[8] pry(main)> 
[9] pry(main)> class Child < Parent
[9] pry(main)*   attr_accessor(:age)   
[9] pry(main)*   def initialize  
[9] pry(main)*     @age = 14    
[9] pry(main)*   end    
[9] pry(main)* end  
=> :initialize
[10] pry(main)> 
[11] pry(main)> child  = Child.new
=> #<Child:0x00007fcf69ed6a08 @age=14>
[12] pry(main)> child.name
=> nil

上記のようにChildクラスにParentを継承していた時にChildをnewしてもParentのnameにはアクセスできないんですよね。
最近、これと全く同じことをしてなんでアクセスできない?って思って調べた結果superが必要だったと思い出しました。
「あーこれこの間ハマったやつや!」って思ったので改めて。

[13] pry(main)> class Child < Parent
[13] pry(main)*   attr_accessor(:age)   
[13] pry(main)*   def initialize  
[13] pry(main)*     super()    
[13] pry(main)*     @age = 14    
[13] pry(main)*   end    
[13] pry(main)* end  
=> :initialize
[14] pry(main)> Child.new
=> #<Child:0x00007fcf5cfda718 @age=14, @name="サンプル太郎">

項目11 構造化データの表現にはHashではなくStructを使おう

Typescriptを触っていて例えばUserの配列を作ろうとしたとき

type User = {
  id: string
  name: string
  address: string
}
const users: User[] = []

Userって型を作ってその配列だよ!って型宣言してたんですが、これと似たようなことだと認識してます。

[2] pry(main)> sample_users = [
[2] pry(main)*   { id: "1", name: "太郎", age: 8, nickname: "とっとこ太郎" }, 
[2] pry(main)*   {id: "2", name: "花子", age: 11, nickname: "トイレの花子"} 
[2] pry(main)* ]  
=> [{:id=>"1", :name=>"太郎", :age=>8, :nickname=>"とっとこ太郎"}, {:id=>"2", :name=>"花子", :age=>11, :nickname=>"トイレの花子"}]
[3] pry(main)> 
[4] pry(main)> array = []
=> []
[5] pry(main)> 
[6] pry(main)> sample_users.each do |user|
[6] pry(main)*   array << { name: user[:name], nickname: user[:nickname] } 
[6] pry(main)* end  
=> [{:id=>"1", :name=>"太郎", :age=>8, :nickname=>"とっとこ太郎"}, {:id=>"2", :name=>"花子", :age=>11, :nickname=>"トイレの花子"}]
[7] pry(main)> 
[8] pry(main)> array[0][:missing]
=> nil

見て分かる通り、missingなんてkeyがないので、本来ならエラー発生してほしいんですが、nilが返ってきてしまいます。
これだと仮にタイポしてたとしても気づかないってことが。
それを防ぐために、Structで型を定義してそれをarrayに詰めようって話ですね。

[19] pry(main)> SampleUser = Struct.new(:name, :nickname)
=> SampleUser
[23] pry(main)> array = []
=> []
[24] pry(main)> sample_users.each do |user|
[24] pry(main)*   array << SampleUser.new(user[:name], user[:nickname])
[24] pry(main)* end  
=> [{:id=>"1", :name=>"太郎", :age=>8, :nickname=>"とっとこ太郎"}, {:id=>"2", :name=>"花子", :age=>11, :nickname=>"トイレの花子"}]

[26] pry(main)> array
=> [#<struct Sample name="太郎", nickname="とっとこ太郎">, #<struct Sample name="花子", nickname="トイレの花子">]
[28] pry(main)> array[0]
=> #<struct Sample name="太郎", nickname="とっとこ太郎">
[29] pry(main)> array[0][:missing]
NameError: no member 'missing' in struct
[30] pry(main)> array[0][:name]
=> "太郎"
[31] pry(main)> array[0].name
=> "太郎"
[32] pry(main)> array[0].missing
NoMethodError: undefined method `missing' for #<struct Sample name="太郎", nickname="とっとこ太郎">
from (pry):36:in `<main>'

なるほど、nilが返ってこなくなりエラーが発生!これはいいですね!

項目19 reduceを使ってコレクションを畳み込む方法を身に付けよう

users = [{ name: "太郎", age: 22 }, { name: "花子", age: 11 }, { name: "大吉", age: 55 }]

ここから21才以上ののname取り出したい時って

[45] pry(main)> users.select { |u| u[:age] >= 21}.map{|u| u[:name]}
=> ["太郎", "大吉"]

って書くと思うのですが、これってselectで21才以上の新しい配列を作ってさらにそこにnameだけを抽出した新しい配列をつくるという無駄な処理があります。

ここでreduce使うと

[48] pry(main)> users.reduce([]) do |names, user|
[48] pry(main)*   names << user[:name] if user[:age] >= 21  
[48] pry(main)*   names
[48] pry(main)* end  
=> ["太郎", "大吉"]
[49] pry(main)> 

うん。シンプル。注意としてはアキュムレーターををしっかりとブロックの中で返してあげることですね。

感想

2回目読んでみましたが、リファクタリングに使えそうなTipsがあって読んで良かったと思います。
正直、第5章メタプログラミングと第8章メモリ管理とパフォーマンスは、どこで使うのか?、そもそも何いってるかようわからんって部分が大半だったので次本書を手にするときは「なるほど!」って思いたいところです

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

Rails Active Storage ファイルのパスを取得する方法

投稿した理由

divタグのstyle属性の値background-imageを使う際にURLが必要になったから

やり方

rails_blob_pathを使う(has_one_attached :image)

show.html.erb
<div style="background-image: url(<%= rails_blob_path(@user.image) %>) "></div>

おまけ

ActiveStorageメソッドあれこれ

  • image.attached? - 画像のアップロードがされているかを確かめるメソッド
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails] マイグレーションファイルの新規作成、書き方

マイグレーションファイルの新規作成コマンド
rails g migration <migration-file-name>

例えば、usersテーブルにカラムを追加、削除するマイグレーションファイルを作成するなら下記のように書く。
rails g migration add_remove_column_to_users

マイグレーションファイルの中には下記のように書く。

def change
  # usesテーブルにbirthdayカラムを追加
  add_column :users, :birthday, :string
  # usesテーブルにageカラムを削除
  remove_column :users, :age, :string

end

最後に、
rails g db:migrate
をすればマイグレーションファイルがDBに反映されます。

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

Rails 複数カラムの追加

やり方

ターミナル
$ rails g migration AddColumnToUsers
マイグレーションファイル
class AddColumnToUsers < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :family_name, :string
    add_column :users, :first_name, :string
    add_column :users, :family_name_kana, :string
    add_column :users, :first_name_kana, :string
  end
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsでhamlを使う

プログラミングの勉強日記

2020年7月29日 Progate Lv.226

概要

 こちらの記事で扱ったgemのhamlを説明する。hamlはHTML Abstraction Markup Languageの略で、簡単にHTMLのコードを書くことができる。erbと同じでRubyのコードを埋め込むこともできる。
 hamlには閉じタグが存在しないので、コードを簡単かつすっきり書くことができる。

使い方

 hamlを使うためにGemfileを編集する

Gemfile
gem 'haml-rails'

Gemfileを編集したら、hamlをインストールする。

ターミナル
bundle install

 これで、index.html.hamlといったビューファイルの拡張子にhamlを使えるようになる。

すでにあるerbファイルをhamlファイルに変えたい場合

Gemfile
gem 'haml-rails'
gem 'erb2haml'
ターミナル
  erbファイルを残して変換
$ rake haml:convert_erbs

  erbを削除して変換
$ rake haml:replace_erbs

基本的な書き方

 %タグ名と記述することで、開始タグと閉じタグに変換する。

index.html.haml
%html
 %body
  %div
   Hello World!

HTMLで以下のように変換されている

index.html
<html>
 <body>
  <div>
   Hello World!
  </div>
 </body>
</html>

hamlの書き方

各タグの書き方

hamlでの書き方 コンパイル後のコード(HTML)
%div <div></div>
%html <html></html>
%meta <meta></meta>
%header <header></header>
%footer <footer></footer>
%table <table></table>
%h1 <h1></h1>
%p <p></p>
%a <a></a>
%ul <ul></ul>
%li <li></li>

属性の書き方

 タグ内の属性は2つの書き方がある。

haml
%a(href='http://www~')
  リンク先の名前

%a{ href: 'http://www~' }
 リンク先の名前

HTMLでは以下のように変換されている

html
<a href="http://www~">
  リンク先の名前
</a>

IDとclassの書き方

haml
# idの指定
%div#id_name
  idを指定する

# クラスの指定
%div.class_name
  クラスを指定する

HTMLでは以下のように変換されている。

html
<div id="id_name">idを指定する</div>

<div class="class_name">クラスを指定する</div>

idとクラスを両方指定することもできる。

haml
%div.contemt#content1

HTMLでは以下のように変換されている。

html
<div class="content" id="content1">
</div>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む