ballot_box 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.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010-2011 Aimbulance.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,96 @@
1
+ = BallotBox
2
+
3
+ The BallotBox gem enables visitors to vote for and against voteable objects
4
+
5
+ == Install
6
+
7
+ gem 'ballot_box'
8
+
9
+ rails generate ballot_box:install
10
+
11
+ == Usage
12
+
13
+ Use middleware with options:
14
+
15
+ # Initialize BallotBox and set its configurations.
16
+ config.app_middleware.use BallotBox::Manager do |config|
17
+ config.routes = { "/posts/votes" => "Post" }
18
+ end
19
+
20
+ Set voteable model:
21
+
22
+ class Post < ActiveRecord::Base
23
+ ballot_box :counter_cache => true
24
+ # ballot_box :counter_cache => :rating, :strategies => [:authenticated]
25
+ end
26
+
27
+ View (just send post request to configure route):
28
+
29
+ link_to 'Vote', "/posts/votes?id=#{@post.id}", :remote => true, :method => :post
30
+
31
+ == Strategies
32
+
33
+ Strategy - is no more a simple validation at the object vote.
34
+ Authenticated - check :voter attribute is not blank.
35
+
36
+ module BallotBox
37
+ module Strategies
38
+ class Authenticated < Base
39
+ validates_presence_of :voter
40
+ end
41
+ end
42
+ end
43
+
44
+ Write your own strategies:
45
+
46
+ class MyCustomStrategy < BallotBox::Strategies::Base
47
+ validate :check_visible, :check_unique_voter
48
+
49
+ protected
50
+
51
+ def check_visible
52
+ errors.add(:voteable, :invalid) unless voteable.visible?
53
+ end
54
+
55
+ def check_unique_voter
56
+ if vote.class.where(["voter_id = ? AND voter_type = ?", vote.voter_id, vote.voter_type]).exists?
57
+ errors.add(:voter, :taken)
58
+ end
59
+ end
60
+ end
61
+
62
+ class Post < ActiveRecord::Base
63
+ ballot_box :strategies => [:authenticated, 'MyCustomStrategy']
64
+ end
65
+
66
+ == Callbacks
67
+
68
+ Middleware callbacks:
69
+
70
+ BallotBox::Manager.before_vote do |env, vote|
71
+ vote.voter = env['warden'].user
72
+ #vote.errors.add(:voter, :empty)
73
+ end
74
+
75
+ BallotBox::Manager.after_vote do |env, vote|
76
+ Rails.logger.info(vote.to_xml)
77
+ end
78
+
79
+ ActiveRecord callbacks:
80
+
81
+ class Post < ActiveRecord::Base
82
+ ballot_box :counter_cache => true
83
+
84
+ before_vote :method_before
85
+ after_vote :method_after
86
+
87
+ def method_before
88
+ Rails.logger.info current_vote.to_xml
89
+ # To terminate register vote, just return false
90
+ # return false
91
+ end
92
+
93
+ def method_after
94
+
95
+ end
96
+ end
data/Rakefile ADDED
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require File.join(File.dirname(__FILE__), 'lib', 'ballot_box', 'version')
6
+
7
+ desc 'Default: run unit tests.'
8
+ task :default => :test
9
+
10
+ desc 'Test the ballot_box plugin.'
11
+ Rake::TestTask.new(:test) do |t|
12
+ t.libs << 'lib'
13
+ t.libs << 'test'
14
+ t.pattern = 'test/**/*_test.rb'
15
+ t.verbose = true
16
+ end
17
+
18
+ desc 'Generate documentation for the ballot_box plugin.'
19
+ Rake::RDocTask.new(:rdoc) do |rdoc|
20
+ rdoc.rdoc_dir = 'rdoc'
21
+ rdoc.title = 'BallotBox'
22
+ rdoc.options << '--line-numbers' << '--inline-source'
23
+ rdoc.rdoc_files.include('README')
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
26
+
27
+ begin
28
+ require 'jeweler'
29
+ Jeweler::Tasks.new do |s|
30
+ s.name = "ballot_box"
31
+ s.version = BallotBox::VERSION.dup
32
+ s.summary = "The BallotBox gem enables visitors to vote for and against voteable objects"
33
+ s.description = "The BallotBox gem enables visitors to vote for and against voteable objects"
34
+ s.email = "galeta.igor@gmail.com"
35
+ s.homepage = "https://github.com/galetahub/ballot_box"
36
+ s.authors = ["Igor Galeta", "Pavlo Galeta"]
37
+ s.files = FileList["[A-Z]*", "{app,lib}/**/*"] - ["Gemfile"]
38
+ #s.extra_rdoc_files = FileList["[A-Z]*"]
39
+ end
40
+
41
+ Jeweler::GemcutterTasks.new
42
+ rescue LoadError
43
+ puts "Jeweler not available. Install it with: gem install jeweler"
44
+ end
@@ -0,0 +1,5 @@
1
+ module BallotBox
2
+ class Vote < ::ActiveRecord::Base
3
+ include BallotBox::Voting
4
+ end
5
+ end
@@ -0,0 +1,74 @@
1
+ module BallotBox
2
+ module Base
3
+ def self.included(base)
4
+ base.extend SingletonMethods
5
+ end
6
+
7
+ module SingletonMethods
8
+ #
9
+ # ballot_box :counter_cache => true,
10
+ # :strategies => [:authenticated]
11
+ #
12
+ def ballot_box(options = {})
13
+ extend ClassMethods
14
+ include InstanceMethods
15
+
16
+ options = { :strategies => [:authenticated] }.merge(options)
17
+
18
+ class_attribute :ballot_box_options, :instance_writer => false
19
+ self.ballot_box_options = options
20
+
21
+ has_many :votes,
22
+ :class_name => 'BallotBox::Vote',
23
+ :as => :voteable,
24
+ :dependent => :delete_all
25
+
26
+ attr_accessor :current_vote
27
+
28
+ define_ballot_box_callbacks :vote
29
+ end
30
+ end
31
+
32
+ module ClassMethods
33
+
34
+ def define_ballot_box_callbacks(*callbacks)
35
+ define_callbacks *[callbacks, {:terminator => "result == false"}].flatten
36
+ callbacks.each do |callback|
37
+ eval <<-end_callbacks
38
+ def before_#{callback}(*args, &blk)
39
+ set_callback(:#{callback}, :before, *args, &blk)
40
+ end
41
+ def after_#{callback}(*args, &blk)
42
+ set_callback(:#{callback}, :after, *args, &blk)
43
+ end
44
+ end_callbacks
45
+ end
46
+ end
47
+
48
+ def ballot_box_cached_column
49
+ if ballot_box_options[:counter_cache] == true
50
+ "votes_count"
51
+ elsif ballot_box_options[:counter_cache]
52
+ ballot_box_options[:counter_cache]
53
+ else
54
+ false
55
+ end
56
+ end
57
+
58
+ def ballot_box_strategies
59
+ @@ballot_box_strategies ||= ballot_box_options[:strategies].map { |st| BallotBox.load_strategy(st) }
60
+ end
61
+ end
62
+
63
+ module InstanceMethods
64
+
65
+ def ballot_box_cached_column
66
+ @ballot_box_cached_column ||= self.class.ballot_box_cached_column
67
+ end
68
+
69
+ def ballot_box_valid?(vote)
70
+ self.class.ballot_box_strategies.map { |st| st.new(self, vote) }.map(&:valid?).all?
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+ module BallotBox
3
+ module Callbacks
4
+ # Hook to _run_callbacks asserting for conditions.
5
+ def _run_callbacks(kind, *args) #:nodoc:
6
+ options = args.last # Last callback arg MUST be a Hash
7
+
8
+ send("_#{kind}").each do |callback, conditions|
9
+ invalid = conditions.find do |key, value|
10
+ value.is_a?(Array) ? !value.include?(options[key]) : (value != options[key])
11
+ end
12
+
13
+ callback.call(*args) unless invalid
14
+ end
15
+ end
16
+
17
+ # A callback that runs before create vote
18
+ # Example:
19
+ # BallotBox::Manager.before_vote do |env, opts|
20
+ # end
21
+ #
22
+ def before_vote(options = {}, method = :push, &block)
23
+ raise BlockNotGiven unless block_given?
24
+ _before_vote.send(method, [block, options])
25
+ end
26
+
27
+ # Provides access to the callback array for before_vote
28
+ # :api: private
29
+ def _before_vote
30
+ @_before_vote ||= []
31
+ end
32
+
33
+ # A callback that runs after vote created
34
+ # Example:
35
+ # BallotBox::Manager.after_vote do |env, opts|
36
+ # end
37
+ #
38
+ def after_vote(options = {}, method = :push, &block)
39
+ raise BlockNotGiven unless block_given?
40
+ _after_vote.send(method, [block, options])
41
+ end
42
+
43
+ # Provides access to the callback array for before_vote
44
+ # :api: private
45
+ def _after_vote
46
+ @_after_vote ||= []
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+ module BallotBox
3
+ class Config < Hash
4
+ # Creates an accessor that simply sets and reads a key in the hash:
5
+ #
6
+ # class Config < Hash
7
+ # hash_accessor :routes
8
+ # end
9
+ #
10
+ # config = Config.new
11
+ # config.routes = {'/posts/vote' => 'Post' }
12
+ # config[:routes] #=> {'/posts/vote' => 'Post' }
13
+ #
14
+ def self.hash_accessor(*names) #:nodoc:
15
+ names.each do |name|
16
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
17
+ def #{name}
18
+ self[:#{name}]
19
+ end
20
+
21
+ def #{name}=(value)
22
+ self[:#{name}] = value
23
+ end
24
+ METHOD
25
+ end
26
+ end
27
+
28
+ hash_accessor :routes
29
+
30
+ def initialize(other={})
31
+ merge!(other)
32
+ self[:routes] ||= { "/ballot_box/vote" => 'Class' }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+ require 'rails'
3
+ require 'ballot_box'
4
+
5
+ module BallotBox
6
+ class Engine < ::Rails::Engine
7
+ config.before_initialize do
8
+ ActiveSupport.on_load :active_record do
9
+ ::ActiveRecord::Base.send :include, BallotBox::Base
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+ module BallotBox
3
+ class Manager
4
+ extend BallotBox::Callbacks
5
+
6
+ attr_accessor :config
7
+
8
+ # Initialize the middleware. If a block is given, a BallotBox::Config is yielded so you can properly
9
+ # configure the BallotBox::Manager.
10
+ def initialize(app, options={})
11
+ options.symbolize_keys!
12
+
13
+ @app, @config = app, BallotBox::Config.new(options)
14
+ yield @config if block_given?
15
+ self
16
+ end
17
+
18
+ def call(env) # :nodoc:
19
+ if voting_path?(env['PATH_INFO']) && env["REQUEST_METHOD"] == "POST"
20
+ create(env)
21
+ else
22
+ @app.call(env)
23
+ end
24
+ end
25
+
26
+ # :api: private
27
+ def _run_callbacks(*args) #:nodoc:
28
+ self.class._run_callbacks(*args)
29
+ end
30
+
31
+ protected
32
+
33
+ def create(env, body = '', status = 500)
34
+ request = Rack::Request.new(env)
35
+ vote = BallotBox::Vote.new(:request => request)
36
+ vote.voteable_type = @config.routes[ request.path_info ]
37
+
38
+ _run_callbacks(:before_vote, env, vote)
39
+
40
+ body, status = vote.call
41
+
42
+ _run_callbacks(:after_vote, env, vote)
43
+
44
+ [status, {'Content-Type' => 'application/json', 'Content-Length' => body.size.to_s}, body]
45
+ end
46
+
47
+ def voting_path?(request_path)
48
+ return false if @config.routes.nil?
49
+
50
+ @config.routes.keys.any? do |route|
51
+ route == request_path
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,7 @@
1
+ module BallotBox
2
+ module Strategies
3
+ class Authenticated < Base
4
+ validates_presence_of :voter
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ require 'active_model/validations'
2
+
3
+ module BallotBox
4
+ module Strategies
5
+ class Base
6
+ include ActiveModel::Validations
7
+
8
+ attr_accessor :voteable, :vote, :request
9
+
10
+ def initialize(voteable, vote)
11
+ @voteable = voteable
12
+ @vote = vote
13
+ @request = vote.request
14
+ end
15
+
16
+ def read_attribute_for_validation(key)
17
+ @vote[key]
18
+ end
19
+
20
+ # Returns the Errors object that holds all information about attribute error messages.
21
+ def errors
22
+ @vote.errors
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,4 @@
1
+ # encoding: utf-8
2
+ module BallotBox
3
+ VERSION = "0.1.0".freeze
4
+ end
@@ -0,0 +1,133 @@
1
+ # encoding: utf-8
2
+ require 'ipaddr'
3
+ require "browser"
4
+
5
+ module BallotBox
6
+ module Voting
7
+ def self.included(base)
8
+ base.send :include, InstanceMethods
9
+ base.send :extend, ClassMethods
10
+ end
11
+
12
+ module ClassMethods
13
+ def self.extended(base)
14
+ base.class_eval do
15
+ # Associations
16
+ belongs_to :voteable, :polymorphic => true
17
+ belongs_to :voter, :polymorphic => true
18
+
19
+ # Validations
20
+ validates_presence_of :ip_address, :user_agent, :voteable_id, :voteable_type
21
+ validates_numericality_of :value, :only_integer => true
22
+
23
+ # Callbacks
24
+ before_save :parse_browser
25
+ after_save :update_cached_columns
26
+ after_destroy :update_cached_columns
27
+
28
+ attr_accessible :request
29
+
30
+ composed_of :ip,
31
+ :class_name => 'IPAddr',
32
+ :mapping => %w(ip_address to_i),
33
+ :constructor => Proc.new { |ip_address| IPAddr.new(ip_address, Socket::AF_INET) },
34
+ :converter => Proc.new { |value| value.is_a?(Integer) ? IPAddr.new(value, Socket::AF_INET) : IPAddr.new(value.to_s) }
35
+
36
+ scope :with_voteable, lambda { |record| where(["voteable_id = ? AND voteable_type = ?", record.id, record.class.name]) }
37
+ end
38
+ end
39
+
40
+ def chart(mode)
41
+ result = case mode.to_s.downcase
42
+ when 'dates' then chart_dates
43
+ when 'browsers' then chart_browsers
44
+ when 'platforms' then chart_platforms
45
+ end
46
+
47
+ [ result ].to_json
48
+ end
49
+
50
+ protected
51
+
52
+ def chart_dates
53
+ data = scoped.select("DATE(created_at) AS created_at, SUM(value) AS rating").group("DATE(created_at)").all
54
+ data.collect { |item| [ item.created_at, item.rating.to_i ] }
55
+ end
56
+
57
+ def chart_browsers
58
+ data = scoped.select("browser_name, SUM(value) AS rating").group("browser_name").all
59
+ data.collect { |item| [ item.browser_name, item.rating.to_i ] }
60
+ end
61
+
62
+ def chart_platforms
63
+ data = scoped.select("browser_platform, SUM(value) AS rating").group("browser_platform").all
64
+ data.collect { |item| [ item.browser_platform, item.rating.to_i ] }
65
+ end
66
+ end
67
+
68
+ module InstanceMethods
69
+
70
+ def browser
71
+ @browser ||= Browser.new(:ua => user_agent, :accept_language => "en-us")
72
+ end
73
+
74
+ def anonymous?
75
+ voter.nil?
76
+ end
77
+
78
+ def as_json(options = nil)
79
+ options = {
80
+ :methods => [:ip],
81
+ :only => [:referrer, :value, :browser_version, :browser_name, :user_agent, :browser_platform ]
82
+ }.merge(options || {})
83
+
84
+ super
85
+ end
86
+
87
+ def request
88
+ @request
89
+ end
90
+
91
+ def request=(req)
92
+ self.ip = req.ip
93
+ self.user_agent = req.user_agent
94
+ self.referrer = req.referer
95
+ self.voteable_id = req.params["id"]
96
+ @request = req
97
+ end
98
+
99
+ def call
100
+ if register
101
+ [self.to_json, 200]
102
+ else
103
+ [self.errors.to_json, 422]
104
+ end
105
+ end
106
+
107
+ def register
108
+ if voteable && voteable.ballot_box_valid?(self)
109
+ voteable.current_vote = self
110
+
111
+ voteable.run_callbacks(:vote) do
112
+ errors.empty? && save
113
+ end
114
+ end
115
+ end
116
+
117
+ protected
118
+
119
+ def parse_browser
120
+ self.browser_name = browser.id.to_s
121
+ self.browser_version = browser.version
122
+ self.browser_platform = browser.platform.to_s
123
+ end
124
+
125
+ def update_cached_columns
126
+ if voteable && voteable.ballot_box_cached_column
127
+ count = voteable.votes.select("SUM(value)")
128
+ voteable.class.update_all("#{voteable.ballot_box_cached_column} = (#{count.to_sql})", ["id = ?", voteable.id])
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
data/lib/ballot_box.rb ADDED
@@ -0,0 +1,26 @@
1
+ module BallotBox
2
+ autoload :Voting, 'ballot_box/voting'
3
+ autoload :Manager, 'ballot_box/manager'
4
+ autoload :Config, 'ballot_box/config'
5
+ autoload :Callbacks, 'ballot_box/callbacks'
6
+ autoload :Base, 'ballot_box/base'
7
+
8
+ module Strategies
9
+ autoload :Base, 'ballot_box/strategies/base'
10
+ autoload :Authenticated, 'ballot_box/strategies/authenticated'
11
+ end
12
+
13
+ def self.table_name_prefix
14
+ 'ballot_box_'
15
+ end
16
+
17
+ def self.load_strategy(name)
18
+ case name.class.name
19
+ when "Symbol" then "BallotBox::Strategies::#{name.to_s.classify}".constantize
20
+ when "String" then name.classify.constantize
21
+ else name
22
+ end
23
+ end
24
+ end
25
+
26
+ require 'ballot_box/engine' if defined?(Rails)
@@ -0,0 +1,7 @@
1
+ Usage:
2
+ rails generate ballot_box:install
3
+
4
+ Options:
5
+
6
+ Example:
7
+ rails g ballot_box:install
@@ -0,0 +1,31 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+
4
+ module BallotBox
5
+ module Generators
6
+ class InstallGenerator < Rails::Generators::Base
7
+ include Rails::Generators::Migration
8
+
9
+ desc "Create ballot_box migration"
10
+ source_root File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
11
+
12
+ # copy migration files
13
+ def create_migrations
14
+ migration_template "migrate/create_votes.rb", File.join('db/migrate', "ballot_box_create_votes.rb")
15
+ end
16
+
17
+ def self.next_migration_number(dirname)
18
+ if ActiveRecord::Base.timestamped_migrations
19
+ current_time.utc.strftime("%Y%m%d%H%M%S")
20
+ else
21
+ "%.3d" % (current_migration_number(dirname) + 1)
22
+ end
23
+ end
24
+
25
+ def self.current_time
26
+ @current_time ||= Time.now
27
+ @current_time += 1.minute
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,34 @@
1
+ class BallotBoxCreateVotes < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :ballot_box_votes do |t|
4
+ # Voter
5
+ t.string :voter_type, :limit => 40
6
+ t.integer :voter_id
7
+
8
+ # Voteable
9
+ t.string :voteable_type, :limit => 40
10
+ t.integer :voteable_id
11
+
12
+ # User info
13
+ t.integer :ip_address, :limit => 8
14
+ t.string :user_agent
15
+ t.string :referrer
16
+ t.string :browser_name, :limit => 40
17
+ t.string :browser_version, :limit => 15
18
+ t.string :browser_platform, :limit => 15
19
+
20
+ # Vote value
21
+ t.integer :value, :default => 1
22
+
23
+ t.timestamps
24
+ end
25
+
26
+ add_index :ballot_box_votes, [:voter_type, :voter_id]
27
+ add_index :ballot_box_votes, [:voteable_type, :voteable_id]
28
+ add_index :ballot_box_votes, :ip_address
29
+ end
30
+
31
+ def self.down
32
+ drop_table :ballot_box_votes
33
+ end
34
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ballot_box
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
+ - Igor Galeta
14
+ - Pavlo Galeta
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-05-18 00:00:00 +03:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ type: :runtime
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 31
30
+ segments:
31
+ - 0
32
+ - 1
33
+ - 2
34
+ version: 0.1.2
35
+ name: browser
36
+ version_requirements: *id001
37
+ prerelease: false
38
+ - !ruby/object:Gem::Dependency
39
+ type: :runtime
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 0
48
+ version: "0"
49
+ name: activemodel
50
+ version_requirements: *id002
51
+ prerelease: false
52
+ description: The BallotBox gem enables visitors to vote for and against voteable objects
53
+ email: galeta.igor@gmail.com
54
+ executables: []
55
+
56
+ extensions: []
57
+
58
+ extra_rdoc_files:
59
+ - LICENSE
60
+ - README.rdoc
61
+ files:
62
+ - LICENSE
63
+ - README.rdoc
64
+ - Rakefile
65
+ - app/models/ballot_box/vote.rb
66
+ - lib/ballot_box.rb
67
+ - lib/ballot_box/base.rb
68
+ - lib/ballot_box/callbacks.rb
69
+ - lib/ballot_box/config.rb
70
+ - lib/ballot_box/engine.rb
71
+ - lib/ballot_box/manager.rb
72
+ - lib/ballot_box/strategies/authenticated.rb
73
+ - lib/ballot_box/strategies/base.rb
74
+ - lib/ballot_box/version.rb
75
+ - lib/ballot_box/voting.rb
76
+ - lib/generators/ballot_box/USAGE
77
+ - lib/generators/ballot_box/install_generator.rb
78
+ - lib/generators/ballot_box/templates/migrate/create_votes.rb
79
+ has_rdoc: true
80
+ homepage: https://github.com/galetahub/ballot_box
81
+ licenses: []
82
+
83
+ post_install_message:
84
+ rdoc_options: []
85
+
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ hash: 3
94
+ segments:
95
+ - 0
96
+ version: "0"
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ hash: 3
103
+ segments:
104
+ - 0
105
+ version: "0"
106
+ requirements: []
107
+
108
+ rubyforge_project:
109
+ rubygems_version: 1.6.2
110
+ signing_key:
111
+ specification_version: 3
112
+ summary: The BallotBox gem enables visitors to vote for and against voteable objects
113
+ test_files: []
114
+