rankable 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,91 @@
1
+ # Rankable
2
+
3
+ Super-simple ActiveRecord extension module, to quickly an efficiently sort
4
+ records. Sorts/ranks records in a single SQL query.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your Gemfile:
9
+
10
+ gem "rankable"
11
+
12
+ Then, bundle:
13
+
14
+ $ bundle install
15
+
16
+ ## Usage Examples:
17
+
18
+ In the model:
19
+
20
+ # app/models/article.rb
21
+ class Article < ActiveRecord::Base
22
+ # Include module
23
+ include Rankable::Model
24
+
25
+ # You default column is "rank", change it e.g. via:
26
+ # self.rankable_column_name = :position
27
+ end
28
+
29
+ In your controllers:
30
+
31
+ # config/routes.rb
32
+ MyApp::Application.routes.draw do
33
+ resources :articles do
34
+ put :sort, :on => :collection
35
+ end
36
+ end
37
+
38
+ # app/controllers/articles_controllers.rb
39
+ class ArticlesController < ApplicationController
40
+ respond_to :html
41
+
42
+ def sort
43
+ Articles.rank_all(params[:article_ids])
44
+ head(:ok)
45
+ end
46
+ end
47
+
48
+ In your views:
49
+
50
+ <script>
51
+ $(function() {
52
+ $( "#sortable" ).sortable({
53
+ stop: function() {
54
+ $.post('<%= sort_articles_path %>', '_method=put&' + $(this).sortable('serialize'));
55
+ }
56
+ });
57
+ });
58
+ </script>
59
+
60
+ <ul id="sortable">
61
+ <li id="article_ids_1">Article 1</li>
62
+ <li id="article_ids_2">Article 2</li>
63
+ <li id="article_ids_3">Article 3</li>
64
+ <li id="article_ids_4">Article 4</li>
65
+ <li id="article_ids_5">Article 5</li>
66
+ </ul>
67
+
68
+
69
+ ## License
70
+
71
+ Copyright (C) 2011 Dimitrij Denissenko
72
+
73
+ Permission is hereby granted, free of charge, to any person obtaining
74
+ a copy of this software and associated documentation files (the
75
+ "Software"), to deal in the Software without restriction, including
76
+ without limitation the rights to use, copy, modify, merge, publish,
77
+ distribute, sublicense, and/or sell copies of the Software, and to
78
+ permit persons to whom the Software is furnished to do so, subject to
79
+ the following conditions:
80
+
81
+ The above copyright notice and this permission notice shall be
82
+ included in all copies or substantial portions of the Software.
83
+
84
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
85
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
86
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
87
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
88
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
89
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
90
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
91
+
@@ -0,0 +1,5 @@
1
+ require "active_record"
2
+
3
+ module Rankable
4
+ autoload :Model, "rankable/model"
5
+ end
@@ -0,0 +1,50 @@
1
+ # Includable module, for ActiveRecord::Base. By default, the "rank"
2
+ # column is used to store the sort order. To override:
3
+ #
4
+ # class Article < ActiveRecord::Base
5
+ # include Rankable::Model
6
+ # self.rankable_column_name = "position"
7
+ # end
8
+ #
9
+ module Rankable::Model
10
+ extend ActiveSupport::Concern
11
+
12
+ included do
13
+ class_attribute :rankable_column_name
14
+ self.rankable_column_name = "rank"
15
+ end
16
+
17
+ module ClassMethods
18
+
19
+ # Ranks all records by given IDs. Example:
20
+ #
21
+ # Article.rank_all([7,5,3])
22
+ # Article.find(7).rank # => 1
23
+ # Article.find(5).rank # => 2
24
+ # Article.find(3).rank # => 3
25
+ #
26
+ # Works with scopes too. Example:
27
+ #
28
+ # Article.unread.rank_all([2,4,3])
29
+ #
30
+ def rank_all(ids)
31
+ pk_col = columns_hash[primary_key]
32
+ rk_col = columns_hash[rankable_column_name.to_s]
33
+
34
+ raise "Ranking only works with integer primary keys" unless pk_col && pk_col.type == :integer
35
+ raise "Ranking is missing the '#{rankable_column_name}' column. Please add a '#{rankable_column_name}' to your database table or specify a custom column name via self.rankable_column_name = '...'" unless rk_col
36
+
37
+ ranked = Array.wrap(ids).map do |value|
38
+ Integer(value) rescue nil
39
+ end.compact
40
+ return 0 if ranked.empty?
41
+
42
+ clause = ranked.each_with_index.map do |id, index|
43
+ "WHEN #{connection.quote(id, pk_col)} THEN #{connection.quote(index + 1, rk_col)}"
44
+ end.join(' ')
45
+
46
+ where(primary_key.to_sym => ranked).update_all "#{connection.quote_column_name rankable_column_name} = CASE #{quoted_primary_key} #{clause} END"
47
+ end
48
+
49
+ end
50
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rankable
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Dimitrij Denissenko
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-08-30 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: activerecord
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ hash: 7
29
+ segments:
30
+ - 3
31
+ - 0
32
+ - 0
33
+ version: 3.0.0
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ description: ActiveRecord extension for ranking/storing records
37
+ email: dimitrij@blacksquaremedia.com
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files: []
43
+
44
+ files:
45
+ - README.markdown
46
+ - lib/rankable/model.rb
47
+ - lib/rankable.rb
48
+ homepage: https://github.com/bsm/rankable
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options: []
53
+
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 57
62
+ segments:
63
+ - 1
64
+ - 8
65
+ - 7
66
+ version: 1.8.7
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 23
73
+ segments:
74
+ - 1
75
+ - 3
76
+ - 6
77
+ version: 1.3.6
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.8.5
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: Sort your records efficiently!
85
+ test_files: []
86
+