refinerycms-polls 0.0.2.dev → 0.0.4.dev

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 (32) hide show
  1. data/CHANGELOG.md +23 -0
  2. data/Gemfile +3 -2
  3. data/README.md +7 -3
  4. data/Rakefile +2 -0
  5. data/app/assets/javascripts/refinery/polls/poll.js +2 -0
  6. data/app/assets/javascripts/refinery/polls/poll_form.js.coffee +6 -0
  7. data/app/assets/stylesheets/refinery/polls/polls.css.scss +7 -0
  8. data/app/controllers/refinery/polls/admin/answers_controller.rb +16 -3
  9. data/app/controllers/refinery/polls/questions_controller.rb +19 -16
  10. data/app/models/refinery/polls/answer.rb +15 -1
  11. data/app/models/refinery/polls/question.rb +22 -15
  12. data/app/models/refinery/polls/vote.rb +5 -3
  13. data/app/views/refinery/polls/questions/_answers_form.html.erb +4 -1
  14. data/app/views/refinery/polls/questions/_poll.html.erb +1 -1
  15. data/app/views/refinery/polls/questions/index.html.erb +4 -3
  16. data/app/views/refinery/polls/questions/show.html.erb +10 -19
  17. data/config/locales/en.yml +19 -19
  18. data/lib/generators/refinery/polls_generator.rb +5 -1
  19. data/lib/generators/refinery/templates/app/assets/stylesheets/refinery/polls/poll.css.scss +28 -0
  20. data/lib/refinery/polls/configuration.rb +1 -0
  21. data/lib/refinery/polls/engine.rb +1 -1
  22. data/lib/refinery/polls/version.rb +1 -1
  23. data/spec/models/refinery/polls/answer_spec.rb +17 -0
  24. data/spec/models/refinery/polls/question_spec.rb +31 -1
  25. data/spec/models/refinery/polls/vote_spec.rb +35 -0
  26. data/spec/requests/refinery/polls/admin/answers_spec.rb +114 -0
  27. data/spec/requests/refinery/polls/admin/questions_spec.rb +1 -1
  28. data/spec/requests/refinery/polls/questions_spec.rb +138 -0
  29. data/spec/spec_helper.rb +1 -0
  30. data/spec/support/factories/refinery/polls.rb +12 -2
  31. metadata +17 -2
  32. data/app/assets/javascripts/refinery/polls/poll_form.js +0 -8
data/CHANGELOG.md ADDED
@@ -0,0 +1,23 @@
1
+ ## v0.0.1.dev
2
+
3
+ * Create polls in refinerycms admin.
4
+ * Add Answers to poll.
5
+ * Render polls in refinerycms.
6
+
7
+ ## v0.0.2.dev
8
+
9
+ * Config vote interval in config/refinery/poll initializer.
10
+
11
+ ## v0.0.3.dev
12
+
13
+ * Add css file app/assets/stylesheets/refinery/polls/poll.css.scss to override poll styles.
14
+
15
+ ## v0.0.4.dev
16
+ * Poll checkbox as labels to better user experience.
17
+ * Translate js to coffee script.
18
+ * Fix jquery library loads from extension and not from cms.
19
+ * Fix poll form double submit if user does dobel click.
20
+ * Fix howto finds votes for question with already_voted?(remote_ip) in Question model.
21
+ * Fix tests for all models/controllers
22
+ * Add tests for question controller
23
+ * Add documentation
data/Gemfile CHANGED
@@ -2,9 +2,9 @@ source "http://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'refinerycms', '~> 2.0.0', :git => 'git://github.com/resolve/refinerycms.git'
5
+ gem 'refinerycms', '~> 2.0.0', :git => 'git://github.com/resolve/refinerycms.git', :branch => '2-0-stable'
6
6
  gem 'refinerycms-i18n', :git => 'git://github.com/parndt/refinerycms-i18n.git'
7
- gem 'refinerycms-settings', :git => 'git://github.com/parndt/refinerycms-settings.git'
7
+ gem 'refinerycms-settings', :git => 'git://github.com/parndt/refinerycms-settings.git', :branch => '2-0-stable'
8
8
 
9
9
  # Refinery/rails should pull in the proper versions of these
10
10
  group :assets do
@@ -19,6 +19,7 @@ group :development, :test do
19
19
  gem 'refinerycms-testing', '~> 2.0.0'
20
20
  gem 'factory_girl_rails'
21
21
  gem 'generator_spec'
22
+ gem 'activesupport'
22
23
 
23
24
  require 'rbconfig'
