refinerycms-polls 0.0.2.dev → 0.0.4.dev
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +23 -0
- data/Gemfile +3 -2
- data/README.md +7 -3
- data/Rakefile +2 -0
- data/app/assets/javascripts/refinery/polls/poll.js +2 -0
- data/app/assets/javascripts/refinery/polls/poll_form.js.coffee +6 -0
- data/app/assets/stylesheets/refinery/polls/polls.css.scss +7 -0
- data/app/controllers/refinery/polls/admin/answers_controller.rb +16 -3
- data/app/controllers/refinery/polls/questions_controller.rb +19 -16
- data/app/models/refinery/polls/answer.rb +15 -1
- data/app/models/refinery/polls/question.rb +22 -15
- data/app/models/refinery/polls/vote.rb +5 -3
- data/app/views/refinery/polls/questions/_answers_form.html.erb +4 -1
- data/app/views/refinery/polls/questions/_poll.html.erb +1 -1
- data/app/views/refinery/polls/questions/index.html.erb +4 -3
- data/app/views/refinery/polls/questions/show.html.erb +10 -19
- data/config/locales/en.yml +19 -19
- data/lib/generators/refinery/polls_generator.rb +5 -1
- data/lib/generators/refinery/templates/app/assets/stylesheets/refinery/polls/poll.css.scss +28 -0
- data/lib/refinery/polls/configuration.rb +1 -0
- data/lib/refinery/polls/engine.rb +1 -1
- data/lib/refinery/polls/version.rb +1 -1
- data/spec/models/refinery/polls/answer_spec.rb +17 -0
- data/spec/models/refinery/polls/question_spec.rb +31 -1
- data/spec/models/refinery/polls/vote_spec.rb +35 -0
- data/spec/requests/refinery/polls/admin/answers_spec.rb +114 -0
- data/spec/requests/refinery/polls/admin/questions_spec.rb +1 -1
- data/spec/requests/refinery/polls/questions_spec.rb +138 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/factories/refinery/polls.rb +12 -2
- metadata +17 -2
- 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.
|
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
|
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
@@ -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
|
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
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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.
|
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 =>
|
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
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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(
|
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
|
-
|
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('
|
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 |
|
4
|
-
|
4
|
+
<% @questions.each do |question| %>
|
5
|
+
<%= content_tag_for :li, question do %>
|
5
6
|
<%= link_to question.title, refinery.polls_question_path(question) %>
|
6
|
-
|
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
|
-
<
|
7
|
-
<
|
8
|
-
|
9
|
-
<%=
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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 |
|
21
|
+
<% @questions.each do |question| %>
|
31
22
|
<li>
|
32
23
|
<%= link_to question.title, refinery.polls_question_path(question) %>
|
33
24
|
</li>
|
data/config/locales/en.yml
CHANGED
@@ -2,39 +2,39 @@ en:
|
|
2
2
|
refinery:
|
3
3
|
plugins:
|
4
4
|
polls:
|
5
|
-
title:
|
5
|
+
title: Questions
|
6
6
|
polls:
|
7
7
|
admin:
|
8
8
|
questions:
|
9
9
|
actions:
|
10
|
-
create_new: Add New
|
11
|
-
reorder: Reorder
|
12
|
-
reorder_done: Done Reordering
|
10
|
+
create_new: Add New Question
|
11
|
+
reorder: Reorder Questions
|
12
|
+
reorder_done: Done Reordering Questions
|
13
13
|
records:
|
14
|
-
title:
|
14
|
+
title: Questions
|
15
15
|
sorry_no_results: Sorry! There are no results found.
|
16
|
-
no_items_yet: There are no
|
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
|
19
|
-
edit: Edit this
|
20
|
-
delete: Remove this
|
21
|
-
manage_answers: View answers for this
|
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
|
25
|
-
reorder: Reorder
|
26
|
-
reorder_done: Done Reordering
|
24
|
+
create_new: Add New Question Answer
|
25
|
+
reorder: Reorder Question Answers
|
26
|
+
reorder_done: Done Reordering Question Answers
|
27
27
|
records:
|
28
|
-
title:
|
28
|
+
title: Question Answers
|
29
29
|
sorry_no_results: Sorry! There are no results found.
|
30
|
-
no_items_yet: There are no
|
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
|
33
|
-
edit: Edit this
|
34
|
-
delete: Remove this
|
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
|
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
|
+
*/
|
@@ -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
|
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
|
@@ -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
@@ -1,7 +1,17 @@
|
|
1
|
-
|
2
1
|
FactoryGirl.define do
|
3
|
-
factory :question,
|
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.
|
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/
|
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
|