Stop()メソッドのメモ

こんな感じのhtmlがあるとして(slimで書いています)

button Toggle
p.slide_text
| This is the test
hoge hoge
huga huga

 

slideToggleを使うと、ボタンをクリックするごとに要素を表示したり隠したりを

アニメーションを伴って出来る

button = $('button')
button.on 'click', ->
$('.slide_text').slideToggle()

 

この時、buttonを連打してしまうと、

連打した回数分開いたい閉じたりが実行されてしまうのだが

button = $('button')
button.on 'click', ->
$('.slide_text').stop(true, false).slideToggle()

こうすると、連打したタイミングで実行中のアクションが中断されるので、

より良い感じになる。

package.jsonについて復習

npm

  • パッケージ管理ツールの1つ
  • JavaScript(Node.js)のパッケージやモジュールをインストール、アップデートできる

package.json

  • このファイルにプロジェクト毎に必要なパッケージの名前とバージョンを記述すれば、npmが勝手に必要な(依存しているという)パッケージをインストールしてくれる。
  • インストールしたパッケージが依存しているパッケージや、さらにそれが依存しているパッケージも自動でインストールしてくれる

 

package.jsonの作り方

  • npm initコマンドを叩く
  • 自分でpackage.jsonファイルを作成する(`touch package.json`)

 

便利な点!!

package.jsonがあるディレクトリで npm install をすると

package.jsonに記述されている依存パッケージを自動でインストールしてくれる

 

package.jsonのプロパティについてつらつらと
  • name

モジュール名。必須項目

  • version

モジュールのバージョン。必須項目。

  • scripts

任意のコマンドにエイリアスをつけて実行できるようになる。すごく便利!!

 

1つのカラムにvalidatesとvalidateをつけたときに気をつけたいこと

仕事中に引っかかりそうになったので、備忘録がてら書きたいと思います。

 

RailsにおけるValidatesとValidateの違い

Validates

validatesは特定のカラムに対して、予めRailsが用意している条件で

バリデーションをかけたい時に使うメソッドです。

例えば下記では、nameカラムに必須条件を加えています。

他にも一意条件である、uniquenessや値の長さをチェックするlengthなどがあります。

```

class Person < ApplicationRecord

  validates :name, presence: true

end

```

 

Validate(カスタムメソッド)

カスタムメソッドとは、ユーザーが独自に作成出来る、モデルの状態を確認し不正な状態の時にerrorsコレクションにメッセージを追加することが出来る機能です。

例えば下記の様なMemberモデルがあるとします。

Memberモデルは入会日(start_date)と退会日(end_date)を持つとした時、

入会日は常に退会日より以前であるということをバリデーションの条件として

追加したい時は下記の様に設定できます。

```

class Member < ApplicationRecord

  validate :check_start_date_before_end_date

 

  def check_start_date_before_end_date

    return if start_date < end_date

 

    errors.add(:start_date, ": 入会日は退会日より後にはできません")

  end

```

 

validatesメソッドもvalidateメソッドもRailsの開発では必須なので、使う機会は頻繁にあるので、ちゃんと理解しておかないといけなかったのですが、今回は下記の様なパターンでちょっと引っかかってしまいました。

 

同一カラムに対してvalidatesとvalidteを使う

ずばり下記の様な条件で引っかかりました。

```

class Member < ApplicationRecord

  validates :start_date, presence: true

  validates :end_date, presence: true

  validate :check_start_date_before_end_date

 

  def check_start_date_before_end_date

    return if start_date < end_date

 

    errors.add(:start_date, ": 入会日は退会日より後にはできません")

  end

```

 

start_dateにもend_dateにも必須制約をつけていたので、すっかり油断していました。

これ、check_start_date_before_end_dateを通る時に、

start_dateもしくはend_dateがnilだった時に、

`NoMethodError: undefined method start_date for nil:NilClass`

で落ちてしまうんですね。

 

バリデーションはそれぞれ独立している

バリデーションでは、どこかで制約に引っかかった、引っかかっていない関係なしに、

設定しているバリデーションを全て実行する訳ですね。

そして、制約に引っかかったものは全てerrorsに追加され、

最終的にerrors.empty?がtrueならvalidはtrue

1つ以上でもエラーメッセージが追加されており、errors.empty?がfalseなら

validはfalseになるわけです。

 

ついつい、validatesで必須制約は作ったから

validateではチェックしなくていいと安心しがちですが、気をつけるべきでした。

