SakuraWi - BLog

みんなのウェディングのエンジニア。聴いたお話をまとめておく倉庫的な。スタックストックスタック!

【Ruby on Rails】enumとは?enumを使って可読性をあげてみよう

ども、櫻井広大です。

enumについて書いてみようと思います。 enumは使ってみると僕は便利だと思っているのですが、初学者からすると、一体これはどうやって使うんだ?とか、ちょっと抵抗があるなじゃないかと思ってまして

そのハードルのようなものが取っ払うことができればと思って書いています。

続きを読む

【Ruby on Rails】delegateの使い方【委譲は便利】

Ruby on Railsにおける便利なメソッドとして、 delegateがあります。

こちらを使うと、メソッドチェーンをたくさん書く必要なく実装することができます。

忘れずにrails guideのリンクも置いておきます。

Active Support コア拡張機能 - Rails ガイド

delegateの使い方

いつも書き方を忘れてしまうため、まずは利用例から書きます。

書き方としてはこのように書きます。

delegate :method_name, to: :associtation

覚えておくのは、delegate :aaaのようにかけば @instance.aaaと呼べるようになると認識しておくとよいと思います。

to:で書いた部分を省略できるというイメージです。

@instance.assoctiona.aaa と書いていた部分を、 @instance.aaaで呼べます。

delegateの実例

クラスの例としては User, Profileクラスがあるとしましょう。(railsガイドと同様の例にしました)

Userクラスは関連付けとして profileを持っているとします。 Profileにはnameカラムがあって参照できるとします。

class User < ApplicationRecord
  has_one :profile
end

@user.profile.nameのように名前を呼び出したいケースがあったとして、毎回メソッドチェーンしたものを書くと冗長に感じますよね。

と、いうことで Userクラスに nameメソッドを定義するとします。 以下のようなコードになるでしょう。

class User < ApplicationRecord
  has_one :profile
 
  def name
    profile.name
  end
end

これでも良いんですが、もっと簡潔に書く方法が delegateです。

@user.nameと呼び出すことが下記の書き方でも実現できます。

class User < ApplicationRecord
  has_one :profile
 
  delegate :name, to: :profile
end

より明示的かつ、短く書くことができました。

インスタンス変数や定数へもアクセスが可能

delegateする対象ですが、インスタンス変数へアクセスすることも可能です。

delegate to:@user

また、定数を参照することも可能。 定数はそのままクラスメソッドのように呼び出せるのであまり使うケースは少なそうに思います。

delegate to: :NUMBER

option

オプションとして、prefixをつけることも可能です。

delegate to: :method_name, prefix: :aaa

上記のように書くと、メソッドを呼び出すときに以下のように呼び出すことができます。

@instance.aaa_method_name

allow_nil

delegate :name, to: :profile, allow_nil: true

上記のように :allow_nilオプションを付与すると、間のprofileがnilだった場合に、

@user.name は例外ではなく、nilを返すようにできます

  def name
    profile&.name
  end

のようにぼっち演算子をつけたメソッドを定義した感じですね。

【Ruby on Rails】Rspecで行数を指定してテストを実行する方法

Ruby on RailsのテスティングフレームワークであるRspecを利用する際の行数を指定して実行する方法があります。

bundle exec rspec app/spec/test/test.rb:5

上記のように、最後に :10などのオプションを付与することで、その行のテストを実行することができます。

Rspecの行数指定のメリット

行数指定をするメリットとしては、テスト実行が早いことが一番のメリットかと思います。

必要な部分のテストだけを行うため、結果が返ってくるのも早いですし、テストが通ったのかどうかという確認も早いです。

E2Eテストである、feature_specsystem_specは実行がかなり重く、1ファイル単位の実行を繰り返しているとあっという間に時間が経ってしまいます。

このような重いテストを繰り返す場合は行数指定で必要最低限のテストだけ実行することが非常に効果的です。

describeやcontext単位で指定してみよう

例えば、下記のテストがあったとします。

テスト全体を実行したい場合

bundle exec rspec app/spec/test/test.rb:1

bundle exec rspec app/spec/test/test.rb

上記のコマンドですべて実行されます。

discribe "#メソッドのテスト" do
  context "when 成功時" do
    it { expect().to eq "ひとつめのテスト") }
    it { expect().to eq "ふたつめのテスト") }
  end

  context "when 失敗時" do
    it { expect().to eq "ひとつめのテスト") }
    it { expect().to eq "ふたつめのテスト") }
  end
end

context単位で実行したい場合

contextの行数部分で指定しましょう。

例えば、 "when 成功時" で囲まれたテストの実行はこんなコマンドです。

bundle exec rspec app/spec/test/test.rb:2

これで実行してテストされるのは、 it節の二つです。 以下の部分がテストとして実行されます。

    it { expect().to eq "ひとつめのテスト") }
    it { expect().to eq "ふたつめのテスト") }

it節単位で実行したい場合

bundle exec rspec app/spec/test/test.rb:3

bundle exec rspec app/spec/test/test.rb:4

といった具体の指定でOKです。

Rspecの行数指定のテストまとめ

行数指定をすることで実行速度の向上、生産性の向上が狙えます!

ぜひ、利用してみてください。

【Ruby on Rails】Railsにおける inverse_ofについて

双方間の関連付けで、異なるオブジェクトを参照しないように指定するオプション。 同様のレコードを見る、のようなイメージ。

Rails 4.1 以降は自動的に付与されるらしいが、関連付けにオプションが増えたりすると自動的につかないケースがある模様。

    has_many :books, -> { order display_order: :asc }, dependent: :destroy, inverse_of: :category