24
25
 
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  Include the latest [gem](http://rubygems.org/gems/refinerycms-polls) into your Refinery CMS application's Gemfile:
6
6
 
7
- gem 'refinerycms-polls', '~> 0.0.1.dev'
7
+ gem 'refinerycms-polls', '~> 0.0.4.dev'
8
8
 
9
9
  Then type the following at command line inside your Refinery CMS application's root directory:
10
10
 
@@ -60,11 +60,15 @@ In summary you can:
60
60
  * Set when starts and ends your polls.
61
61
  * Show results for your polls.
62
62
  * Set votes for anonymous users by IP addres
63
- * Set aa duration period to vote. (if a guest vote it will need to wait x time to vote again)
63
+ * Set duration period to vote. (if a guest vote it will need to wait X time to vote again)
64
64
 
65
65
  ## Todo
66
66
 
67
67
  * Vote tracking by cookies.
68
68
  * Documentation
69
69
  * Tests
70
- * Wiki
70
+ * Wiki
71
+
72
+
73
+ ## License
74
+ RefineryCMS Polls extension is released under the MIT license and is copyright (c) 2012 Agustin Viñao
data/Rakefile CHANGED
@@ -18,3 +18,5 @@ Refinery::Testing::Railtie.load_dummy_tasks(ENGINE_PATH)
18
18
 
19
19
  load File.expand_path('../tasks/testing.rake', __FILE__)
20
20
  load File.expand_path('../tasks/rspec.rake', __FILE__)
21
+
22
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,2 @@
1
+ //= require jquery
2
+ //= require jquery_ujs
@@ -0,0 +1,6 @@
1
+ do_vote = (element) ->
2
+ $(element).parents().find('form').submit()
3
+ jQuery ->
4
+ $("input[type=radio][name=answer_id]").click ->
5
+ do_vote(this)
6
+ $(this).attr "disabled", true
@@ -0,0 +1,7 @@
1
+ .refinery-polls{
2
+ ul{
3
+ list-style-type: none;
4
+ padding: 10px;
5
+ margin: 0;
6
+ }
7
+ }
@@ -5,7 +5,7 @@ module Refinery
5
5
 
6
6
  crudify :'refinery/polls/answer', :title_attribute => 'title', :xhr_paging => true
7
7
  before_filter :find_question
8
- before_filter :find_answer, :only => [:edit, :update]
8
+ before_filter :find_answer, :only => [:edit, :update, :destroy]
9
9
 
10
10
  def index
11
11
  paginate_all_answers
@@ -16,18 +16,19 @@ module Refinery
16
16
 
17
17
  def create
18
18
  if (@answer = ::Refinery::Polls::Answer.create({:question_id => @question.id}.merge(params[:answer]))).valid?
19
- flash.now[:notice] = "#{@answer.title} was successfully created."
19
+ flash.now[:notice] = "'#{@answer.title}' was successfully added."
20
20
  self.index
21
21
  @dialog_successful = true
22
22
  render :index
23
23
  else
24
+ flash.now[:notice] = "There were problems"
24
25
  render :action => 'new'
25
26
  end
26
27
  end
27
28
 
28
29
  def update
29
30
  if @answer.update_attributes({:question_id => @question.id}.merge(params[:answer]))
30
- flash.now[:notice] = "#{@answer.title} was successfully updated."
31
+ flash.now[:notice] = "'#{@answer.title}' was successfully updated."
31
32
  self.index
32
33
  @dialog_successful = true
33
34
  render :index
@@ -36,6 +37,18 @@ module Refinery
36
37
  end
37
38
  end
38
39
 
40
+ def destroy
41
+ answer_title = @answer.title
42
+ if @answer.destroy
43
+ flash.now[:notice] = "'#{answer_title}' was successfully removed."
44
+ @dialog_successful = true
45
+ else
46
+ flash.now[:notice] = "There were problems"
47
+ end
48
+ self.index
49
+ render :index
50
+ end
51
+
39
52
  private
40
53
  def find_answer
41
54
  @answer = ::Refinery::Polls::Answer.find_by_slug_or_id(params[:id])
@@ -2,11 +2,11 @@ module Refinery
2
2
  module Polls
3
3
  class QuestionsController < ::ApplicationController
4
4
 
5
- before_filter :find_all_questions, :only => [:index]
5
+ before_filter :find_all_questions, :only => [:index, :show]
6
6
  before_filter :find_page, :except => [:submit]
7
- before_filter :find_vote, :only => [:show, :create]
8
- before_filter :find_answer, :only => [:submit]
9
7
  before_filter :find_question, :only => [:submit, :show]
8
+ before_filter :find_answer, :only => [:submit]
9
+ before_filter :find_vote, :only => [:show, :create, :submit]
10
10
  respond_to :html, :js, :json
11
11
  def index
12
12
  # you can use meta fields from your model instead (e.g. browser_title)
@@ -20,21 +20,24 @@ module Refinery
20
20
  present(@page)
21
21
  end
22
22
 
23
+
24
+ # Handle votes from questions
25
+ #
26
+ # @param [id] Id of question voted
27
+ # @param [question_id] Value of the answer selected by guest
28
+ # @return [String] Question results
23
29
  def submit
24
- @vote = nil
25
- if @answer.nil?
26
- flash[:notice] = t(".no_answer_selected")
27
- else
28
- unless @vote
29
- @answer.votes_count += 1
30
- @answer.save
31
- @vote = ::Refinery::Polls::Vote.vote_by_ip(@question, @answer, request.remote_ip)
32
- end
33
- respond_to do |format|
34
- format.js
35
- format.html
30
+ if @vote.nil?
31
+ if @answer.nil?
32
+ flash[:notice] = t(".no_answer_selected")
33
+ else
34
+ @vote = ::Refinery::Polls::Vote.vote_by_ip(@answer, request.remote_ip)
36
35
  end
37
36
  end
37
+ respond_to do |format|
38
+ format.js
39
+ format.html
40
+ end
38
41
  end
39
42
 
40
43
  protected
@@ -55,7 +58,7 @@ module Refinery
55
58
  end
56
59
 
57
60
  def find_vote
58
- @vote = ::Refinery::Polls::Vote.where("ip=? AND created_at > ?", request.remote_ip, Time.now - Refinery::Polls.vote_duration).first
61
+ @vote = ::Refinery::Polls::Vote.get_vote(@question, request.remote_ip)
59
62
  end
60
63
  end
61
64
  end
@@ -8,7 +8,7 @@ module Refinery
8
8
 
9
9
  acts_as_indexed :fields => [:title]
10
10
 
11
- validates :title, :presence => true, :uniqueness => true
11
+ validates :title, :presence => true, :uniqueness => { :scope => :question_id}
12
12
 
13
13
  attr_accessible :title, :question_id, :position
14
14
  attr_accessor :locale
@@ -22,6 +22,20 @@ module Refinery
22
22
  attr_accessible :locale
23
23
  end
24
24
 
25
+ # Get a string to represent a dom id
26
+ #
27
+ # @return [String] Returns the dom id representation for the current object
28
+ def dom_id
29
+ "answer_#{id}"
30
+ end
31
+
32
+ # Get an array of title and votes_count
33
+ #
34
+ # @return [Array] Returns an array of title and votes_count
35
+ def data_result
36
+ [title, votes_count]
37
+ end
38
+
25
39
  def self.translated
26
40
  with_translations(::Globalize.locale)
27
41
  end
@@ -26,17 +26,33 @@ module Refinery
26
26
 
27
27
  has_many :answers, :class_name => '::Refinery::Polls::Answer'
28
28
 
29
+ # Get all actives questions by start_date and end_date
30
+ #
31
+ # @return [Array] Array of Refinery::Polls::Question
29
32
  def self.actives
30
33
  where("start_date <= ? and end_date >= ?", Date.today, Date.today)
31
34
  end
32
35
 
36
+ # Check if we have a vote by ip address
37
+ #
38
+ # @param [String] A string to represent an IP address
39
+ # @return [::Refinery::Polls::Vote, nil] Returns the vote finded or nil
40
+ def already_voted?(remote_ip)
41
+ answers.joins(:votes).where(Refinery::Polls::Vote.table_name.to_sym => {:created_at => Time.now.utc - Refinery::Polls.vote_duration, :ip => remote_ip}).first
42
+ end
43
+
44
+ # Get al data for answers and total votes count
45
+ #
46
+ # @return [Array] Returns an array with [[title,votes_count]..[title,votes_count]], total_votes]
33
47
  def answers_with_data
34
- results, votes_total = [], 0
35
- answers.each do |answer|
36
- results << [answer.title, answer.votes_count]
37
- votes_total += answer.votes_count
38
- end
39
- return results, votes_total
48
+ return answers.map(&:data_result), total_votes
49
+ end
50
+
51
+ # Calculate the total votes for current question
52
+ #
53
+ # @return [Integer] Returns the value of total votes
54
+ def total_votes
55
+ answers.sum(&:votes_count)
40
56
  end
41
57
 
42
58
  class << self
@@ -48,15 +64,6 @@ module Refinery
48
64
  end
49
65
  end
50
66
  end
51
- # def self.active_poll(user_id)
52
- # users_polls = UsersPoll.find_all_by_user_id(user_id, :select => :poll_id)
53
- # polls = users_polls.count > 0 ? Poll.active.find(:all, :conditions => ["id NOT IN (?)", users_polls.collect {|up| up.poll_id } ]) : Poll.active
54
- # polls.count > 0 ? polls.first : nil
55
- # end
56
-
57
-
58
- # acceso a variables connfiguradas
59
- #self.per_page = Refinery::Blog.posts_per_page
60
67
  end
61
68
  end
62
69
  end
@@ -5,20 +5,22 @@ module Refinery
5
5
  acts_as_indexed :fields => [:question_id, :answer_id, :ip]
6
6
 
7
7
  belongs_to :question, :class_name => '::Refinery::Polls::Question'
8
- belongs_to :answer, :class_name => '::Refinery::Polls::Answer'
8
+ belongs_to :answer, :class_name => '::Refinery::Polls::Answer', :counter_cache => true
9
9
 
10
10
  attr_accessible :question_id, :answer_id, :ip
11
11
 
12
12
  # Create Vote for Question, Answer and IP
13
+ #
13
14
  # @param [::Refinery::Polls::Question] Question object
14
15
  # @parama [::Refinery::Polls::Answer] Answer object
15
16
  # @return [::Refinery::Polls::Vote] Vote object created
16
17
 
17
- def self.vote_by_ip(question, answer, ip)
18
- self.create(:answer_id => answer.id, :question_id => question.id, :ip => ip)
18
+ def self.vote_by_ip(answer, ip)
19
+ self.create(:answer_id => answer.id, :question_id => answer.question.id, :ip => ip)
19
20
  end
20
21
 
21
22
  # Find vote for Question by IP
23
+ #
22
24
  # @param [::Refinery::Polls::Question] Question object
23
25
  # @parama [Request] Request object to use remote_ip
24
26
  # @return [::Refinery::Polls::Vote] Vote object created
@@ -4,7 +4,10 @@
4
4
  :remote => true,
5
5
  :html => {:id => "reinerycms-poll-#{question.slug}"} do |f| %>
6
6
  <% question.answers.each do |answer| %>
7
- <li><%= radio_button_tag("answer_id", answer.id, false) %> <%= answer.title %></li>
7
+ <%= content_tag_for :li, answer do %>
8
+ <%= radio_button_tag("answer_id", answer.id, false, id: answer.dom_id) %>
9
+ <%= label_tag answer.dom_id, answer.title %>
10
+ <% end %>
8
11
  <% end %>
9
12
  <% end %>
10
13
  </ul>
@@ -6,5 +6,5 @@
6
6
  <%= (vote = ::Refinery::Polls::Vote.get_vote(question, request.remote_ip)).nil? ? render(:partial => 'refinery/polls/questions/answers_form', :locals => {:question => question}) : render(:partial => 'refinery/polls/questions/results', :locals => {:question => question, :vote => vote}) %>
7
7
  <% end %>
8
8
  </div>
9
- <% content_for :javascripts, javascript_include_tag('application', 'refinery/polls/poll_form') %>
9
+ <% content_for :javascripts, javascript_include_tag('refinery/polls/poll', 'refinery/polls/poll_form') %>
10
10
  <% end %>
@@ -1,9 +1,10 @@
1
1
  <% content_for :body_content_left do %>
2
+ <h4>Polls</h4>
2
3
  <ul id="questions">
3
- <% @questions.each do |poll| %>
4
- <li>
4
+ <% @questions.each do |question| %>
5
+ <%= content_tag_for :li, question do %>
5
6
  <%= link_to question.title, refinery.polls_question_path(question) %>
6
- </li>
7
+ <% end %>
7
8
  <% end %>
8
9
  </ul>
9
10
  <% end %>
@@ -1,33 +1,24 @@
1
+ <% content_for :stylesheets, stylesheet_link_tag('refinery/polls/polls') %>
1
2
  <% content_for :body_content_title do %>
2
3
  <%= @question.title %>
3
4
  <% end %>
4
5
 
5
6
  <% content_for :body_content_left do %>
6
- <section>
7
- <h1>Title</h1>
8
- <p>
9
- <%=raw @question.title %>
10
- </p>
11
- </section>
12
- <section>
13
- <h1>Start Date</h1>
14
- <p>
15
- <%=raw @question.start_date %>
16
- </p>
17
- </section>
18
- <section>
19
- <h1>End Date</h1>
20
- <p>
21
- <%=raw @question.end_date %>
22
- </p>
23
- </section>
7
+ <div class="refinery-polls">
8
+ <ul>
9
+ <li>Title: <%=raw @question.title %></li>
10
+ <li>Start: <%=l(@question.start_date, :format => :short) %></li>
11
+ <li>End: <%=l(@question.end_date, :format => :short) %></li>
12
+ <li>Votes: <%=pluralize(@question.total_votes, "vote") %></li>
13
+ <ul>
14
+ </div>
24
15
  <% end %>
25
16
 
26
17
  <% content_for :body_content_right do %>
27
18
  <aside>
28
19
  <h2><%= t('.other') %></h2>
29
20
  <ul id="questions">
30
- <% @questions.each do |poll| %>
21
+ <% @questions.each do |question| %>
31
22
  <li>
32
23
  <%= link_to question.title, refinery.polls_question_path(question) %>
33
24
  </li>
@@ -2,39 +2,39 @@ en:
2
2
  refinery:
3
3
  plugins:
4
4
  polls:
5
- title: Polls
5
+ title: Questions
6
6
  polls:
7
7
  admin:
8
8
  questions:
9
9
  actions:
10
- create_new: Add New Poll
11
- reorder: Reorder Polls
12
- reorder_done: Done Reordering Polls
10
+ create_new: Add New Question
11
+ reorder: Reorder Questions
12
+ reorder_done: Done Reordering Questions
13
13
  records:
14
- title: Polls
14
+ title: Questions
15
15
  sorry_no_results: Sorry! There are no results found.
16
- no_items_yet: There are no Polls yet. Click "Add New Poll" to add your first poll.
16
+ no_items_yet: There are no Questions yet. Click "Add New Question" to add your first question.
17
17
  question:
18
- view_live_html: View this poll live <br/><em>(opens in a new window)</em>
19
- edit: Edit this poll
20
- delete: Remove this poll forever
21
- manage_answers: View answers for this poll
18
+ view_live_html: View this question live <br/><em>(opens in a new window)</em>
19
+ edit: Edit this question
20
+ delete: Remove this question forever
21
+ manage_answers: View answers for this question
22
22
  answers:
23
23
  actions:
24
- create_new: Add New Poll Answer
25
- reorder: Reorder Poll Answers
26
- reorder_done: Done Reordering Poll Answers
24
+ create_new: Add New Question Answer
25
+ reorder: Reorder Question Answers
26
+ reorder_done: Done Reordering Question Answers
27
27
  records:
28
- title: Poll Answers
28
+ title: Question Answers
29
29
  sorry_no_results: Sorry! There are no results found.
30
- no_items_yet: There are no Poll Answers yet. Click "Add New Poll Answer" to add your first poll answer.
30
+ no_items_yet: There are no Question Answers yet. Click "Add New Question Answer" to add your first question answer.
31
31
  answer:
32
- view_live_html: View this poll answer live <br/><em>(opens in a new window)</em>
33
- edit: Edit this poll answer
34
- delete: Remove this poll answer forever
32
+ view_live_html: View this question answer live <br/><em>(opens in a new window)</em>
33
+ edit: Edit this question answer
34
+ delete: Remove this question answer forever
35
35
  questions:
36
36
  show:
37
- other: Other Polls
37
+ other: Other Questions
38
38
  activerecord:
39
39
  attributes:
40
40
  'refinery/polls/question':
@@ -10,7 +10,11 @@ module Refinery
10
10
  def generate_poll_initializer
11
11
  template "config/initializers/refinery/poll.rb.erb", File.join(destination_root, "config", "initializers", "refinery", "poll.rb")
12
12
  end
13
-
13
+
14
+ def generate_styles_to_assets
15
+ template "app/assets/stylesheets/refinery/polls/poll.css.scss", File.join(destination_root, "app", "assets", "stylesheets", "refinery", "polls", "poll.css.scss")
16
+ end
17
+
14
18
  def append_load_seed_data
15
19
  create_file 'db/seeds.rb' unless File.exists?(File.join(destination_root, 'db', 'seeds.rb'))
16
20
  append_file 'db/seeds.rb', :verbose => true do
@@ -0,0 +1,28 @@
1
+ /* These are all classes used by poll to render */
2
+ /*
3
+ .reinerycms-polls-form h3{
4
+ padding:5px;
5
+ }
6
+ .reinerycms-polls-form ul{
7
+ list-style-type: none;
8
+ padding: 10px;
9
+ margin: 0;
10
+ }
11
+ .reinerycms-polls-pollbar {
12
+ margin: 1px;
13
+ font-size: 13px;
14
+ line-height: 15px;
15
+ height: 15px;
16
+ background-image: image_url('refinery/polls/pollbg.gif');
17
+ border: 1px solid #ffffff;
18
+ }
19
+ .reinerycms-polls-pollbar IMG {
20
+ display: inline;
21
+ border: 0px;
22
+ padding: 0px;
23
+ margin: 0px;
24
+ }
25
+ .reinerycms-polls-results{
26
+ border:1px solid #CCC;
27
+ }
28
+ */
@@ -1,3 +1,4 @@
1
+ require 'active_support/core_ext/numeric/time'
1
2
  module Refinery
2
3
  module Polls
3
4
  include ActiveSupport::Configurable
@@ -12,7 +12,7 @@ module Refinery
12
12
  plugin.url = proc { Refinery::Core::Engine.routes.url_helpers.polls_admin_questions_path }
13
13
  plugin.pathname = root
14
14
  plugin.activity = {
15
- :class_name => :'refinery/polls/poll'
15
+ :class_name => :'refinery/polls/question'
16
16
  }
17
17
 
18
18
  end
@@ -3,7 +3,7 @@ module Refinery
3
3
  class Version
4
4
  @major = 0
5
5
  @minor = 0
6
- @tiny = 2
6
+ @tiny = 4
7
7
  @build = 'dev'
8
8
 
9
9
  class << self
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ module Refinery
4
+ module Polls
5
+ describe Answer do
6
+ describe "validations" do
7
+ subject do
8
+ FactoryGirl.create(:answer, :title => "Answer 1")
9
+ end
10
+
11
+ it { should be_valid }
12
+ its(:errors) { should be_empty }
13
+ its(:title) { should == "Answer 1" }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  module Refinery
4
4
  module Polls
5
- describe quesiton do
5
+ describe Question do
6
6
  describe "validations" do
7
7
  subject do
8
8
  FactoryGirl.create(:question,
@@ -13,6 +13,36 @@ module Refinery
13
13
  its(:errors) { should be_empty }
14
14
  its(:title) { should == "Refinery CMS" }
15
15
  end
16
+ describe "class methods" do
17
+ before do
18
+ Factory.create(:question)
19
+ Factory.create(:question,
20
+ start_date: Time.now+2.days,
21
+ end_date: Time.now+10.days)
22
+ end
23
+ subject { Question.first }
24
+ it "should get one question active" do
25
+ Question.actives.should == [subject]
26
+ end
27
+ end
28
+ describe "instance methods" do
29
+ before do
30
+ question = Factory.create(:question)
31
+ @times = 3
32
+ @answer = Factory.create(:answer, question: question)
33
+ (@times-1).times{ Factory.create(:answer, question: question) }
34
+ @ip = "192.168.1.1"
35
+ @vote = Factory.create(:vote, answer: @answer, ip: @ip)
36
+ end
37
+ subject{ Question.first }
38
+ it { subject.answers.size == @times }
39
+ it { subject.total_votes.should == subject.answers.sum(&:votes_count) }
40
+ it "should get answers data for view" do
41
+ subject.answers_with_data.should == [subject.answers.collect{|a| [a.title, a.votes_count]}, subject.total_votes]
42
+ end
43
+ it { subject.already_voted?("127.0.0.1").should be_false }
44
+ it { subject.already_voted?("192.168.1.1").should be_nil }
45
+ end
16
46
  end
17
47
  end
18
48
  end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ module Refinery
4
+ module Polls
5
+ describe Vote do
6
+ describe "validations" do
7
+ subject do
8
+ FactoryGirl.create(:vote)
9
+ end
10
+
11
+ it { should be_valid }
12
+ its(:errors) { should be_empty }
13
+ end
14
+ describe "class methods" do
15
+ before do
16
+ question = Factory.create(:question)
17
+ @answer = Factory.create(:answer, question: question)
18
+ @vote = Factory.create(:vote, answer: @answer)
19
+ @ip = "192.168.1.1"
20
+ end
21
+ it "should create a vote by ip for an Answer" do
22
+ vote = Vote.vote_by_ip(@answer, @ip)
23
+ vote.should be_valid
24
+ vote.ip.should == @ip
25
+ end
26
+ it "should get a vote by ip for a Question" do
27
+ Vote.get_vote(@question, @ip) == @vote
28
+ end
29
+ end
30
+ describe "instance methods" do
31
+ #nothing
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,114 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ describe Refinery do
5
+ describe "Polls" do
6
+ describe "Admin" do
7
+ describe "Answers" do
8
+ login_refinery_user
9
+
10
+ describe "answers list" do
11
+ before(:each) do
12
+ @question = FactoryGirl.create(:question)
13
+ Factory.create(:answer, question: @question, title: "Option_1")
14
+ Factory.create(:answer, question: @question, title: "Option_2")
15
+ end
16
+
17
+ it "shows two items" do
18
+ visit refinery.polls_admin_question_answers_path(@question)
19
+ page.should have_content("Option_1")
20
+ page.should have_content("Option_2")
21
+ end
22
+ end
23
+
24
+ describe "create" do
25
+ before(:each) do
26
+ @question = FactoryGirl.create(:question)
27
+ visit refinery.polls_admin_question_answers_path(@question)
28
+
29
+ click_link "Add New Question Answer"
30
+ end
31
+
32
+ context "valid data" do
33
+ it "should succeed" do
34
+ fill_in "Title", :with => "This is a test of the first string field"
35
+ click_button "Save"
36
+
37
+ page.should have_content("'This is a test of the first string field' was successfully added.")
38
+ Refinery::Polls::Answer.count.should == 1
39
+ end
40
+ end
41
+
42
+ # we can't test this because admin/answers/_form.html creates wrong url helper for nested models
43
+ # context "invalid data" do
44
+ # it "should fail" do
45
+ # click_button "Save"
46
+ #
47
+ # page.should have_content("Title can't be blank")
48
+ # Refinery::Polls::Answer.count.should == 0
49
+ # end
50
+ # end
51
+
52
+ # we can't test this because admin/answers/_form.html creates wrong url helper for nested models
53
+ # context "duplicate" do
54
+ # before(:each) do
55
+ # @question = FactoryGirl.create(:question, :title => "UniqueTitle")
56
+ # Factory.create(:answer, question: @question, :title => "Option repeated")
57
+ # end
58
+ #
59
+ # it "should fail" do
60
+ # visit refinery.polls_admin_question_answers_path(@question)
61
+ #
62
+ # click_link "Add New Question Answer"
63
+ #
64
+ # fill_in "Title", :with => "Option repeated"
65
+ # click_button "Save"
66
+ #
67
+ # page.should have_content("There were problems")
68
+ # Refinery::Polls::Answer.count.should == 1
69
+ # end
70
+ # end
71
+
72
+ end
73
+
74
+ describe "edit" do
75
+ before(:each) do
76
+ @question = FactoryGirl.create(:question, :title => "A title")
77
+ Factory.create(:answer, question: @question)
78
+ end
79
+
80
+ it "should succeed" do
81
+ visit refinery.polls_admin_question_answers_path(@question)
82
+
83
+ within ".actions" do
84
+ click_link "Edit this question answer"
85
+ end
86
+
87
+ fill_in "Title", :with => "A different title"
88
+ click_button "Save"
89
+
90
+ page.should have_content("'A different title' was successfully updated.")
91
+ page.should have_no_content("A title")
92
+ end
93
+ end
94
+
95
+ describe "destroy" do
96
+ before(:each) do
97
+ @question = FactoryGirl.create(:question, :title => "A title")
98
+ Factory.create(:answer, question: @question, title: "UniqueTitleOne")
99
+ end
100
+
101
+ it "should succeed" do
102
+ visit refinery.polls_admin_question_answers_path(@question)
103
+
104
+ click_link "Remove this question answer forever"
105
+
106
+ page.should have_content("'UniqueTitleOne' was successfully removed.")
107
+ Refinery::Polls::Answer.count.should == 0
108
+ end
109
+ end
110
+
111
+ end
112
+ end
113
+ end
114
+ end
@@ -4,7 +4,7 @@ require "spec_helper"
4
4
  describe Refinery do
5
5
  describe "Polls" do
6
6
  describe "Admin" do
7
- describe "questions" do
7
+ describe "Questions" do
8
8
  login_refinery_user
9
9
 
10
10
  describe "questions list" do
@@ -0,0 +1,138 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ describe Refinery do
5
+ describe "Polls" do
6
+ describe "Questions" do
7
+ login_refinery_user
8
+
9
+ describe "questions index" do
10
+ before(:each) do
11
+ FactoryGirl.create(:question, :title => "UniqueTitleTwo")
12
+ FactoryGirl.create(:question, :title => "UniqueTitleOne")
13
+ end
14
+
15
+ it "shows two items" do
16
+ visit refinery.polls_questions_path
17
+ page.should have_content("UniqueTitleOne")
18
+ page.should have_content("UniqueTitleTwo")
19
+ end
20
+ end
21
+ describe "question show" do
22
+ before(:each) do
23
+ @question = FactoryGirl.create(:question, :title => "UniqueTitleOne")
24
+ end
25
+ it "shows question" do
26
+ visit refinery.polls_question_path(@question)
27
+ page.should have_content(@question.title)
28
+ page.should have_content(I18n.l(@question.start_date, :format => :short))
29
+ page.should have_content(I18n.l(@question.end_date, :format => :short))
30
+ page.should have_content(@question.total_votes)
31
+ end
32
+ end
33
+
34
+ describe "question answer submit" do
35
+ before(:each) do
36
+ @question = FactoryGirl.create(:question, title: "submite_test")
37
+ @answers = []
38
+ 3.times do |value|
39
+ @answers << Factory.create(:answer, question: @question, title: "Option #{value}")
40
+ end
41
+ ActionDispatch::Request.any_instance.stub(:remote_ip).and_return("192.168.0.1")
42
+
43
+ end
44
+ it "should save vote", :js => true do
45
+ post refinery.submit_polls_question_path(@question), :answer_id => @answers.first.id, :format=> 'js'
46
+ Refinery::Polls::Vote.count.should == 1
47
+ @answers.first.votes_count == 1
48
+ @question.total_votes.should == 1
49
+ end
50
+ it "should not save second vote from same ip", :js => true do
51
+ Factory.create(:vote, question: @question, answer: @answers.first, ip: "192.168.0.1")
52
+ #second call to submit
53
+ post refinery.submit_polls_question_path(@question), :answer_id => @answers.first.id, :format=> 'js'
54
+ Refinery::Polls::Vote.count.should == 1
55
+ @answers.first.votes_count == 1
56
+ @question.total_votes.should == 1
57
+ end
58
+
59
+ end
60
+ #
61
+ # describe "create" do
62
+ # before(:each) do
63
+ # visit refinery.polls_admin_questions_path
64
+ #
65
+ # click_link "Add New Question"
66
+ # end
67
+ #
68
+ # context "valid data" do
69
+ # it "should succeed" do
70
+ # fill_in "Title", :with => "This is a test of the first string field"
71
+ # click_button "Save"
72
+ #
73
+ # page.should have_content("'This is a test of the first string field' was successfully added.")
74
+ # Refinery::Polls::Question.count.should == 1
75
+ # end
76
+ # end
77
+ #
78
+ # context "invalid data" do
79
+ # it "should fail" do
80
+ # click_button "Save"
81
+ #
82
+ # page.should have_content("Title can't be blank")
83
+ # Refinery::Polls::Question.count.should == 0
84
+ # end
85
+ # end
86
+ #
87
+ # context "duplicate" do
88
+ # before(:each) { FactoryGirl.create(:question, :title => "UniqueTitle") }
89
+ #
90
+ # it "should fail" do
91
+ # visit refinery.polls_admin_questions_path
92
+ #
93
+ # click_link "Add New Question"
94
+ #
95
+ # fill_in "Title", :with => "UniqueTitle"
96
+ # click_button "Save"
97
+ #
98
+ # page.should have_content("There were problems")
99
+ # Refinery::Polls::Question.count.should == 1
100
+ # end
101
+ # end
102
+ #
103
+ # end
104
+ #
105
+ # describe "edit" do
106
+ # before(:each) { FactoryGirl.create(:question, :title => "A title") }
107
+ #
108
+ # it "should succeed" do
109
+ # visit refinery.polls_admin_questions_path
110
+ #
111
+ # within ".actions" do
112
+ # click_link "Edit this question"
113
+ # end
114
+ #
115
+ # fill_in "Title", :with => "A different title"
116
+ # click_button "Save"
117
+ #
118
+ # page.should have_content("'A different title' was successfully updated.")
119
+ # page.should have_no_content("A title")
120
+ # end
121
+ # end
122
+ #
123
+ # describe "destroy" do
124
+ # before(:each) { FactoryGirl.create(:question, :title => "UniqueTitleOne") }
125
+ #
126
+ # it "should succeed" do
127
+ # visit refinery.polls_admin_questions_path
128
+ #
129
+ # click_link "Remove this question forever"
130
+ #
131
+ # page.should have_content("'UniqueTitleOne' was successfully removed.")
132
+ # Refinery::Polls::Question.count.should == 0
133
+ # end
134
+ # end
135
+
136
+ end
137
+ end
138
+ end
data/spec/spec_helper.rb CHANGED
@@ -6,6 +6,7 @@ def setup_environment
6
6
 
7
7
  require 'rspec/rails'
8
8
  require 'capybara/rspec'
9
+ require 'capybara/rails'
9
10
 
10
11
  Rails.backtrace_cleaner.remove_silencers!
11
12
 
@@ -1,7 +1,17 @@
1
-
2
1
  FactoryGirl.define do
3
- factory :question, :class => Refinery::Polls::Question do
2
+ factory :question, :class => Refinery::Polls::Question do
4
3
  sequence(:title) { |n| "refinery#{n}" }
4
+ start_date Time.now-10.days
5
+ end_date Time.now+10.days
6
+ end
7
+ factory :answer, :class => Refinery::Polls::Answer do
8
+ sequence(:title) { |n| "refinery-answer#{n}" }
9
+ association :question, :factory => :question
10
+ end
11
+ factory :vote, :class => Refinery::Polls::Vote do
12
+ association :question, :factory => :question
13
+ association :answer, :factory => :answer
14
+ sequence(:ip) { |n| "127.0.1.#{n}" }
5
15
  end
6
16
  end
7
17
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: refinerycms-polls
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2.dev
4
+ version: 0.0.4.dev
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -66,13 +66,16 @@ extensions: []
66
66
  extra_rdoc_files: []
67
67
  files:
68
68
  - .gitignore
69
+ - CHANGELOG.md
69
70
  - Gemfile
70
71
  - Guardfile
71
72
  - README.md
72
73
  - Rakefile
73
74
  - app/assets/images/refinery/polls/pollbg.gif
74
- - app/assets/javascripts/refinery/polls/poll_form.js
75
+ - app/assets/javascripts/refinery/polls/poll.js
76
+ - app/assets/javascripts/refinery/polls/poll_form.js.coffee
75
77
  - app/assets/stylesheets/refinery/polls/poll_form.css.scss
78
+ - app/assets/stylesheets/refinery/polls/polls.css.scss
76
79
  - app/controllers/refinery/polls/admin/answers_controller.rb
77
80
  - app/controllers/refinery/polls/admin/questions_controller.rb
78
81
  - app/controllers/refinery/polls/questions_controller.rb
@@ -118,6 +121,7 @@ files:
118
121
  - db/migrate/5_create_polls_translations.rb
119
122
  - db/seeds.rb
120
123
  - lib/generators/refinery/polls_generator.rb
124
+ - lib/generators/refinery/templates/app/assets/stylesheets/refinery/polls/poll.css.scss
121
125
  - lib/generators/refinery/templates/config/initializers/refinery/poll.rb.erb
122
126
  - lib/refinery/polls.rb
123
127
  - lib/refinery/polls/configuration.rb
@@ -126,8 +130,12 @@ files:
126
130
  - lib/refinerycms-polls.rb
127
131
  - lib/tasks/refinery/polls.rake
128
132
  - refinerycms-polls.gemspec
133
+ - spec/models/refinery/polls/answer_spec.rb
129
134
  - spec/models/refinery/polls/question_spec.rb
135
+ - spec/models/refinery/polls/vote_spec.rb
136
+ - spec/requests/refinery/polls/admin/answers_spec.rb
130
137
  - spec/requests/refinery/polls/admin/questions_spec.rb
138
+ - spec/requests/refinery/polls/questions_spec.rb
131
139
  - spec/spec_helper.rb
132
140
  - spec/support/factories/refinery/polls.rb
133
141
  - tasks/rspec.rake
@@ -146,6 +154,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
146
154
  - - ! '>='
147
155
  - !ruby/object:Gem::Version
148
156
  version: '0'
157
+ segments:
158
+ - 0
159
+ hash: -252205175820330906
149
160
  required_rubygems_version: !ruby/object:Gem::Requirement
150
161
  none: false
151
162
  requirements:
@@ -159,7 +170,11 @@ signing_key:
159
170
  specification_version: 3
160
171
  summary: Polls extension for Refinery CMS
161
172
  test_files:
173
+ - spec/models/refinery/polls/answer_spec.rb
162
174
  - spec/models/refinery/polls/question_spec.rb
175
+ - spec/models/refinery/polls/vote_spec.rb
176
+ - spec/requests/refinery/polls/admin/answers_spec.rb
163
177
  - spec/requests/refinery/polls/admin/questions_spec.rb
178
+ - spec/requests/refinery/polls/questions_spec.rb
164
179
  - spec/spec_helper.rb
165
180
  - spec/support/factories/refinery/polls.rb
@@ -1,8 +0,0 @@
1
- function do_vote(element) {
2
- $(element).parents().find('form').submit();
3
- }
4
- $(document).ready(function(){
5
- $("input[type=radio][name=answer_id]").click(function() {
6
- do_vote(this);
7
- });
8
- })