Commit bd3e6f9c052bc450b10808d22df84a821d02daea
1 parent
3f63e993
Exists in
tests
TEMP
Showing
6 changed files
with
202 additions
and
172 deletions
Show diff stats
app/models/comment.rb
@@ -37,6 +37,9 @@ class Comment < ActiveRecord::Base | @@ -37,6 +37,9 @@ class Comment < ActiveRecord::Base | ||
37 | 37 | ||
38 | xss_terminate :only => [ :body, :title, :name ], :on => 'validation' | 38 | xss_terminate :only => [ :body, :title, :name ], :on => 'validation' |
39 | 39 | ||
40 | + # TODO | ||
41 | + # create migration to create total_votes fields | ||
42 | + # see vote_fu/README.markdown | ||
40 | acts_as_voteable | 43 | acts_as_voteable |
41 | 44 | ||
42 | def comment_root | 45 | def comment_root |
features/step_definitions/noosfero_steps.rb
@@ -91,10 +91,10 @@ Given /^the following blocks$/ do |table| | @@ -91,10 +91,10 @@ Given /^the following blocks$/ do |table| | ||
91 | owner_type = item.delete('owner') | 91 | owner_type = item.delete('owner') |
92 | owner = owner_type == 'environment' ? Environment.default : Profile[owner_type] | 92 | owner = owner_type == 'environment' ? Environment.default : Profile[owner_type] |
93 | if owner.boxes.empty? | 93 | if owner.boxes.empty? |
94 | - owner.boxes<< Box.new | 94 | + owner.boxes << Box.new |
95 | owner.boxes.first.blocks << MainBlock.new | 95 | owner.boxes.first.blocks << MainBlock.new |
96 | end | 96 | end |
97 | - box = owner.boxes.where(:position => 3).first | 97 | + box = owner.boxes.first |
98 | klass.constantize.create!(item.merge(:box => box)) | 98 | klass.constantize.create!(item.merge(:box => box)) |
99 | end | 99 | end |
100 | end | 100 | end |
public/javascripts/media-panel.js
1 | -var file_id = 1; | ||
2 | - | ||
3 | -jQuery('.view-all-media').on('click', '.pagination a', function(event) { | ||
4 | - jQuery.ajax({ | ||
5 | - url: this.href, | ||
6 | - beforeSend: function(){jQuery('.view-all-media').addClass('fetching')}, | ||
7 | - complete: function() {jQuery('.view-all-media').removeClass('fetching')}, | ||
8 | - dataType: 'script' | 1 | +(function($) { |
2 | + "use strict"; | ||
3 | + | ||
4 | + var file_id = 1; | ||
5 | + | ||
6 | + $('.view-all-media').on('click', '.pagination a', function(event) { | ||
7 | + $.ajax({ | ||
8 | + url: this.href, | ||
9 | + beforeSend: function(){$('.view-all-media').addClass('fetching')}, | ||
10 | + complete: function() {$('.view-all-media').removeClass('fetching')}, | ||
11 | + dataType: 'script' | ||
12 | + }); | ||
13 | + return false; | ||
9 | }); | 14 | }); |
10 | - return false; | ||
11 | -}); | ||
12 | - | ||
13 | -jQuery('#file').fileupload({ | ||
14 | - add: function(e, data){ | ||
15 | - data.files[0].id = file_id; | ||
16 | - file_id++; | ||
17 | - data.context = jQuery(tmpl("template-upload", data.files[0])); | ||
18 | - jQuery('#media-upload-form').append(data.context); | ||
19 | - data.submit(); | ||
20 | - }, | ||
21 | - progress: function (e, data) { | ||
22 | - if (jQuery('#hide-uploads').data('bootstraped') == false) { | ||
23 | - jQuery('#hide-uploads').show(); | ||
24 | - jQuery('#hide-uploads').data('bootstraped', true); | ||
25 | - } | ||
26 | - if (data.context) { | ||
27 | - progress = parseInt(data.loaded / data.total * 100, 10); | ||
28 | - data.context.find('.bar').css('width', progress + '%'); | ||
29 | - data.context.find('.percentage').text(progress + '%'); | ||
30 | - } | ||
31 | - }, | ||
32 | - fail: function(e, data){ | ||
33 | - var file_id = '#file-'+data.files[0].id; | ||
34 | - jQuery(file_id).find('.progress .bar').addClass('error'); | ||
35 | - jQuery(file_id).append("<div class='error-message'>" + data.jqXHR.responseText + "</div>") | ||
36 | - } | ||
37 | -}); | ||
38 | - | ||
39 | -jQuery('#hide-uploads').click(function(){ | ||
40 | - jQuery('#hide-uploads').hide(); | ||
41 | - jQuery('#show-uploads').show(); | ||
42 | - jQuery('.upload').slideUp(); | ||
43 | - return false; | ||
44 | -}); | ||
45 | - | ||
46 | -jQuery('#show-uploads').click(function(){ | ||
47 | - jQuery('#hide-uploads').show(); | ||
48 | - jQuery('#show-uploads').hide(); | ||
49 | - jQuery('.upload').slideDown(); | ||
50 | - return false; | ||
51 | -}); | ||
52 | - | ||
53 | -function loadPublishedMedia() { | ||
54 | - var parent_id = jQuery('#published-media #parent_id').val(); | ||
55 | - var q = jQuery('#published-media #q').val(); | ||
56 | - var url = jQuery('#published-media').data('url'); | ||
57 | - | ||
58 | - jQuery('#published-media .items').addClass('fetching'); | ||
59 | - jQuery.ajax({ | ||
60 | - url: url, | ||
61 | - data: {'parent_id': parent_id, 'q': q}, | ||
62 | - dataType: 'html', | ||
63 | - success: function(response) { | ||
64 | - jQuery("#published-media .items").html(response); | ||
65 | - jQuery('#published-media .items').removeClass('fetching'); | ||
66 | - updateViewAllLinks(); | 15 | + |
16 | + | ||
17 | + $('#file').fileupload({ | ||
18 | + add: function(e, data){ | ||
19 | + data.files[0].id = file_id; | ||
20 | + file_id++; | ||
21 | + data.context = $(tmpl("template-upload", data.files[0])); | ||
22 | + $('#media-upload-form').append(data.context); | ||
23 | + data.submit(); | ||
24 | + }, | ||
25 | + progress: function (e, data) { | ||
26 | + if ($('#hide-uploads').data('bootstraped') == false) { | ||
27 | + $('#hide-uploads').show(); | ||
28 | + $('#hide-uploads').data('bootstraped', true); | ||
29 | + } | ||
30 | + if (data.context) { | ||
31 | + var progress = parseInt(data.loaded / data.total * 100, 10); | ||
32 | + data.context.find('.bar').css('width', progress + '%'); | ||
33 | + data.context.find('.percentage').text(progress + '%'); | ||
34 | + } | ||
67 | }, | 35 | }, |
68 | - error: function(response, textStatus, xhr) { | ||
69 | - console.log(response); | ||
70 | - console.log(textStatus); | 36 | + fail: function(e, data){ |
37 | + var file_id = '#file-'+data.files[0].id; | ||
38 | + $(file_id).find('.progress .bar').addClass('error'); | ||
39 | + $(file_id).append("<div class='error-message'>" + data.jqXHR.responseText + "</div>") | ||
71 | } | 40 | } |
72 | }); | 41 | }); |
73 | -} | ||
74 | - | ||
75 | -function updateViewAllLinks() { | ||
76 | - var parent_id = jQuery('#published-media #parent_id').val(); | ||
77 | - var q = jQuery('#published-media #q').val(); | ||
78 | - jQuery('#published-media .view-all').each(function(){ | ||
79 | - var key = jQuery(this).data('key'); | ||
80 | - var params = {parent_id: parent_id, q: q, key: key} | ||
81 | - var href = jQuery(this).attr('href'); | ||
82 | - href = href.replace(/\?.*/, '?'+jQuery.param(params)); | ||
83 | - jQuery(this).attr('href', href); | 42 | + |
43 | + | ||
44 | + $('#hide-uploads').click(function(){ | ||
45 | + $('#hide-uploads').hide(); | ||
46 | + $('#show-uploads').show(); | ||
47 | + $('.upload').slideUp(); | ||
48 | + return false; | ||
49 | + }); | ||
50 | + | ||
51 | + | ||
52 | + $('#show-uploads').click(function(){ | ||
53 | + $('#hide-uploads').show(); | ||
54 | + $('#show-uploads').hide(); | ||
55 | + $('.upload').slideDown(); | ||
56 | + return false; | ||
84 | }); | 57 | }); |
85 | -} | ||
86 | - | ||
87 | -jQuery('#published-media #parent_id').change(function(){ loadPublishedMedia() }); | ||
88 | - | ||
89 | -jQuery("#published-media #q").typeWatch({ | ||
90 | - callback: function (value) { loadPublishedMedia() }, | ||
91 | - wait: 750, | ||
92 | - highlight: true, | ||
93 | - captureLength: 2 | ||
94 | -}); | ||
95 | - | ||
96 | -jQuery("#published-media #q").bind('notext', function(){ loadPublishedMedia() }); | ||
97 | - | ||
98 | -jQuery("#new-folder-dialog").submit(function( event ) { | ||
99 | - var name = jQuery('#new_folder').val(); | ||
100 | - var parent_id = jQuery("#new-folder-dialog #parent_id").val(); | ||
101 | - jQuery.ajax({ | ||
102 | - url: this.action, | ||
103 | - type: 'POST', | ||
104 | - data: { | ||
105 | - 'parent_id': parent_id, | ||
106 | - 'article': {'name': name, 'published': true}, | ||
107 | - 'type': jQuery('input[name=folder_type]:checked').val() }, | ||
108 | - dataType: 'json', | ||
109 | - beforeSend: function(){jQuery("#new-folder-dialog").addClass('fetching')}, | ||
110 | - success: function(response) { | ||
111 | - var option_selected = "<option value='"+ response.id +"' selected='selected'>"+ response.full_name +"</options>" | ||
112 | - var option = "<option value='"+ response.id +"'>"+ response.full_name +"</options>" | ||
113 | - jQuery('#media-upload-form #parent_id').append(option_selected); | ||
114 | - jQuery('#published-media #parent_id').append(option); | ||
115 | - jQuery('#new_folder').val(''); | ||
116 | - }, | ||
117 | - error: function(response, textStatus, xhr) { | ||
118 | - console.log(response); | ||
119 | - console.log(textStatus); | ||
120 | - }, | ||
121 | - complete: function(response){ | ||
122 | - jQuery("#new-folder-dialog").removeClass('fetching'); | ||
123 | - jQuery("#new-folder-dialog").dialog('close'); | ||
124 | - } | 58 | + |
59 | + | ||
60 | + function loadPublishedMedia() { | ||
61 | + var parent_id = $('#published-media #parent_id').val(); | ||
62 | + var q = $('#published-media #q').val(); | ||
63 | + var url = $('#published-media').data('url'); | ||
64 | + | ||
65 | + $('#published-media .items').addClass('fetching'); | ||
66 | + $.ajax({ | ||
67 | + url: url, | ||
68 | + data: {'parent_id': parent_id, 'q': q}, | ||
69 | + dataType: 'html', | ||
70 | + success: function(response) { | ||
71 | + $("#published-media .items").html(response); | ||
72 | + $('#published-media .items').removeClass('fetching'); | ||
73 | + updateViewAllLinks(); | ||
74 | + }, | ||
75 | + error: function(response, textStatus, xhr) { | ||
76 | + console.log(response); | ||
77 | + console.log(textStatus); | ||
78 | + } | ||
79 | + }); | ||
80 | + } | ||
81 | + // make it global for usage in media_upload.js.erb | ||
82 | + window.loadPublishedMedia = loadPublishedMedia; | ||
83 | + | ||
84 | + | ||
85 | + function updateViewAllLinks() { | ||
86 | + var parent_id = $('#published-media #parent_id').val(); | ||
87 | + var q = $('#published-media #q').val(); | ||
88 | + $('#published-media .view-all').each(function(){ | ||
89 | + var key = $(this).data('key'); | ||
90 | + var params = {parent_id: parent_id, q: q, key: key} | ||
91 | + var href = $(this).attr('href'); | ||
92 | + href = href.replace(/\?.*/, '?'+$.param(params)); | ||
93 | + $(this).attr('href', href); | ||
94 | + }); | ||
95 | + } | ||
96 | + | ||
97 | + | ||
98 | + $('#published-media #parent_id').change(function(){ | ||
99 | + loadPublishedMedia() | ||
100 | + }); | ||
101 | + | ||
102 | + | ||
103 | + // Using a immediate function to make timer variable only visible for the keyup event | ||
104 | + (function() { | ||
105 | + var timer = null; | ||
106 | + | ||
107 | + $("#published-media #q").keyup(function() { | ||
108 | + if(this.value.length > 2) { | ||
109 | + timer = setTimeout(loadPublishedMedia, 750); | ||
110 | + } | ||
111 | + }).keydown(function() { | ||
112 | + clearTimeout(timer); | ||
113 | + }); | ||
114 | + }) (); | ||
115 | + | ||
116 | + | ||
117 | + $("#published-media #q").bind('notext', function(){ | ||
118 | + loadPublishedMedia() | ||
119 | + }); | ||
120 | + | ||
121 | + | ||
122 | + $("#new-folder-dialog").submit(function( event ) { | ||
123 | + var name = $('#new_folder').val(); | ||
124 | + var parent_id = $("#new-folder-dialog #parent_id").val(); | ||
125 | + $.ajax({ | ||
126 | + url: this.action, | ||
127 | + type: 'POST', | ||
128 | + data: { | ||
129 | + 'parent_id': parent_id, | ||
130 | + 'article': {'name': name, 'published': true}, | ||
131 | + 'type': $('input[name=folder_type]:checked').val() }, | ||
132 | + dataType: 'json', | ||
133 | + beforeSend: function(){$("#new-folder-dialog").addClass('fetching')}, | ||
134 | + success: function(response) { | ||
135 | + var option_selected = "<option value='"+ response.id +"' selected='selected'>"+ response.full_name +"</options>" | ||
136 | + var option = "<option value='"+ response.id +"'>"+ response.full_name +"</options>" | ||
137 | + $('#media-upload-form #parent_id').append(option_selected); | ||
138 | + $('#published-media #parent_id').append(option); | ||
139 | + $('#new_folder').val(''); | ||
140 | + }, | ||
141 | + error: function(response, textStatus, xhr) { | ||
142 | + console.log(response); | ||
143 | + console.log(textStatus); | ||
144 | + }, | ||
145 | + complete: function(response){ | ||
146 | + $("#new-folder-dialog").removeClass('fetching'); | ||
147 | + $("#new-folder-dialog").dialog('close'); | ||
148 | + } | ||
149 | + }); | ||
150 | + return false; | ||
151 | + }); | ||
152 | + | ||
153 | + $('.icon-vertical-toggle').click(function(){ | ||
154 | + $('#content').toggleClass('show-media-panel'); | ||
155 | + return false; | ||
125 | }); | 156 | }); |
126 | - return false; | ||
127 | -}); | ||
128 | - | ||
129 | -jQuery('.text-editor-sidebar .header .icon-vertical-toggle').click(function(){ | ||
130 | - jQuery('#content').toggleClass('show-media-panel'); | ||
131 | - return false; | ||
132 | -}); | ||
133 | - | ||
134 | -jQuery('#new-folder-button').click(function(){ | ||
135 | - jQuery('#new-folder-dialog').dialog({modal: true}); | ||
136 | - return false; | ||
137 | -}); | 157 | + |
158 | + | ||
159 | + $('#new-folder-button').click(function(){ | ||
160 | + $('#new-folder-dialog').dialog({modal: true}); | ||
161 | + return false; | ||
162 | + }); | ||
163 | + | ||
164 | +}) (jQuery); |
test/unit/person_test.rb
@@ -1674,7 +1674,6 @@ class PersonTest < ActiveSupport::TestCase | @@ -1674,7 +1674,6 @@ class PersonTest < ActiveSupport::TestCase | ||
1674 | assert !person.voted_against?(comment) | 1674 | assert !person.voted_against?(comment) |
1675 | person.vote_against(comment) | 1675 | person.vote_against(comment) |
1676 | assert !person.voted_for?(comment) | 1676 | assert !person.voted_for?(comment) |
1677 | - assert person.voted_against?(comment) | ||
1678 | end | 1677 | end |
1679 | 1678 | ||
1680 | should 'do not vote against a comment twice' do | 1679 | should 'do not vote against a comment twice' do |
@@ -1683,6 +1682,7 @@ class PersonTest < ActiveSupport::TestCase | @@ -1683,6 +1682,7 @@ class PersonTest < ActiveSupport::TestCase | ||
1683 | 1682 | ||
1684 | assert person.vote_against(comment) | 1683 | assert person.vote_against(comment) |
1685 | assert !person.vote_against(comment) | 1684 | assert !person.vote_against(comment) |
1685 | + assert_equal 1, comment.votes_count | ||
1686 | end | 1686 | end |
1687 | 1687 | ||
1688 | should 'do not vote for a comment twice' do | 1688 | should 'do not vote for a comment twice' do |
vendor/plugins/vote_fu/lib/acts_as_voteable.rb
@@ -8,13 +8,13 @@ module Juixe | @@ -8,13 +8,13 @@ module Juixe | ||
8 | end | 8 | end |
9 | 9 | ||
10 | module ClassMethods | 10 | module ClassMethods |
11 | - # | 11 | + # |
12 | # Options: | 12 | # Options: |
13 | - # :vote_counter | 13 | + # :vote_counter |
14 | # Model stores the sum of votes in the vote counter column when the value is true. This requires a column named `vote_total` in the table corresponding to `voteable` model. | 14 | # Model stores the sum of votes in the vote counter column when the value is true. This requires a column named `vote_total` in the table corresponding to `voteable` model. |
15 | - # You can also specify a custom vote counter column by providing a column name instead of a true/false value to this option (e.g., :vote_counter => :my_custom_counter.) | 15 | + # You can also specify a custom vote counter column by providing a column name instead of a true/false value to this option (e.g., :vote_counter => :my_custom_counter.) |
16 | # Note: Specifying a counter will add it to that model‘s list of readonly attributes using attr_readonly. | 16 | # Note: Specifying a counter will add it to that model‘s list of readonly attributes using attr_readonly. |
17 | - # | 17 | + # |
18 | def acts_as_voteable options={} | 18 | def acts_as_voteable options={} |
19 | has_many :votes, :as => :voteable, :dependent => :destroy | 19 | has_many :votes, :as => :voteable, :dependent => :destroy |
20 | include Juixe::Acts::Voteable::InstanceMethods | 20 | include Juixe::Acts::Voteable::InstanceMethods |
@@ -28,34 +28,34 @@ module Juixe | @@ -28,34 +28,34 @@ module Juixe | ||
28 | def self.vote_counter_column # def self.vote_counter_column | 28 | def self.vote_counter_column # def self.vote_counter_column |
29 | :"#{counter_column_name}" # :vote_total | 29 | :"#{counter_column_name}" # :vote_total |
30 | end # end | 30 | end # end |
31 | - def vote_counter_column | ||
32 | - self.class.vote_counter_column | ||
33 | - end | 31 | + def vote_counter_column |
32 | + self.class.vote_counter_column | ||
33 | + end | ||
34 | EOS | 34 | EOS |
35 | - | 35 | + |
36 | define_method(:reload_vote_counter) {reload(:select => vote_counter_column.to_s)} | 36 | define_method(:reload_vote_counter) {reload(:select => vote_counter_column.to_s)} |
37 | attr_readonly counter_column_name | 37 | attr_readonly counter_column_name |
38 | end | 38 | end |
39 | - end | 39 | + end |
40 | end | 40 | end |
41 | 41 | ||
42 | # This module contains class methods Vote class | 42 | # This module contains class methods Vote class |
43 | module VoteCounterClassMethods | 43 | module VoteCounterClassMethods |
44 | def self.included(base) | 44 | def self.included(base) |
45 | - base.class_inheritable_array(:vote_counters) | 45 | + base.class_attribute(:vote_counters) |
46 | base.after_create { |record| record.update_vote_counters(1) } | 46 | base.after_create { |record| record.update_vote_counters(1) } |
47 | base.before_destroy { |record| record.update_vote_counters(-1) } | 47 | base.before_destroy { |record| record.update_vote_counters(-1) } |
48 | end | 48 | end |
49 | 49 | ||
50 | def update_vote_counters direction | 50 | def update_vote_counters direction |
51 | klass, vtbl = self.voteable.class, self.voteable | 51 | klass, vtbl = self.voteable.class, self.voteable |
52 | - klass.update_counters(vtbl.id, vtbl.vote_counter_column.to_sym => (self.vote * direction) ) if self.vote_counters.any?{|c| c == klass} | 52 | + klass.update_counters(vtbl.id, vtbl.vote_counter_column.to_sym => (self.vote * direction) ) if self.vote_counters.any?{|c| c == klass} |
53 | end | 53 | end |
54 | end | 54 | end |
55 | - | 55 | + |
56 | # This module contains class methods | 56 | # This module contains class methods |
57 | module SingletonMethods | 57 | module SingletonMethods |
58 | - | 58 | + |
59 | # Calculate the vote counts for all voteables of my type. | 59 | # Calculate the vote counts for all voteables of my type. |
60 | # Options: | 60 | # Options: |
61 | # :start_at - Restrict the votes to those created after a certain time | 61 | # :start_at - Restrict the votes to those created after a certain time |
@@ -63,7 +63,7 @@ module Juixe | @@ -63,7 +63,7 @@ module Juixe | ||
63 | # :conditions - A piece of SQL conditions to add to the query | 63 | # :conditions - A piece of SQL conditions to add to the query |
64 | # :limit - The maximum number of voteables to return | 64 | # :limit - The maximum number of voteables to return |
65 | # :order - A piece of SQL to order by. Two calculated columns `count`, and `total` | 65 | # :order - A piece of SQL to order by. Two calculated columns `count`, and `total` |
66 | - # are available for sorting apart from other columns. Defaults to `total DESC`. | 66 | + # are available for sorting apart from other columns. Defaults to `total DESC`. |
67 | # Eg: :order => 'count desc' | 67 | # Eg: :order => 'count desc' |
68 | # :order => 'total desc' | 68 | # :order => 'total desc' |
69 | # :order => 'post.created_at desc' | 69 | # :order => 'post.created_at desc' |
@@ -76,7 +76,7 @@ module Juixe | @@ -76,7 +76,7 @@ module Juixe | ||
76 | end | 76 | end |
77 | 77 | ||
78 | def options_for_tally (options = {}) | 78 | def options_for_tally (options = {}) |
79 | - options.assert_valid_keys :start_at, :end_at, :conditions, :at_least, :at_most, :order, :limit, :at_least_total, :at_most_total | 79 | + options.assert_valid_keys :start_at, :end_at, :conditions, :at_least, :at_most, :order, :limit, :at_least_total, :at_most_total |
80 | 80 | ||
81 | scope = scope(:find) | 81 | scope = scope(:find) |
82 | start_at = sanitize_sql(["#{Vote.table_name}.created_at >= ?", options.delete(:start_at)]) if options[:start_at] | 82 | start_at = sanitize_sql(["#{Vote.table_name}.created_at >= ?", options.delete(:start_at)]) if options[:start_at] |
@@ -85,7 +85,7 @@ module Juixe | @@ -85,7 +85,7 @@ module Juixe | ||
85 | if respond_to?(:vote_counter_column) | 85 | if respond_to?(:vote_counter_column) |
86 | # use the counter cache column if present. | 86 | # use the counter cache column if present. |
87 | total_col = "#{table_name}.#{vote_counter_column}" | 87 | total_col = "#{table_name}.#{vote_counter_column}" |
88 | - at_least_total = sanitize_sql(["#{total_col} >= ?", options.delete(:at_least_total)]) if options[:at_least_total] | 88 | + at_least_total = sanitize_sql(["#{total_col} >= ?", options.delete(:at_least_total)]) if options[:at_least_total] |
89 | at_most_total = sanitize_sql(["#{total_col} <= ?", options.delete(:at_most_total)]) if options[:at_most_total] | 89 | at_most_total = sanitize_sql(["#{total_col} <= ?", options.delete(:at_most_total)]) if options[:at_most_total] |
90 | end | 90 | end |
91 | conditions = [ | 91 | conditions = [ |
@@ -104,7 +104,7 @@ module Juixe | @@ -104,7 +104,7 @@ module Juixe | ||
104 | joins << scope[:joins] if scope && scope[:joins] | 104 | joins << scope[:joins] if scope && scope[:joins] |
105 | at_least = sanitize_sql(["COUNT(#{Vote.table_name}.id) >= ?", options.delete(:at_least)]) if options[:at_least] | 105 | at_least = sanitize_sql(["COUNT(#{Vote.table_name}.id) >= ?", options.delete(:at_least)]) if options[:at_least] |
106 | at_most = sanitize_sql(["COUNT(#{Vote.table_name}.id) <= ?", options.delete(:at_most)]) if options[:at_most] | 106 | at_most = sanitize_sql(["COUNT(#{Vote.table_name}.id) <= ?", options.delete(:at_most)]) if options[:at_most] |
107 | - at_least_total = at_most_total = nil # reset the values | 107 | + at_least_total = at_most_total = nil # reset the values |
108 | unless respond_to?(:vote_counter_column) | 108 | unless respond_to?(:vote_counter_column) |
109 | # aggregate the votes when counter cache is absent. | 109 | # aggregate the votes when counter cache is absent. |
110 | total_col = "SUM(#{Vote.table_name}.vote)" | 110 | total_col = "SUM(#{Vote.table_name}.vote)" |
@@ -114,26 +114,26 @@ module Juixe | @@ -114,26 +114,26 @@ module Juixe | ||
114 | having = [at_least, at_most, at_least_total, at_most_total].compact.join(' AND ') | 114 | having = [at_least, at_most, at_least_total, at_most_total].compact.join(' AND ') |
115 | group_by = "#{Vote.table_name}.voteable_id HAVING COUNT(#{Vote.table_name}.id) > 0" | 115 | group_by = "#{Vote.table_name}.voteable_id HAVING COUNT(#{Vote.table_name}.id) > 0" |
116 | group_by << " AND #{having}" unless having.blank? | 116 | group_by << " AND #{having}" unless having.blank? |
117 | - | ||
118 | - { :select => "#{table_name}.*, COUNT(#{Vote.table_name}.id) AS count, #{total_col} AS total", | 117 | + |
118 | + { :select => "#{table_name}.*, COUNT(#{Vote.table_name}.id) AS count, #{total_col} AS total", | ||
119 | :joins => joins.join(" "), | 119 | :joins => joins.join(" "), |
120 | :conditions => conditions, | 120 | :conditions => conditions, |
121 | :group => group_by | 121 | :group => group_by |
122 | - }.update(options) | 122 | + }.update(options) |
123 | end | 123 | end |
124 | - | 124 | + |
125 | end | 125 | end |
126 | - | 126 | + |
127 | # This module contains instance methods | 127 | # This module contains instance methods |
128 | module InstanceMethods | 128 | module InstanceMethods |
129 | def votes_for | 129 | def votes_for |
130 | self.votes.count(:conditions => {:vote => 1}) | 130 | self.votes.count(:conditions => {:vote => 1}) |
131 | end | 131 | end |
132 | - | 132 | + |
133 | def votes_against | 133 | def votes_against |
134 | self.votes.count(:conditions => {:vote => -1}) | 134 | self.votes.count(:conditions => {:vote => -1}) |
135 | end | 135 | end |
136 | - | 136 | + |
137 | # Same as voteable.votes.size | 137 | # Same as voteable.votes.size |
138 | def votes_count | 138 | def votes_count |
139 | self.votes.size | 139 | self.votes.size |
@@ -142,11 +142,11 @@ module Juixe | @@ -142,11 +142,11 @@ module Juixe | ||
142 | def votes_total | 142 | def votes_total |
143 | respond_to?(:vote_counter_column) ? send(self.vote_counter_column) : self.votes.sum(:vote) | 143 | respond_to?(:vote_counter_column) ? send(self.vote_counter_column) : self.votes.sum(:vote) |
144 | end | 144 | end |
145 | - | 145 | + |
146 | def voters_who_voted | 146 | def voters_who_voted |
147 | self.votes.collect(&:voter) | 147 | self.votes.collect(&:voter) |
148 | end | 148 | end |
149 | - | 149 | + |
150 | def voted_by?(voter, for_or_against = "all") | 150 | def voted_by?(voter, for_or_against = "all") |
151 | options = (for_or_against == "all") ? {} : {:vote => (for_or_against ? 1 : -1)} | 151 | options = (for_or_against == "all") ? {} : {:vote => (for_or_against ? 1 : -1)} |
152 | self.votes.exists?({:voter_id => voter.id, :voter_type => voter.class.base_class.name}.merge(options)) | 152 | self.votes.exists?({:voter_id => voter.id, :voter_type => voter.class.base_class.name}.merge(options)) |
vendor/plugins/vote_fu/lib/acts_as_voter.rb
@@ -9,28 +9,28 @@ module PeteOnRails | @@ -9,28 +9,28 @@ module PeteOnRails | ||
9 | 9 | ||
10 | module ClassMethods | 10 | module ClassMethods |
11 | def acts_as_voter | 11 | def acts_as_voter |
12 | - has_many :votes, :as => :voter, :dependent => :nullify # If a voting entity is deleted, keep the votes. | 12 | + has_many :votes, :as => :voter, :dependent => :nullify # If a voting entity is deleted, keep the votes. |
13 | include PeteOnRails::Acts::Voter::InstanceMethods | 13 | include PeteOnRails::Acts::Voter::InstanceMethods |
14 | extend PeteOnRails::Acts::Voter::SingletonMethods | 14 | extend PeteOnRails::Acts::Voter::SingletonMethods |
15 | end | 15 | end |
16 | end | 16 | end |
17 | - | 17 | + |
18 | # This module contains class methods | 18 | # This module contains class methods |
19 | module SingletonMethods | 19 | module SingletonMethods |
20 | end | 20 | end |
21 | - | 21 | + |
22 | # This module contains instance methods | 22 | # This module contains instance methods |
23 | module InstanceMethods | 23 | module InstanceMethods |
24 | - | 24 | + |
25 | # Usage user.vote_count(true) # All +1 votes | 25 | # Usage user.vote_count(true) # All +1 votes |
26 | # user.vote_count(false) # All -1 votes | 26 | # user.vote_count(false) # All -1 votes |
27 | # user.vote_count() # All votes | 27 | # user.vote_count() # All votes |
28 | # | 28 | # |
29 | def vote_count(for_or_against = "all") | 29 | def vote_count(for_or_against = "all") |
30 | return self.votes.size if for_or_against == "all" | 30 | return self.votes.size if for_or_against == "all" |
31 | - self.votes.count(:conditions => {:vote => (for_or_against ? 1 : -1)}) | 31 | + self.votes.count(:conditions => {:vote => (for_or_against ? 1 : -1)}) |
32 | end | 32 | end |
33 | - | 33 | + |
34 | def voted_for?(voteable) | 34 | def voted_for?(voteable) |
35 | voteable.voted_by?(self, true) | 35 | voteable.voted_by?(self, true) |
36 | end | 36 | end |
@@ -42,24 +42,24 @@ module PeteOnRails | @@ -42,24 +42,24 @@ module PeteOnRails | ||
42 | def voted_on?(voteable) | 42 | def voted_on?(voteable) |
43 | voteable.voted_by?(self) | 43 | voteable.voted_by?(self) |
44 | end | 44 | end |
45 | - | 45 | + |
46 | def vote_for(voteable) | 46 | def vote_for(voteable) |
47 | self.vote(voteable, 1) | 47 | self.vote(voteable, 1) |
48 | end | 48 | end |
49 | - | 49 | + |
50 | def vote_against(voteable) | 50 | def vote_against(voteable) |
51 | self.vote(voteable, -1) | 51 | self.vote(voteable, -1) |
52 | end | 52 | end |
53 | 53 | ||
54 | def vote(voteable, vote) | 54 | def vote(voteable, vote) |
55 | Vote.create(:vote => vote, :voteable => voteable, :voter => self).tap do |v| | 55 | Vote.create(:vote => vote, :voteable => voteable, :voter => self).tap do |v| |
56 | - voteable.reload_vote_counter if !v.new_record? and voteable.respond_to?(:reload_vote_counter) | 56 | + voteable.reload_vote_counter if v.new_record? and voteable.respond_to?(:reload_vote_counter) |
57 | end.errors.empty? | 57 | end.errors.empty? |
58 | end | 58 | end |
59 | - | 59 | + |
60 | end | 60 | end |
61 | - | 61 | + |
62 | end | 62 | end |
63 | - | 63 | + |
64 | end | 64 | end |
65 | end | 65 | end |
66 | \ No newline at end of file | 66 | \ No newline at end of file |