コードレビューで心がけたいこと

仕事では、チームで開発をしているので、毎日お互いにコードレビューをする機会が多くあります。

しかし、コードレビューはどうしてもレビュワーの技術力や好みに左右される部分があり、私はまだまだ技術的に未熟な部分もあり、質の高いレビューは難しいな〜

と思うことが度々あります。

 

現在読んでいる最中の本の中に、コード妥当性レビュー観点という内容がありました。

そこでは、7つの設計原理といわれるコード構造上の核心観点のことで、

それをレビュー上での観点として持つことで、レビューの質の安定や向上が図ることが出来るという内容でした。

非常に参考になったので、7つの設計原理について、1から纏めてみたいと思います。

 

ちなみに、読んでいる本はこれです。

 

 


 

1. 単純原理

単純原理とはシンプルに実装するという原理です。

これだとそのままなので、シンプルとはでイメージしてみたのですが

  • ロジックが単純である
  • 見通しが良い
  • 初心者でも読みやすい(必要以上に複雑でない、基礎的に技術で構成されている)
  • 1つのメソッドが長すぎない

とかになると思います。(他にも多々あると思いますが)

 

ここは実装する上で真っ先に意識する点だと思いますが、

「初心者でも読みやすい」は特に大事にしたいなと思いました。

 

「メソッドを長くしない」に囚われすぎて、なかなか使うことの無いような

ニッチなメソッドを使ったり、ちょっと凝ったロジックを実装したりとかは無意識のうちにあることなので、意識していきたいなと思いました。

 

2. 同型原理 3. 対称原理

ここは一緒に説明した方が分かりやすいかなと思ったので、一緒に説明します。

ここは、アプリケーション全体として、

  • 同じようなものは、同じように実装する
  • 反対のものは、明らかに反対なように実装する

というものでした。

 

ここは非常に重要だなと思って、

コードを読むときって、ミスが無いようにコードを遡って丁寧に読むことは

大事ですが、同じような実装は同じように実装してあった方が

スピーディーにミスなく読めるからです。

 

例えば、あるエクスポート処理の実装があったとして、

エクスポート処理の実装は、色々なデータの種類に応じて複数個作る必要がある

としたら、一連の処理が同じ様に実装されていた方が読みやすいですよね。

 

また、反対なものについてもそうで、

メソッド名でいうとgetの反対はsetで。pushの反対派popで命名するべき

などがあります。

 

4. 階層原理

これは、処理の階層関係を理解し、整理することが大事だという内容でした。

個人的には一番出来ていなくてハットした原理でした。

階層関係でも十分伝わると思うのですが、

1つのメソッドの中には、同じ抽象度のものを扱う様にする

という様に理解しました。

 

例えば、基本的にあるデータをDBに保存するまでの処理があったとして、

簡単に考えると、流れとしては

  1. データをどこからか受け取る
  2. 保存できる形に整形する
  3. 保存する

といったような順番になると思います。

この時、1.2.3はそれぞれさらに細かく分けることが出来て

1.データをどこからか受け取る(APIで受け取るとします)

     1. リクエスト先のURLを取得する

     2. リクエストするときのパラメータを設定

     3. 例外処理の対応

     4. etc...

 

などなど、1を達成するために必要なことがさらに複数あります。

で、このときに、これらの詳細な項目と、最初の1.2.3の大項目を

同じ階層で扱わないことが大事になります。

これらは抽象度が違うことなので、完全に分けて実装すべきで、

詳細項目は、大項目の下の階層で扱うべき問題になります。

 

5. 線形原理

これは処理の流れは直線的であるべきという内容です。

受け取るデータによって、通るべき処理が全く異なってしまう様な実装は非常に複雑なので控えようと思いました。

 

6. 明証原理 7. 安全原理

ここは1の単純原理とも近しい部分があるのですが、

常に実装は明確になっていて、後にメンテナンスをする技術者が読んでも

確実に理解できる実装を心がけなさいということでした。

また、安全原理に関しては、実装は基本的に常に安全サイドに倒して実装しなさい

という内容でした。

「ここのメソッドはこんなデータを受け取ることは無いだろう」

という安易な予測がバグをうむ原因になることは多々あると思うので、

必要以上な対応は返って複雑性をうむので、加減が大事ですが、

例外処理や、データチェックは念入りに行うに越したことは無いということでした。

 

基本的にこれらは、自らが実装するときに心がけるべき内容という感じなのですが、

