{"action":"created","comment":{"url":"https://api.github.com/repos/rails/rails/pulls/comments/22776379","id":22776379,"diff_hunk":"@@ -5,11 +5,23 @@\n <% module_namespacing do -%>\n class <%= controller_class_name %>Controller < ApplicationController\n   before_action :set_<%= singular_table_name %>, only: [:show, :edit, :update, :destroy]\n+  \n+  <%- if collection_routing? -%>\n+  # GET <%= route_url %>/1..10,17\n+  def index\n+    @<%= plural_table_name %> = <%= singular_table_name %>_ids ? <%= orm_class.find(class_name, \"#{singular_table_name}_ids\") %> : <%= orm_class.all(class_name) %>\n+  end\n \n+  # <%= singular_table_name.capitalize %> ids\n+  def <%= singular_table_name %>_ids","path":"railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb","position":12,"original_position":12,"commit_id":"7023d3110aed18f201212643c1a89e891feb870b","original_commit_id":"7023d3110aed18f201212643c1a89e891feb870b","user":{"login":"ujjwalt","id":660290,"avatar_url":"https://avatars.githubusercontent.com/u/660290?v=3","gravatar_id":"","url":"https://api.github.com/users/ujjwalt","html_url":"https://github.com/ujjwalt","followers_url":"https://api.github.com/users/ujjwalt/followers","following_url":"https://api.github.com/users/ujjwalt/following{/other_user}","gists_url":"https://api.github.com/users/ujjwalt/gists{/gist_id}","starred_url":"https://api.github.com/users/ujjwalt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ujjwalt/subscriptions","organizations_url":"https://api.github.com/users/ujjwalt/orgs","repos_url":"https://api.github.com/users/ujjwalt/repos","events_url":"https://api.github.com/users/ujjwalt/events{/privacy}","received_events_url":"https://api.github.com/users/ujjwalt/received_events","type":"User","site_admin":false},"body":"Thanks @claudiob \r\nYes it's intended to be a public method :smile: ","created_at":"2015-01-12T06:28:08Z","updated_at":"2015-01-12T06:28:08Z","html_url":"https://github.com/rails/rails/pull/15719#discussion_r22776379","pull_request_url":"https://api.github.com/repos/rails/rails/pulls/15719","_links":{"self":{"href":"https://api.github.com/repos/rails/rails/pulls/comments/22776379"},"html":{"href":"https://github.com/rails/rails/pull/15719#discussion_r22776379"},"pull_request":{"href":"https://api.github.com/repos/rails/rails/pulls/15719"}}},"pull_request":{"url":"https://api.github.com/repos/rails/rails/pulls/15719","id":17141857,"html_url":"https://github.com/rails/rails/pull/15719","diff_url":"https://github.com/rails/rails/pull/15719.diff","patch_url":"https://github.com/rails/rails/pull/15719.patch","issue_url":"https://api.github.com/repos/rails/rails/issues/15719","number":15719,"state":"open","locked":false,"title":"Collection Routing for Rails","user":{"login":"ujjwalt","id":660290,"avatar_url":"https://avatars.githubusercontent.com/u/660290?v=3","gravatar_id":"","url":"https://api.github.com/users/ujjwalt","html_url":"https://github.com/ujjwalt","followers_url":"https://api.github.com/users/ujjwalt/followers","following_url":"https://api.github.com/users/ujjwalt/following{/other_user}","gists_url":"https://api.github.com/users/ujjwalt/gists{/gist_id}","starred_url":"https://api.github.com/users/ujjwalt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ujjwalt/subscriptions","organizations_url":"https://api.github.com/users/ujjwalt/orgs","repos_url":"https://api.github.com/users/ujjwalt/repos","events_url":"https://api.github.com/users/ujjwalt/events{/privacy}","received_events_url":"https://api.github.com/users/ujjwalt/received_events","type":"User","site_admin":false},"body":"As part of Google Summer of Code 2013, I worked on implementing a collection routing api for Rails under the mentorship of @pixeltrix.\r\nMajority of the work is over with enough stability to be considered for merging. I would like to open up the discussion on the api. The documentation still remains but this is on purpose considering the community might vote for changes.\r\n### Features\r\n#### Generate collection routes by including a collection option.\r\n```ruby\r\nresources :posts, collection: true\r\n# rake routes\r\n#     Prefix Verb   URI Pattern                Controller#Action\r\n#      posts GET    /posts(/:ids)(.:format)    posts#index {:ids=>/(?:[^\\.\\/\\?]|\\.\\.)+/, :collection=>true}\r\n#            POST   /posts(.:format)           posts#create {:collection=>true}\r\n#            PUT    /posts/:ids(.:format)      posts#replace {:ids=>/(?:[^\\.\\/\\?]|\\.\\.)+/, :collection=>true}\r\n#            PATCH  /posts/:ids(.:format)      posts#update_many {:ids=>/(?:[^\\.\\/\\?]|\\.\\.)+/, :collection=>true}\r\n#            DELETE /posts/:ids(.:format)      posts#destroy_many {:ids=>/(?:[^\\.\\/\\?]|\\.\\.)+/, :collection=>true}\r\n# edit_posts GET    /posts/:ids/edit(.:format) posts#edit_many {:ids=>/(?:[^\\.\\/\\?]|\\.\\.)+/, :collection=>true}\r\n#   new_post GET    /posts/new(.:format)       posts#new\r\n#  edit_post GET    /posts/:id/edit(.:format)  posts#edit\r\n#       post GET    /posts/:id(.:format)       posts#show\r\n#            PATCH  /posts/:id(.:format)       posts#update\r\n#            PUT    /posts/:id(.:format)       posts#update\r\n#            DELETE /posts/:id(.:format)       posts#destroy\r\n```\r\n\r\n#### Pass ranges as parameters and filter them using the Strong Parameters API\r\nRanges can now be passed as url parameters. Following are some examples :-\r\n```\r\nhttp://example.com/posts/1..10,17,45...89 => 1 to 10, 17 and 45 to 88\r\nhttp://example.com/posts/1..10,7 => 1 to 10\r\nhttp://example.com/posts/1,5,9 => 1, 5 and 9\r\n```\r\n\r\n```ruby\r\nfiltered_params = params.permit ids: 1...768\r\nfiltered_params = params.permit ids: 69..420\r\n```\r\n\r\n#### Generate collection routing enabled controllers using scaffolds\r\n`rails generate scaffold Posts --collection`\r\n```ruby\r\nclass PostsController < ApplicationController\r\n  before_action :set_post, only: [:show, :edit, :update, :destroy]\r\n  \r\n  # GET /posts/1..10,17\r\n  def index\r\n    @posts = post_ids ? Post.find(post_ids) : Post.all\r\n  end\r\n\r\n  # Post ids\r\n  def post_ids\r\n    @posts_ids ||= params.permit(ids: 1..2**32-1)\r\n  end\r\n\r\n  # GET /posts/1\r\n  def show\r\n  end\r\n\r\n  # GET /posts/new\r\n  def new\r\n    @post = Post.new\r\n  end\r\n\r\n  # GET /posts/1/edit\r\n  def edit\r\n  end\r\n\r\n  # POST /posts\r\n  def create\r\n    posts_params ? create_many : create_one\r\n  end\r\n\r\n  def create_many\r\n    @posts = Post.create(posts_params)\r\n    redirect_to posts_url(@posts), notice: 'Posts were successfully updated.'\r\n  end\r\n\r\n  def create_one\r\n    @post = Post.create(post_params)\r\n    redirect_to post_url(@post), notice: 'Post was successfully updated.'\r\n  end\r\n\r\n  # PATCH/PUT /posts/1\r\n  def update\r\n    if @post.update(post_params)\r\n      redirect_to @post, notice: 'Post was successfully updated.'\r\n    else\r\n      render action: 'edit'\r\n    end\r\n  end\r\n\r\n  # DELETE /posts/1\r\n  def destroy\r\n    @post.destroy\r\n    redirect_to posts_url, notice: 'Post was successfully destroyed.'\r\n  end\r\n  \r\n  # Collection routes\r\n  # PATCH /posts/1..10\r\n  def update_many\r\n    Post.find(post_ids).each do |post|\r\n      post.update(params[:posts][:\"#{post.id}\"])\r\n    end\r\n    redirect_to @post, notice: 'Posts were successfully updated.'\r\n  end\r\n\r\n  # PUT /posts/1..10\r\n  def replace\r\n    Post.destroy_all\r\n    create\r\n  end\r\n\r\n  # DELETE /users/1..10\r\n  def destroy_many\r\n    @posts = Post.destroy(posts_ids)\r\n  end\r\n  \r\n  private\r\n    # Use callbacks to share common setup or constraints between actions.\r\n    def set_post\r\n      @post = Post.find(params[:id])\r\n    end\r\n\r\n    # Only allow a trusted parameter \"white list\" through.\r\n    def post_params\r\n      params[:post]\r\n    end\r\n    \r\n    # Only allow a trusted collection parameter \"white list\" through.\r\n    def posts_params\r\n      params[:posts]\r\n    end\r\nend\r\n```\r\nScaffold generators of dependencies like JBuilder need to be updated to incorporate collection routing.\r\nFuture work will include reducing `replace` and `update_many` to single line atomic database operations using ActiveRecord.","created_at":"2014-06-14T09:34:40Z","updated_at":"2015-01-12T06:28:08Z","closed_at":null,"merged_at":null,"merge_commit_sha":null,"assignee":{"login":"pixeltrix","id":6321,"avatar_url":"https://avatars.githubusercontent.com/u/6321?v=3","gravatar_id":"","url":"https://api.github.com/users/pixeltrix","html_url":"https://github.com/pixeltrix","followers_url":"https://api.github.com/users/pixeltrix/followers","following_url":"https://api.github.com/users/pixeltrix/following{/other_user}","gists_url":"https://api.github.com/users/pixeltrix/gists{/gist_id}","starred_url":"https://api.github.com/users/pixeltrix/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pixeltrix/subscriptions","organizations_url":"https://api.github.com/users/pixeltrix/orgs","repos_url":"https://api.github.com/users/pixeltrix/repos","events_url":"https://api.github.com/users/pixeltrix/events{/privacy}","received_events_url":"https://api.github.com/users/pixeltrix/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/rails/rails/milestones/34","labels_url":"https://api.github.com/repos/rails/rails/milestones/34/labels","id":665192,"number":34,"title":"5.0.0","description":null,"creator":{"login":"rafaelfranca","id":47848,"avatar_url":"https://avatars.githubusercontent.com/u/47848?v=3","gravatar_id":"","url":"https://api.github.com/users/rafaelfranca","html_url":"https://github.com/rafaelfranca","followers_url":"https://api.github.com/users/rafaelfranca/followers","following_url":"https://api.github.com/users/rafaelfranca/following{/other_user}","gists_url":"https://api.github.com/users/rafaelfranca/gists{/gist_id}","starred_url":"https://api.github.com/users/rafaelfranca/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rafaelfranca/subscriptions","organizations_url":"https://api.github.com/users/rafaelfranca/orgs","repos_url":"https://api.github.com/users/rafaelfranca/repos","events_url":"https://api.github.com/users/rafaelfranca/events{/privacy}","received_events_url":"https://api.github.com/users/rafaelfranca/received_events","type":"User","site_admin":false},"open_issues":92,"closed_issues":36,"state":"open","created_at":"2014-05-21T00:58:22Z","updated_at":"2015-01-10T21:20:01Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/rails/rails/pulls/15719/commits","review_comments_url":"https://api.github.com/repos/rails/rails/pulls/15719/comments","review_comment_url":"https://api.github.com/repos/rails/rails/pulls/comments/{number}","comments_url":"https://api.github.com/repos/rails/rails/issues/15719/comments","statuses_url":"https://api.github.com/repos/rails/rails/statuses/7023d3110aed18f201212643c1a89e891feb870b","head":{"label":"ujjwalt:gsoc13","ref":"gsoc13","sha":"7023d3110aed18f201212643c1a89e891feb870b","user":{"login":"ujjwalt","id":660290,"avatar_url":"https://avatars.githubusercontent.com/u/660290?v=3","gravatar_id":"","url":"https://api.github.com/users/ujjwalt","html_url":"https://github.com/ujjwalt","followers_url":"https://api.github.com/users/ujjwalt/followers","following_url":"https://api.github.com/users/ujjwalt/following{/other_user}","gists_url":"https://api.github.com/users/ujjwalt/gists{/gist_id}","starred_url":"https://api.github.com/users/ujjwalt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ujjwalt/subscriptions","organizations_url":"https://api.github.com/users/ujjwalt/orgs","repos_url":"https://api.github.com/users/ujjwalt/repos","events_url":"https://api.github.com/users/ujjwalt/events{/privacy}","received_events_url":"https://api.github.com/users/ujjwalt/received_events","type":"User","site_admin":false},"repo":{"id":10567904,"name":"rails","full_name":"ujjwalt/rails","owner":{"login":"ujjwalt","id":660290,"avatar_url":"https://avatars.githubusercontent.com/u/660290?v=3","gravatar_id":"","url":"https://api.github.com/users/ujjwalt","html_url":"https://github.com/ujjwalt","followers_url":"https://api.github.com/users/ujjwalt/followers","following_url":"https://api.github.com/users/ujjwalt/following{/other_user}","gists_url":"https://api.github.com/users/ujjwalt/gists{/gist_id}","starred_url":"https://api.github.com/users/ujjwalt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ujjwalt/subscriptions","organizations_url":"https://api.github.com/users/ujjwalt/orgs","repos_url":"https://api.github.com/users/ujjwalt/repos","events_url":"https://api.github.com/users/ujjwalt/events{/privacy}","received_events_url":"https://api.github.com/users/ujjwalt/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ujjwalt/rails","description":"Ruby on Rails","fork":true,"url":"https://api.github.com/repos/ujjwalt/rails","forks_url":"https://api.github.com/repos/ujjwalt/rails/forks","keys_url":"https://api.github.com/repos/ujjwalt/rails/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ujjwalt/rails/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ujjwalt/rails/teams","hooks_url":"https://api.github.com/repos/ujjwalt/rails/hooks","issue_events_url":"https://api.github.com/repos/ujjwalt/rails/issues/events{/number}","events_url":"https://api.github.com/repos/ujjwalt/rails/events","assignees_url":"https://api.github.com/repos/ujjwalt/rails/assignees{/user}","branches_url":"https://api.github.com/repos/ujjwalt/rails/branches{/branch}","tags_url":"https://api.github.com/repos/ujjwalt/rails/tags","blobs_url":"https://api.github.com/repos/ujjwalt/rails/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ujjwalt/rails/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ujjwalt/rails/git/refs{/sha}","trees_url":"https://api.github.com/repos/ujjwalt/rails/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ujjwalt/rails/statuses/{sha}","languages_url":"https://api.github.com/repos/ujjwalt/rails/languages","stargazers_url":"https://api.github.com/repos/ujjwalt/rails/stargazers","contributors_url":"https://api.github.com/repos/ujjwalt/rails/contributors","subscribers_url":"https://api.github.com/repos/ujjwalt/rails/subscribers","subscription_url":"https://api.github.com/repos/ujjwalt/rails/subscription","commits_url":"https://api.github.com/repos/ujjwalt/rails/commits{/sha}","git_commits_url":"https://api.github.com/repos/ujjwalt/rails/git/commits{/sha}","comments_url":"https://api.github.com/repos/ujjwalt/rails/comments{/number}","issue_comment_url":"https://api.github.com/repos/ujjwalt/rails/issues/comments/{number}","contents_url":"https://api.github.com/repos/ujjwalt/rails/contents/{+path}","compare_url":"https://api.github.com/repos/ujjwalt/rails/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ujjwalt/rails/merges","archive_url":"https://api.github.com/repos/ujjwalt/rails/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ujjwalt/rails/downloads","issues_url":"https://api.github.com/repos/ujjwalt/rails/issues{/number}","pulls_url":"https://api.github.com/repos/ujjwalt/rails/pulls{/number}","milestones_url":"https://api.github.com/repos/ujjwalt/rails/milestones{/number}","notifications_url":"https://api.github.com/repos/ujjwalt/rails/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ujjwalt/rails/labels{/name}","releases_url":"https://api.github.com/repos/ujjwalt/rails/releases{/id}","created_at":"2013-06-08T11:46:55Z","updated_at":"2014-06-30T22:08:34Z","pushed_at":"2014-08-19T17:06:13Z","git_url":"git://github.com/ujjwalt/rails.git","ssh_url":"git@github.com:ujjwalt/rails.git","clone_url":"https://github.com/ujjwalt/rails.git","svn_url":"https://github.com/ujjwalt/rails","homepage":"http://rubyonrails.org","size":116939,"stargazers_count":2,"watchers_count":2,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":2,"default_branch":"master"}},"base":{"label":"rails:master","ref":"master","sha":"eb87074e0b73dcb80e8d47cbcfe355f8bdef8428","user":{"login":"rails","id":4223,"avatar_url":"https://avatars.githubusercontent.com/u/4223?v=3","gravatar_id":"","url":"https://api.github.com/users/rails","html_url":"https://github.com/rails","followers_url":"https://api.github.com/users/rails/followers","following_url":"https://api.github.com/users/rails/following{/other_user}","gists_url":"https://api.github.com/users/rails/gists{/gist_id}","starred_url":"https://api.github.com/users/rails/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rails/subscriptions","organizations_url":"https://api.github.com/users/rails/orgs","repos_url":"https://api.github.com/users/rails/repos","events_url":"https://api.github.com/users/rails/events{/privacy}","received_events_url":"https://api.github.com/users/rails/received_events","type":"Organization","site_admin":false},"repo":{"id":8514,"name":"rails","full_name":"rails/rails","owner":{"login":"rails","id":4223,"avatar_url":"https://avatars.githubusercontent.com/u/4223?v=3","gravatar_id":"","url":"https://api.github.com/users/rails","html_url":"https://github.com/rails","followers_url":"https://api.github.com/users/rails/followers","following_url":"https://api.github.com/users/rails/following{/other_user}","gists_url":"https://api.github.com/users/rails/gists{/gist_id}","starred_url":"https://api.github.com/users/rails/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rails/subscriptions","organizations_url":"https://api.github.com/users/rails/orgs","repos_url":"https://api.github.com/users/rails/repos","events_url":"https://api.github.com/users/rails/events{/privacy}","received_events_url":"https://api.github.com/users/rails/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rails/rails","description":"Ruby on Rails","fork":false,"url":"https://api.github.com/repos/rails/rails","forks_url":"https://api.github.com/repos/rails/rails/forks","keys_url":"https://api.github.com/repos/rails/rails/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rails/rails/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rails/rails/teams","hooks_url":"https://api.github.com/repos/rails/rails/hooks","issue_events_url":"https://api.github.com/repos/rails/rails/issues/events{/number}","events_url":"https://api.github.com/repos/rails/rails/events","assignees_url":"https://api.github.com/repos/rails/rails/assignees{/user}","branches_url":"https://api.github.com/repos/rails/rails/branches{/branch}","tags_url":"https://api.github.com/repos/rails/rails/tags","blobs_url":"https://api.github.com/repos/rails/rails/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rails/rails/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rails/rails/git/refs{/sha}","trees_url":"https://api.github.com/repos/rails/rails/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rails/rails/statuses/{sha}","languages_url":"https://api.github.com/repos/rails/rails/languages","stargazers_url":"https://api.github.com/repos/rails/rails/stargazers","contributors_url":"https://api.github.com/repos/rails/rails/contributors","subscribers_url":"https://api.github.com/repos/rails/rails/subscribers","subscription_url":"https://api.github.com/repos/rails/rails/subscription","commits_url":"https://api.github.com/repos/rails/rails/commits{/sha}","git_commits_url":"https://api.github.com/repos/rails/rails/git/commits{/sha}","comments_url":"https://api.github.com/repos/rails/rails/comments{/number}","issue_comment_url":"https://api.github.com/repos/rails/rails/issues/comments/{number}","contents_url":"https://api.github.com/repos/rails/rails/contents/{+path}","compare_url":"https://api.github.com/repos/rails/rails/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rails/rails/merges","archive_url":"https://api.github.com/repos/rails/rails/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rails/rails/downloads","issues_url":"https://api.github.com/repos/rails/rails/issues{/number}","pulls_url":"https://api.github.com/repos/rails/rails/pulls{/number}","milestones_url":"https://api.github.com/repos/rails/rails/milestones{/number}","notifications_url":"https://api.github.com/repos/rails/rails/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rails/rails/labels{/name}","releases_url":"https://api.github.com/repos/rails/rails/releases{/id}","created_at":"2008-04-11T02:19:47Z","updated_at":"2015-01-12T05:41:21Z","pushed_at":"2015-01-12T05:41:20Z","git_url":"git://github.com/rails/rails.git","ssh_url":"git@github.com:rails/rails.git","clone_url":"https://github.com/rails/rails.git","svn_url":"https://github.com/rails/rails","homepage":"http://rubyonrails.org","size":375109,"stargazers_count":24553,"watchers_count":24553,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":9474,"mirror_url":null,"open_issues_count":733,"forks":9474,"open_issues":733,"watchers":24553,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rails/rails/pulls/15719"},"html":{"href":"https://github.com/rails/rails/pull/15719"},"issue":{"href":"https://api.github.com/repos/rails/rails/issues/15719"},"comments":{"href":"https://api.github.com/repos/rails/rails/issues/15719/comments"},"review_comments":{"href":"https://api.github.com/repos/rails/rails/pulls/15719/comments"},"review_comment":{"href":"https://api.github.com/repos/rails/rails/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/rails/rails/pulls/15719/commits"},"statuses":{"href":"https://api.github.com/repos/rails/rails/statuses/7023d3110aed18f201212643c1a89e891feb870b"}}}}