bcms_polling 1.0.3 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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