bcms_polling 1.0.3 → 1.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/GPL.txt +674 -0
- data/Gemfile +4 -0
- data/README.markdown +8 -11
- data/{public/bcms/polling → app/assets}/README +0 -0
- data/app/assets/javascripts/bcms_polling.js +5 -0
- data/{public/bcms/polling → app/assets/javascripts/bcms_polling}/bcms-polling.js +0 -0
- data/app/assets/stylesheets/bcms_polling/application.css +13 -0
- data/{public/bcms/polling → app/assets/stylesheets/bcms_polling}/bcms-polling.css +0 -0
- data/app/controllers/bcms_polling/polling_controller.rb +46 -0
- data/app/controllers/bcms_polling/polls_controller.rb +2 -0
- data/app/helpers/bcms_polling/application_helper.rb +4 -0
- data/app/helpers/{cms → bcms_polling}/polls_helper.rb +1 -1
- data/app/models/bcms_polling/poll.rb +38 -0
- data/app/models/bcms_polling/poll_response.rb +9 -0
- data/app/views/{polling → bcms_polling/polling}/results.html.erb +1 -1
- data/app/views/{cms → bcms_polling}/polls/_form.html.erb +1 -2
- data/app/views/{cms → bcms_polling}/polls/render.html.erb +3 -3
- data/config/routes.rb +3 -0
- data/db/bcms_polling.seeds.rb +1 -0
- data/db/migrate/20110216195733_create_polls.rb +0 -4
- data/db/migrate/20120530182315_v110.rb +8 -0
- data/lib/bcms_polling.rb +5 -1
- data/lib/bcms_polling/engine.rb +27 -0
- data/lib/bcms_polling/route_extensions.rb +13 -0
- data/lib/bcms_polling/version.rb +3 -0
- data/lib/generators/bcms_polling/install/USAGE +3 -0
- data/lib/generators/bcms_polling/install/install_generator.rb +21 -0
- data/test/bcms_polling_test.rb +7 -0
- data/test/test_helper.rb +9 -32
- data/test/unit/models/bcms_polling/poll_response_test.rb +11 -0
- data/test/unit/models/bcms_polling/poll_test.rb +52 -0
- metadata +82 -66
- data/Rakefile +0 -42
- data/VERSION +0 -1
- data/app/controllers/cms/polls_controller.rb +0 -2
- data/app/controllers/polling_controller.rb +0 -44
- data/app/models/poll.rb +0 -37
- data/app/models/poll_response.rb +0 -4
- data/doc/README_FOR_APP +0 -2
- data/lib/bcms_polling/routes.rb +0 -12
- data/rails/init.rb +0 -5
- data/test/performance/browsing_test.rb +0 -9
- data/test/unit/models/poll_response_test.rb +0 -9
- data/test/unit/models/poll_test.rb +0 -41
data/Gemfile
ADDED
data/README.markdown
CHANGED
|
@@ -21,20 +21,18 @@ vote multiple times from multiple computers or just clear their cookies to revot
|
|
|
21
21
|
Installation:
|
|
22
22
|
=============
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
$ rails g cms:install bcms_polling
|
|
25
|
+
$ rake db:install
|
|
25
26
|
|
|
26
27
|
Follow standard module installation after that.
|
|
27
28
|
|
|
28
|
-
Finally, edit your project's app/helpers/application_helper.rb so it looks like:
|
|
29
|
-
|
|
30
|
-
module ApplicationHelper
|
|
31
|
-
include Cms::PollsHelper
|
|
32
|
-
end
|
|
33
|
-
|
|
34
29
|
Finally, add the default stylesheet for polls to your template, tweaking as necessary or inlining into the site's main stylesheet.
|
|
35
30
|
|
|
36
|
-
<%= stylesheet_link_tag '/bcms
|
|
31
|
+
<%= stylesheet_link_tag 'bcms_polling/bcms-polling' %>
|
|
37
32
|
|
|
33
|
+
Update your config/application.rb with the following:
|
|
34
|
+
|
|
35
|
+
Rails.application.routes.default_url_options[:host] = config.cms.site_domain
|
|
38
36
|
|
|
39
37
|
|
|
40
38
|
Bugs:
|
|
@@ -43,6 +41,5 @@ Bugs:
|
|
|
43
41
|
|
|
44
42
|
BrowserCMS Core Notes:
|
|
45
43
|
================
|
|
46
|
-
* Using nested_attributes doesn't work without some monkeying around. Specifically, BrowserCMS doesn't consider nested attributes as 'changes', so
|
|
47
|
-
|
|
48
|
-
nested_attributes and save correctly if they are present.
|
|
44
|
+
* Using nested_attributes doesn't work without some monkeying around. Specifically, BrowserCMS doesn't consider nested attributes as 'changes', so updates (and a new version) doesn't get saved. Can fix this by timestamping 'updated_at' but the core CMS should be aware of nested_attributes and save correctly if they are present.
|
|
45
|
+
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
3
|
+
* listed below.
|
|
4
|
+
*
|
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
|
7
|
+
*
|
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
|
10
|
+
*
|
|
11
|
+
*= require_self
|
|
12
|
+
*= require_tree .
|
|
13
|
+
*/
|
|
File without changes
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Handles the public submissions of answers to poll questions.
|
|
2
|
+
module BcmsPolling
|
|
3
|
+
class PollingController < ApplicationController
|
|
4
|
+
include BcmsPolling::PollsHelper
|
|
5
|
+
include Cms::Authentication::Controller
|
|
6
|
+
|
|
7
|
+
def update
|
|
8
|
+
@response = PollResponse.find(params[:id])
|
|
9
|
+
unique_key = cookie_key(@response.poll)
|
|
10
|
+
|
|
11
|
+
if !cookies[unique_key]
|
|
12
|
+
@response.votes += 1
|
|
13
|
+
@response.save!
|
|
14
|
+
|
|
15
|
+
cookies[unique_key] = {
|
|
16
|
+
:value => true,
|
|
17
|
+
:expires => 1.year.from_now
|
|
18
|
+
}
|
|
19
|
+
logger.warn "Saving cookie called '#{unique_key}'"
|
|
20
|
+
else
|
|
21
|
+
logger.warn "User attempted to submit another answer to the same poll."
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
render :nothing => true, :status => :ok
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def results
|
|
28
|
+
@poll = Poll.find(params[:id])
|
|
29
|
+
render :layout => false
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def reset
|
|
33
|
+
@poll = Poll.find(params[:id])
|
|
34
|
+
|
|
35
|
+
cookie = cookie_key(@poll)
|
|
36
|
+
cookies.delete(cookie)
|
|
37
|
+
|
|
38
|
+
redirect_to "/"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
def cookie_key(poll)
|
|
43
|
+
cookie_for(poll)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module BcmsPolling
|
|
2
|
+
class Poll < ActiveRecord::Base
|
|
3
|
+
acts_as_content_block
|
|
4
|
+
|
|
5
|
+
has_many :responses, :class_name => "PollResponse"
|
|
6
|
+
accepts_nested_attributes_for :responses, :allow_destroy => true
|
|
7
|
+
attr_accessible :responses_attributes
|
|
8
|
+
validates_presence_of :question
|
|
9
|
+
|
|
10
|
+
after_validation :ensure_responses_save
|
|
11
|
+
|
|
12
|
+
def total_votes
|
|
13
|
+
self.responses.inject(0) { |sum, r| sum += r.votes }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def name
|
|
17
|
+
question
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
# This is a work around for bugs in CMS 3.5.x where updates to nested_associations:
|
|
23
|
+
# 1. Do not count as 'changes' to the parent model (so they don't trigger a version save)
|
|
24
|
+
# 2. Associated blocks don't save and/or delete themselves like nested_attributes says they should.
|
|
25
|
+
#
|
|
26
|
+
# Both of these will require changes to the core CMS to fix.
|
|
27
|
+
def ensure_responses_save
|
|
28
|
+
responses.each do |r|
|
|
29
|
+
if r.changed?
|
|
30
|
+
r.save
|
|
31
|
+
elsif r.marked_for_destruction?
|
|
32
|
+
responses.delete(r)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<% end %>
|
|
7
7
|
</ul>
|
|
8
8
|
<% if cookies[cookie_for(@poll)] && current_user.able_to?(:edit_content)-%>
|
|
9
|
-
<%= link_to "Vote Again (Reset Cookie)", poll_reset_path(@poll) %>
|
|
9
|
+
<%= link_to "Vote Again (Reset Cookie)", main_app.poll_reset_path(@poll) %>
|
|
10
10
|
<% end %>
|
|
11
11
|
<% if params[:return] == 'true' %>
|
|
12
12
|
<%= link_to_function "Back to Poll", 'history.go(0);return false;' %>
|
|
@@ -51,8 +51,7 @@
|
|
|
51
51
|
|
|
52
52
|
<div id="responses">
|
|
53
53
|
<% count = 0 -%>
|
|
54
|
-
|
|
55
|
-
<% f.fields_for(:responses, available_responses) do |response_fields| %>
|
|
54
|
+
<%= f.fields_for :responses do |response_fields| %>
|
|
56
55
|
<%= response_fields.cms_text_field :answer, :label => "Response ##{count = count + 1}" %>
|
|
57
56
|
<%= link_to_function('Delete', 'removeResponse(this)', 'data-count-id'=>count-1, :style=>'position: relative; left: 465px; top: -25px;') %>
|
|
58
57
|
<%= response_fields.check_box :_destroy, :style=>"display:none" %>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<% unless self.controller.instance_variable_defined? :@include_js_http_methods -%>
|
|
2
|
-
<%= javascript_include_tag '
|
|
2
|
+
<%= javascript_include_tag 'bcms_polling' %>
|
|
3
3
|
<%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? -%>
|
|
4
4
|
<% self.controller.instance_variable_set(:@include_js_http_methods, true) -%>
|
|
5
5
|
<% end -%>
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
<span class="question"><%= @content_block.question %></span>
|
|
10
10
|
|
|
11
11
|
<ul class="vote-choices">
|
|
12
|
-
<% for response in PollResponse.find(:all, :conditions => {:poll_id => @content_block.id}) %>
|
|
12
|
+
<% for response in BcmsPolling::PollResponse.find(:all, :conditions => {:poll_id => @content_block.id}) %>
|
|
13
13
|
<li>
|
|
14
14
|
<span class="response"><%= response.answer %></span>
|
|
15
|
-
<%= link_to "Vote!", poll_response_url(response), :class => "vote-this", 'data-poll-id'=>@content_block.id %>
|
|
15
|
+
<%= link_to "Vote!", main_app.poll_response_url(response), :class => "vote-this", 'data-poll-id'=>@content_block.id %>
|
|
16
16
|
</li>
|
|
17
17
|
<% end %>
|
|
18
18
|
</ul>
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Cms::ContentType.create!(:name => "BcmsPolling::Poll", :group_name => "Polling")
|
|
@@ -11,13 +11,9 @@ class CreatePolls < ActiveRecord::Migration
|
|
|
11
11
|
t.belongs_to :poll
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
ContentType.create!(:name => "Poll", :group_name => "Polling")
|
|
15
14
|
end
|
|
16
15
|
|
|
17
16
|
def self.down
|
|
18
|
-
ContentType.delete_all(['name = ?', 'Poll'])
|
|
19
|
-
CategoryType.all(:conditions => ['name = ?', 'Poll']).each(&:destroy)
|
|
20
|
-
#If you aren't creating a versioned table, be sure to comment this out.
|
|
21
17
|
drop_table :poll_responses
|
|
22
18
|
drop_table :poll_versions
|
|
23
19
|
drop_table :polls
|
data/lib/bcms_polling.rb
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'browsercms'
|
|
2
|
+
module BcmsPolling
|
|
3
|
+
class Engine < ::Rails::Engine
|
|
4
|
+
isolate_namespace BcmsPolling
|
|
5
|
+
include Cms::Module
|
|
6
|
+
|
|
7
|
+
config.to_prepare do |app|
|
|
8
|
+
Cms::ViewContext.send(:include, BcmsPolling::MainAppPatch)
|
|
9
|
+
Cms::ViewContext.send(:include, BcmsPolling::PollsHelper)
|
|
10
|
+
|
|
11
|
+
::ApplicationHelper.send(:include, BcmsPolling::PollsHelper)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
initializer 'bcms_polling.route_extensions', :after => 'action_dispatch.prepare_dispatcher' do |app|
|
|
15
|
+
ActionDispatch::Routing::Mapper.send :include, BcmsPolling::RouteExtensions
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Patches Core CMS so views can access the main_app routes.
|
|
20
|
+
module MainAppPatch
|
|
21
|
+
|
|
22
|
+
def main_app
|
|
23
|
+
Rails.application.routes.url_helpers
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module BcmsPolling::RouteExtensions
|
|
2
|
+
def mount_bcms_polling
|
|
3
|
+
|
|
4
|
+
# These routes are added to the main routes of the application, rather than under the engine
|
|
5
|
+
# In retrospect, its probably better to put them into the engine to reduce the chance of conflicts.
|
|
6
|
+
get '/polls/:id/results', to:"bcms_polling/polling#results", as: 'poll_results'
|
|
7
|
+
get '/polls/:id/reset', to:"bcms_polling/polling#reset", as: 'poll_reset'
|
|
8
|
+
put '/poll_responses/:id', to:"bcms_polling/polling#update", as: 'poll_response'
|
|
9
|
+
|
|
10
|
+
mount BcmsPolling::Engine => "/bcms_polling"
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'cms/module_installation'
|
|
2
|
+
|
|
3
|
+
class BcmsPolling::InstallGenerator < Cms::ModuleInstallation
|
|
4
|
+
add_migrations_directory_to_source_root __FILE__
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def copy_migrations
|
|
8
|
+
rake 'bcms_polling:install:migrations'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Uncomment to add module specific seed data to a project.
|
|
12
|
+
def add_seed_data_to_project
|
|
13
|
+
copy_file "../bcms_polling.seeds.rb", "db/bcms_polling.seeds.rb"
|
|
14
|
+
append_to_file "db/seeds.rb", "load File.expand_path('../bcms_polling.seeds.rb', __FILE__)\n"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def add_routes
|
|
18
|
+
route 'mount_bcms_polling'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
data/test/test_helper.rb
CHANGED
|
@@ -1,38 +1,15 @@
|
|
|
1
|
+
# Configure Rails Environment
|
|
1
2
|
ENV["RAILS_ENV"] = "test"
|
|
2
|
-
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
|
|
3
|
-
require 'test_help'
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
# in a transaction that's rolled back on completion. This ensures that the
|
|
8
|
-
# test database remains unchanged so your fixtures don't have to be reloaded
|
|
9
|
-
# between every test method. Fewer database queries means faster tests.
|
|
10
|
-
#
|
|
11
|
-
# Read Mike Clark's excellent walkthrough at
|
|
12
|
-
# http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
|
|
13
|
-
#
|
|
14
|
-
# Every Active Record database supports transactions except MyISAM tables
|
|
15
|
-
# in MySQL. Turn off transactional fixtures in this case; however, if you
|
|
16
|
-
# don't care one way or the other, switching from MyISAM to InnoDB tables
|
|
17
|
-
# is recommended.
|
|
18
|
-
#
|
|
19
|
-
# The only drawback to using transactional fixtures is when you actually
|
|
20
|
-
# need to test transactions. Since your test is bracketed by a transaction,
|
|
21
|
-
# any transactions started in your code will be automatically rolled back.
|
|
22
|
-
self.use_transactional_fixtures = true
|
|
4
|
+
require File.expand_path("../dummy/config/environment.rb", __FILE__)
|
|
5
|
+
require "rails/test_help"
|
|
23
6
|
|
|
24
|
-
|
|
25
|
-
# would need people(:david). If you don't want to migrate your existing
|
|
26
|
-
# test cases which use the @david style and don't mind the speed hit (each
|
|
27
|
-
# instantiated fixtures translates to a database query per test method),
|
|
28
|
-
# then set this back to true.
|
|
29
|
-
self.use_instantiated_fixtures = false
|
|
7
|
+
Rails.backtrace_cleaner.remove_silencers!
|
|
30
8
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
# Note: You'll currently still have to declare fixtures explicitly in integration tests
|
|
34
|
-
# -- they do not yet inherit this setting
|
|
35
|
-
fixtures :all
|
|
9
|
+
# Load support files
|
|
10
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
|
36
11
|
|
|
37
|
-
|
|
12
|
+
# Load fixtures from the engine
|
|
13
|
+
if ActiveSupport::TestCase.method_defined?(:fixture_path=)
|
|
14
|
+
ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
|
|
38
15
|
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
module BcmsPolling
|
|
4
|
+
class PollTest < ActiveSupport::TestCase
|
|
5
|
+
|
|
6
|
+
test "should be able to create new block" do
|
|
7
|
+
assert Poll.create!(:question=>"A?")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
test "Should have responses" do
|
|
12
|
+
p = Poll.create!(:question=>"What color?")
|
|
13
|
+
|
|
14
|
+
p.responses << PollResponse.create!(:answer=>"Red")
|
|
15
|
+
p.responses << PollResponse.create!(:answer=>"Blue")
|
|
16
|
+
|
|
17
|
+
found = Poll.find(p.id)
|
|
18
|
+
assert_equal 2, p.responses.size
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
test "Should have responses unpublished" do
|
|
23
|
+
p = Poll.create!(:question=>"What color?")
|
|
24
|
+
|
|
25
|
+
p.responses << PollResponse.create!(:answer=>"Red")
|
|
26
|
+
p.responses << PollResponse.create!(:answer=>"Blue")
|
|
27
|
+
|
|
28
|
+
found = Poll.find(p.id)
|
|
29
|
+
found = found.as_of_draft_version
|
|
30
|
+
assert_equal 2, p.responses.size
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
test "Binding responses as nested attributes for new object" do
|
|
35
|
+
poll = Poll.create!(:question=>"Are you different?")
|
|
36
|
+
poll.update_attributes({ :responses_attributes=>{"0"=>{"answer"=>"Answer 1"}}})
|
|
37
|
+
assert_equal 1, poll.responses.size
|
|
38
|
+
assert_equal 1, PollResponse.count
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
test "Delete a response" do
|
|
43
|
+
poll = Poll.create!(:question=>"Are you different?")
|
|
44
|
+
poll.update_attributes({ :responses_attributes=>{"0"=>{"answer"=>"Answer 1"}}})
|
|
45
|
+
|
|
46
|
+
poll.update_attributes({ :responses_attributes=>{"0"=>{"id"=>PollResponse.first.id, "answer"=>"Answer 1", "_destroy" => "1"}}})
|
|
47
|
+
|
|
48
|
+
assert_equal 0, poll.responses.size
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|