QA@IT
«回答へ戻る

回答を投稿

あくまで私の考え方ですが、回答させていただきます。

RESTfulにするということは、操作対象となる概念を一つのリソースとして捉えて、アプリケーションの機能をそのリソースに対する単純なCRUD処理で実現できるように設計する、ということです。
これはあくまで、URLを通じてアクセスしてくる外側から見たシンプルさです。

しかし、常にindex, show, create, update, destroyだけではカバーできない事もあります。
その際も出来るだけ、対象となっているリソースを「参照する」「作成する」「更新する」「削除する」という考え方で処理できるようなメソッドにしていくのがRESTfulな設計だと思います。

一つの指針として、URLが名詞になっているかという考え方があります。CRUDに関わる動詞はHTTPメソッドとして表現できるので、RESTfulになっていれば多くの場合URLはリソースの場所を示すだけで済むはずです。

コントローラーについて

RESTfulな設計を行う場合、コントローラー数はどうしても増加する傾向になります。
操作対象によってコントローラーをしっかり分けることで、一つ一つのコントローラーは単純になり、よりモデルにロジックを書き易くなります。

とは言え、常にコントローラーを増やすのかについては議論の余地があります。
例えば、何かの一覧が欲しい時に全ての一覧と入力された文字列で検索されたパターンの両方が欲しい場合、コントローラーを増やして新しいリソースとして表現するよりも、searchというアクションを追加する方が自然なこともあります。

RESTfulな設計を行った場合、リソースとして表現するものは、必ずしもActiveRecordのモデルと1:1に対応するものではありません。
複数のテーブルをジョインした結果や、あるモデルの一部を切り出したものが一つのリソースとなる場合もあります。
それはURLを通じてアクセスするクライアントが、どの単位で情報を扱いたいのかに関わってきます。

今回の例で言うなら、従業員(Member)、社員(RegularMember),アルバイト(ParttimeMember)がリソースの候補になります。

もし、従業員全体を一つの集合として扱いたい場合があるなら、Memberというリソースを扱うコントローラーが必要です。
個別に社員とアルバイトを扱う用途が存在するなら、RegularMemberとParttimeMemberを扱うコントローラーが必要です。

URLについて

URLを表現するのに必ずしもnamespaceは必要ありません。
それもリソースがどういう扱いになるかで変化します。
社員とかアルバイトという概念が、あくまで従業員という概念の一部でしかないなら、namespaceで区切る方が自然かもしれません。

扱うリソースが増えてきた場合の対応

今回の例のように、ほぼ同じような処理が必要となる複数のリソースを扱う場合、実装が重複しないような対応策が必要になる場合があります。
最近のRailsでは、concernという考え方を用いてこれに対処するのがRailsらしいと思います。

concernは日本語だと「横断的関心事」と表現されます。

そのリソースに対してどういった処理が必要になるか、という事を「関心事」として振舞いを分離し、処理を共通化します。

例えば、従業員の検索が必要になった場合、RegularMembersControllerと、ParttimeMemmbersControllerにsearchメソッドを追加すると重複してしまいます。
そこで、Searchableのように「検索できる」という関心事に名前を付けてモジュールとして振舞いを分離します。

イメージとしては以下のような形です。

# app/controllers/concerns/searchable_resource.rb
module SearchableResource
  def search
    @searchable = searchable_model.search(params[:query])
    respond_with @searchable
  end
end

# app/controllers/regular_members_controller.rb
class RegularMembersController < ApplicationController
  include SearchableResource

  private
  def searchable_model
    RegularMember
  end
end

# app/controllers/parttime_members_controller.rb
class ParttimeMembersController < ApplicationController
  include SearchableResource

  private
  def searchable_model
    ParttimeMember
  end
end

# config/routes.rb
## 省略

concern :searchable do
  collection do
    get :search
  end
end

resources :regular_members, concerns: [:searchable]
resources :parttime_members, concerns: [:searchable]
## 省略

# モデルのメソッド呼び出しの形式も揃えておく必要があるので、モデル側にも似たようなconcernモジュールが入ることになります。

実際にはこんな綺麗にまとめられないことの方が多いですが、本当に同じ関心事を持った処理なら、このようにしてまとめていくのがRailsっぽいスタイルです。

ちなみに、routes.rbでのconcernの活用はRails4からの機能なので、利用しているRailsのバージョンに気を付けてください。