上記のように、orderをかませたりすると効かなくなってしまう。

[rubocop/warning] Rails/InverseOf: Specify an :inverse_of option.

ちなみにrubocopで怒られるエラーは上記。

inverse_ofをつけて対応しましょう。

参考

こちらのqiitaがわかりやすかった。 inverse_of について - Qiita

アジャイル開発の書籍を読んで

SCRUM BOOT CAMPを読んだので感想and学びをまとめておきます。

本誌の内容を抜粋しながら書きます。

まとめ

  • 可視化をすることで、問題を早期検知できるようにする。
  • 熱意は大切。
  • 成果を最大限にする責任をプロダクトオーナーがもつ。

ソフトウェアをつくる上で本当に大事なことは何でしょうか?

それはできたものを使って実際の利用者が便利になったりお金を稼いだりといった成果をあげることです。

P.20

成果を最大にするための方法の1種類。

約束

注意しなければならないのは、開発チームはスプリント計画で合意した内容を完了させることについては全力をつくす必要はあるものの、計画したことを全て完了させることは約束しているわけではないということです。

完了が目的になると、何かがおろそかになったり、不足の事態が’発生した場合に残業したり、プロダクトにおける問題が発生することになる。 ベロシティは、あくまでも守るべきポイントではなく、チームの状態を示すものの一部と捉えるのがよさそう。

P.30

ロールは目印

熱意のないひとがプロダクトオーナーだったら、どうなるんだろう?プロダクトオーナーがなんとなく思いついたことを実現するために、開発チームは数週間を費やすかもしれない。そしてできあがったものをみて、結局やり直しになるかもしれない。どっちのしようにした方がいいかを考えて欲しいとお願いしてもなかなか明確な答えが帰ってこないかもしれない。そんなふうにプロジェクトの大事な時間やお金を使っていて大丈夫なはずがない。

具体的に何かが足りなくて困っているのなら、スクラムチーム全体でどうやって補っていくかを考えて行けばいい。だけど、そもそも熱意を持っていないとしたら、それを補うのは一番難しいことなんだ

これに通ずる部分があるかも。

https://note.mu/lifeisbeautiful/n/na13cf6fffe8d

P.50

どれが重要か

自分たちで順序をつけることで、自分たちが大丈夫だと思えるようにするんだ。

自分たちで順序、優先順位を決めること。現場が決めることに意味がある。

P.72

スプリントレビューの目的

けれど、デモする本当の目的は、実際に動くものを触ってみて、本当はどうするべきかを知ることなんだ。

プロダクトを小さく試しながら、本当に価値のあるものへと磨いていく。 大きな手戻りはできるだけなくす。ペーパープロトタイプも一種。

P.132

着手するべきか

次のスプリントで実現したいものは、実現しても大丈夫だという確信がプロダクトオーナーにあって、開発チームに必要なことを伝えられるようになっていないといけない。開発チームも、これなら実現できそうだと判断できないといけない。

  1. 223

スクラム

スクラムは問題をみつけやすいやり方なんだな。プロジェクトの問題を見つけられるのは、実際にプロジェクトを進めていく現場の人たちだけなんだ。

P.263

【Ruby on Rails】カスタムレスポンスHTTPヘッダを付与する方法【noindexを指定する】

response.set_header('HEADER NAME', 'HEADER VALUE')

Rails5以前は以下の方法で書けるようです。

response.headers['HEADER NAME'] = 'HEADER VALUE'

実装例

class TestsController
  def index
     @books = Book.all
     response.headers['HEADER NAME'] = 'HEADER VALUE'
  end
end

上記のように書けばレスポンスヘッダに付与してくれます。

X-Robots-Tag HTTP ヘッダーにnoindexを付与する

Ruby on Railsを使っている時に、metaタグに記載するのではなく、レスポンスに直接noindexを付与したいケースもあると思います。 そんなときは以下のドキュメントにまずは目を通して、以下の実装をしましょう。

response.set_header('X-Robots-Tag', 'noindex')

robots メタタグと X-Robots-Tag HTTP ヘッダーの仕様  |  検索  |  Google Developers

参照するならやっぱりRailsガイド

細かい実装や実例はqiitaなどでよいと思いますが、概要をつかむにはやはりドキュメントかドキュメントに近しいものを読むのが一番です。

ということでRailsガイドにも記載があるのでまずはここを読んでおきましょう。

Action Controller の概要 - Rails ガイド

その他参考

ruby on rails - How do you add a custom http header? - Stack Overflow

Chrome拡張が思ったよりも簡単に作れるのを知って触ってみた

ども、櫻井広大です。

最近社内で思ったよりも簡単にchrome拡張が触れることを知ったのでやってみました。

書いた

github.com

実は2ファイルくらいで拡張機能って動かせるんですね。

manifest.jsonを用意して、動かすjsを置いてあげるだけ。

詰まった

.forEachは配列じゃないと利用できないので変換っぽい処理が必要だった

配列ライクなオブジェクトをforEachするときのイディオム - ぷちてく - Petittech

まだ未完成

もとからコメントボックスがある場合はOKなんですけど、 追加ででてきたコメントboxに対応ができてない。。。 うーむ

参考にした

Chrome 拡張機能のマニフェストファイルの書き方 - Qiita

Array.prototype.forEach() - JavaScript | MDN

getElementByIdとgetElementsByNameの違い - hogehoge foobar Blog Style5