実装する時より、ついつい観点がブレがちなレビューでも、これらを意識してレビュー

することで、今までより安定的、かつ質の高いレビューを心がけたいなと思いました。

 

RSpecのexpect() と expect{ } がややこしい

expect() と expect{ }の使い分けを理解する

最近RSpecのテストを書くようになったのですが、 expect()expect{ } の違いがよく分かっておらず、「どっちかでテストを書いてみて、 テストが落ちたら、もう片方に修正する。」 なんて、非常に無駄な作業が発生していたので、調べてみました!

もうお分かりかと思いますが、RSpec初心者向けの記事です笑

結論

結論から言うと、expect()expect{ }2つを使い分けるコツは expectはmatcherに中身をそのまま渡すので、() で書けるか、{}でかけるかはmatcherがProcを評価できるか出来ないか次第 と言うことでした!

なので、この2つの理解が大事と言うことですね。 - matcher - Proc

どちらも、ご存知とは思いますが、一応簡単に説明入れると

matcher

matcherとは下でいう to の部分のことです。 expect() で呼んでいる変数とeqの後に続く期待する答えの橋渡し的な存在です。 to以外では、not_to be raise_errorなどがあります。

hoge = 3
expect(hoge).to eq 3

Proc

Procとはブロック(何らかの)をオブジェクト化するためのクラスです。 Procオブジェクトはcallメソッドによって実行されます。

ex

add_number = Proc.new { |num_1, num_2|
  puts num_1 + num_2
}
add_number.call(1, 2) #=> 3

Procについては下記の記事がわかりやすいと思います Ruby Procについて学ぶ - Qiita

下記の記事を参考にしたので、理由は下記の記事を参照してください。 should を捨て expect を使うようになった、たった一つの理由 - MUGENUP技術ブログ

Rubyのattr_accessorについて

こちらの記事を参考にしました!

以下は自分なりにこの記事を咀嚼したものですので、詳しくは元記事をお読みください。

bryankawa.hatenablog.com

 

Rubyのattr_accessorについてのお勉強

なんとなくModelクラスにいるあいつってぐらいしかきちんと分かっていないので、まとめてみました。

 

結論からいうと

👇を省略して記述するためのものがattr_accessor

class User
  def name
    @name
  end

  def name=(str)
    @name = str
  end
end

user = User.new
user.name = 'Yusuke'
user.name # => "Yusuke"

 

`User`インスタンスにある`name`は

読み取り書き込みが必要である。

そのため本来は👆の様に、

読み取りようのnameメソッドと

書き込みようのnameメソッド

が必要だが、それを簡単に記述できるようにしてくれるものがattr_accessorになる。

 

で、実際に使うとこうなる。

 

class User
  attr_accessor :name
end

user = User.new
user.name = "Yusuke"
user.name # => "Yusuke"

 

ちなみにこの2つの実装の中間がこんな感じ

 

class User
  attr_reader :name
  attr_writer :name
end

 

readerをゲッター

writerをセッターと呼ぶ

 

そして最後に。

attr_accessorで設定したnamはインスタンス変数でUserオブジェクトに設定することが出来る

 

class User
  attr_accessor :name

  def greeting
    "Hello #{@name}"
  end
end

user = User.new
user.name = "Yusuke"
user.greeting # => "Hello Yusuke"

Rails5へのバージョンアップ ApplicationRecordへの変更

Rails4からRails5にバージョンアップする時の変更点として、ApplicationRecordを継承するようになるのが大きな変更点の一つとしてある。

 

それぞれRails4、5のモデルを見てみると、

 

これがRails4

class Article < ActiveRecord::Base

end

 

これがRails5

class Article < ApplicationRecord

 end

 

4ではActiveRecord::Baseを継承していたのが、

5からApplicationRecordを継承するようになった。

 

で、ApplicationRecordはどうやってできているかと言うと、

# app/models/application_record.rb class ApplicationRecord < ActiveRecord::Base

self.abstract_class = true

end

 

ActiveRecord::Baseを継承している。

つまり、各モデルとActiveRecord::Baseの間に一つクラスが挟まるようになった。

 

最初は余計なものが増えて面倒臭いだけでは?と思ったが、

モデルに何か機能を追加したいときに、今まではActiveRecord::Baseに追加するので、ActiveRecord::Baseを継承する全てのクラスが強制的に機能を継承してしまい、無駄な影響を与えてしまう危険性があったが、それを今までよりは回避しやすくなったのがメリットで、目的だと思われる。