あくまで私の考え方ですが、回答させていただきます。

RESTfulにするということは、操作対象となる概念を一つのリソースとして捉えて、アプリケーションの機能をそのリソースに対する単純なCRUD処理で実現できるように設計する、ということです。
これはあくまで、URLを通じてアクセスしてくる外側から見たシンプルさです。

しかし、常にindex, show, create, update, destroyだけではカバーできない事もあります。
その際も出来るだけ、対象となっているリソースを「参照する」「作成する」「更新する」「削除する」という考え方で処理できるようなメソッドにしていくのがRESTfulな設計だと思います。

一つの指針として、URLが名詞になっているかという考え方があります。CRUDに関わる動詞はHTTPメソッドとして表現できるので、RESTfulになっていれば多くの場合URLはリソースの場所を示すだけで済むはずです。


## コントローラーについて
RESTfulな設計を行う場合、コントローラー数はどうしても増加する傾向になります。
操作対象によってコントローラーをしっかり分けることで、一つ一つのコントローラーは単純になり、よりモデルにロジックを書き易くなります。

とは言え、常にコントローラーを増やすのかについては議論の余地があります。
例えば、何かの一覧が欲しい時に全ての一覧と入力された文字列で検索されたパターンの両方が欲しい場合、コントローラーを増やして新しいリソースとして表現するよりも、`search`というアクションを追加する方が自然なこともあります。

RESTfulな設計を行った場合、リソースとして表現するものは、必ずしもActiveRecordのモデルと1:1に対応するものではありません。
複数のテーブルをジョインした結果や、あるモデルの一部を切り出したものが一つのリソースとなる場合もあります。
それはURLを通じてアクセスするクライアントが、どの単位で情報を扱いたいのかに関わってきます。

今回の例で言うなら、従業員(Member)、社員(RegularMember),アルバイト(ParttimeMember)がリソースの候補になります。

もし、従業員全体を一つの集合として扱いたい場合があるなら、Memberというリソースを扱うコントローラーが必要です。
個別に社員とアルバイトを扱う用途が存在するなら、RegularMemberとParttimeMemberを扱うコントローラーが必要です。

## URLについて
URLを表現するのに必ずしもnamespaceは必要ありません。
それもリソースがどういう扱いになるかで変化します。
社員とかアルバイトという概念が、あくまで従業員という概念の一部でしかないなら、namespaceで区切る方が自然かもしれません。

## 扱うリソースが増えてきた場合の対応
今回の例のように、ほぼ同じような処理が必要となる複数のリソースを扱う場合、実装が重複しないような対応策が必要になる場合があります。
最近のRailsでは、concernという考え方を用いてこれに対処するのがRailsらしいと思います。

concernは日本語だと「横断的関心事」と表現されます。

そのリソースに対してどういった処理が必要になるか、という事を「関心事」として振舞いを分離し、処理を共通化します。

例えば、従業員の検索が必要になった場合、RegularMembersControllerと、ParttimeMemmbersControllerに`search`メソッドを追加すると重複してしまいます。
そこで、`Searchable`のように「検索できる」という関心事に名前を付けてモジュールとして振舞いを分離します。

イメージとしては以下のような形です。

```ruby
# app/controllers/concerns/searchable_resource.rb
module SearchableResource
  def search
    @searchable = searchable_model.search(params[:query])
    respond_with @searchable
  end
end

# app/controllers/regular_members_controller.rb
class RegularMembersController < ApplicationController
  include SearchableResource

  private
  def searchable_model
    RegularMember
  end
end

# app/controllers/parttime_members_controller.rb
class ParttimeMembersController < ApplicationController
  include SearchableResource

  private
  def searchable_model
    ParttimeMember
  end
end

# config/routes.rb
## 省略

concern :searchable do
  collection do
    get :search
  end
end

resources :regular_members, concerns: [:searchable]
resources :parttime_members, concerns: [:searchable]
## 省略

# モデルのメソッド呼び出しの形式も揃えておく必要があるので、モデル側にも似たようなconcernモジュールが入ることになります。
```



実際にはこんな綺麗にまとめられないことの方が多いですが、本当に同じ関心事を持った処理なら、このようにしてまとめていくのがRailsっぽいスタイルです。

ちなみに、`routes.rb`でのconcernの活用はRails4からの機能なので、利用しているRailsのバージョンに気を付けてください。