Railsのリスト操作におけるURL設計

2013-02-25

前回の記事を基に、Facebookで #sendagayarb の皆さんとディスカッションした内容をここに残しておきます。

前回までの流れ

以下の様なリソースがあった場合、どのようなURL/コントローラでmove_highermove_to_bottomメソッドを叩くのか、というお題。


#from_README_Example.rb

class TodoList < ActiveRecord::Base
  has_many :todo_items, order: "position"
end

class TodoItem < ActiveRecord::Base
  belongs_to :todo_list
  acts_as_list scope: :todo_list
end

todo_list.first.move_to_bottom
todo_list.last.move_higher

# routes.rb
resources :todo_lists, shallow: true do
  resources :todo_items
end

リソースは何なのかを見極める

今回のリソースは「Itemの順序」です。

この「Itemの順序を更新する」という行為を、以下のように表現するべきだろうという結論になりました。


PUT /todo_lists/1/todo_items/2/position?move=bottom

ただ、パラメータ部分はいろいろ意見があってまとまっていないです。 上記の他に、to=topとかgo=downなど。

※ なお、原理主義者の方曰く「GETする意味のないものはリソースとして相応しくない」とのこと。

実装編

さて、これをどうやって実装するか、までは議論していなかったので、ここに続きを書いてみます。

まずmove_to_bottomは冪等(べきとう)であるためPUTでの実行が望ましいです。Rails4ではPATCHも利用できるのでそれでも良いでしょう。

move_higherは実行後のリソースの状態が冪等ではないためPOSTとして実行させます。

※ 冪等についてはこちらの記事を参照のこと。


#routes.rb

resources :todo_lists, shallow: true do
  resources :todo_items do
    resource :position, only: [:create, :update]
  end
end

routes.rbshallow: trueしているので、実際のURLはこんな感じですね。


PUT  /todo_items/2/position

次にコントローラ。


class PositionsController < ApplicationController
  # remote: true なアクセスを想定
  # 例: link_to 'higher', todo_item_position_path(todo_item, move: 'higher'), remote: true
  respond_to :js, :json

  # POST /todo_items/2/position?move=higher|lower
  # render create.js.erb or create.json.jbuilder or json: @chapter_article
  def create
    case params[:move]
    when 'higher' then @chapter_article.move_higher
    when 'lower' then @chapter_article.move_lower
    end
  end

  # PATCH/PUT /todo_items/2/position?move=top|bottom
  # render update.js.erb or update.json.jbuilder or json: @chapter_article
  def update
    case params[:move]
    when 'top' then @chapter_article.move_to_top
    when 'bottom' then @chapter_article.move_to_bottom
    end
  end
end

うう、、これは分ける必要があるのか?悩ましい。

所感

ともあれ、まあこんな塩梅で作っておけば問題は無さそうですね。 テストも書きやすいですし。

ただacts_as_list使うたびにPositionsControllerを作成するのは面倒そう。 どうせなら、Engie使ってgemにすると良いですね。

それとremote: trueのときに何をレンダリングさせるか、どうやってViewをレンダリングするか、ってのも最近気になってることに気づいた。 これも後で書きたい。

参考情報

RailsのURL設計を考えてみる(7) リスト操作

  • このエントリーをはてなブックマークに追加
comments powered by Disqus

Recent Article

About Me

身近な問題をみつけて、それを解決するためのサービスをつくっている。

SFA(営業支援ソフト)会社のJavaエンジニアだった頃に、新サービス開発の依頼を受けてRubyエンジニアとなる。

P4D デザイナー向けプログラム部デザインビギナーズというデザイン勉強会に参加し、デザインの面白さに触れたりしている。

もっと詳しく