rankable 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+