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.
Files changed (44) hide show
  1. data/GPL.txt +674 -0
  2. data/Gemfile +4 -0
  3. data/README.markdown +8 -11
  4. data/{public/bcms/polling → app/assets}/README +0 -0
  5. data/app/assets/javascripts/bcms_polling.js +5 -0
  6. data/{public/bcms/polling → app/assets/javascripts/bcms_polling}/bcms-polling.js +0 -0
  7. data/app/assets/stylesheets/bcms_polling/application.css +13 -0
  8. data/{public/bcms/polling → app/assets/stylesheets/bcms_polling}/bcms-polling.css +0 -0
  9. data/app/controllers/bcms_polling/polling_controller.rb +46 -0
  10. data/app/controllers/bcms_polling/polls_controller.rb +2 -0
  11. data/app/helpers/bcms_polling/application_helper.rb +4 -0
  12. data/app/helpers/{cms → bcms_polling}/polls_helper.rb +1 -1
  13. data/app/models/bcms_polling/poll.rb +38 -0
  14. data/app/models/bcms_polling/poll_response.rb +9 -0
  15. data/app/views/{polling → bcms_polling/polling}/results.html.erb +1 -1
  16. data/app/views/{cms → bcms_polling}/polls/_form.html.erb +1 -2
  17. data/app/views/{cms → bcms_polling}/polls/render.html.erb +3 -3
  18. data/config/routes.rb +3 -0
  19. data/db/bcms_polling.seeds.rb +1 -0
  20. data/db/migrate/20110216195733_create_polls.rb +0 -4
  21. data/db/migrate/20120530182315_v110.rb +8 -0
  22. data/lib/bcms_polling.rb +5 -1
  23. data/lib/bcms_polling/engine.rb +27 -0
  24. data/lib/bcms_polling/route_extensions.rb +13 -0
  25. data/lib/bcms_polling/version.rb +3 -0
  26. data/lib/generators/bcms_polling/install/USAGE +3 -0
  27. data/lib/generators/bcms_polling/install/install_generator.rb +21 -0
  28. data/test/bcms_polling_test.rb +7 -0
  29. data/test/test_helper.rb +9 -32
  30. data/test/unit/models/bcms_polling/poll_response_test.rb +11 -0
  31. data/test/unit/models/bcms_polling/poll_test.rb +52 -0
  32. metadata +82 -66
  33. data/Rakefile +0 -42
  34. data/VERSION +0 -1
  35. data/app/controllers/cms/polls_controller.rb +0 -2
  36. data/app/controllers/polling_controller.rb +0 -44
  37. data/app/models/poll.rb +0 -37
  38. data/app/models/poll_response.rb +0 -4
  39. data/doc/README_FOR_APP +0 -2
  40. data/lib/bcms_polling/routes.rb +0 -12
  41. data/rails/init.rb +0 -5
  42. data/test/performance/browsing_test.rb +0 -9
  43. data/test/unit/models/poll_response_test.rb +0 -9
  44. data/test/unit/models/poll_test.rb +0 -41
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+ gem 'sqlite3'
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
- gem install bcms_polling
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/polling/bcms-polling' %>
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
- updates (and a new version) doesn't get saved. Can fix this by timestamping 'updated_at' but the core CMS should be aware of
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
@@ -0,0 +1,5 @@
1
+ // Manifest file for bcms_polling
2
+ //
3
+ //= require jquery
4
+ //= require jquery.cookie
5
+ //= require_tree .
@@ -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
+ */
@@ -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,2 @@
1
+ class BcmsPolling::PollsController < Cms::ContentBlockController
2
+ end
@@ -0,0 +1,4 @@
1
+ module BcmsPolling
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -1,4 +1,4 @@
1
- module Cms::PollsHelper
1
+ module BcmsPolling::PollsHelper
2
2
  def response_results(response)
3
3
  total = response.poll.total_votes == 0 ? 0 : (response.votes.to_f / response.poll.total_votes.to_f) * 100
4
4
  "#{response.votes} votes (#{sprintf("%.2f", total)}%)"
@@ -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
@@ -0,0 +1,9 @@
1
+ module BcmsPolling
2
+ class PollResponse < ActiveRecord::Base
3
+ belongs_to :poll
4
+ validates_presence_of :answer
5
+
6
+ attr_accessible :answer
7
+
8
+ end
9
+ 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
- <% available_responses = PollResponse.find(:all, :conditions => {:poll_id => f.object.id}) %>
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 'jquery', '/bcms/polling/bcms-polling', 'jquery.cookie' %>
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,3 @@
1
+ BcmsPolling::Engine.routes.draw do
2
+ content_blocks :polls
3
+ end
@@ -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
@@ -0,0 +1,8 @@
1
+ require 'cms/upgrades/v3_5_0'
2
+ class V110 < ActiveRecord::Migration
3
+ def change
4
+ v3_5_0_apply_namespace_to_block("BcmsPolling", "Poll")
5
+ rename_table :poll_responses, :bcms_polling_poll_responses
6
+
7
+ end
8
+ end
data/lib/bcms_polling.rb CHANGED
@@ -1 +1,5 @@
1
- require 'bcms_polling/routes'
1
+ require "bcms_polling/engine"
2
+ require "bcms_polling/route_extensions"
3
+
4
+ module BcmsPolling
5
+ end
@@ -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,3 @@
1
+ module BcmsPolling
2
+ VERSION = "1.1.0"
3
+ end
@@ -0,0 +1,3 @@
1
+ Installs bcms_polling into a project. Typically invoked indirectly via:
2
+
3
+ rails generate cms:install bcms_polling
@@ -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
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class BcmsPollingTest < ActiveSupport::TestCase
4
+ test "truth" do
5
+ assert_kind_of Module, BcmsPolling
6
+ end
7
+ 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
- class ActiveSupport::TestCase
6
- # Transactional fixtures accelerate your tests by wrapping each test method
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
- # Instantiated fixtures are slow, but give you @david where otherwise you
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
- # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
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
- # Add more helper methods to be used by all tests here...
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,11 @@
1
+ require 'test_helper'
2
+
3
+ module BcmsPolling
4
+ class PollResponseTest < ActiveSupport::TestCase
5
+
6
+ test "should be able to create new block" do
7
+ assert PollResponse.create!(:answer=>"Non-blank")
8
+ end
9
+
10
+ end
11
+ 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