REFACTOR: rename "total_votes" poll field to the more accurate "voters"

FEATURE: automagically load plugin's migrations
This commit is contained in:
Régis Hanol 2015-05-04 16:01:57 +02:00
parent 8f706f11cb
commit 86d7412f30
13 changed files with 58 additions and 39 deletions

View file

@ -217,9 +217,6 @@ class Plugin::Instance
DiscoursePluginRegistry.register_glob(root_path, 'hbs')
end
# Automatically include all rake tasks
Rake.add_rakelib "#{File.dirname(path)}/lib/tasks"
self.instance_eval File.read(path), path
if auto_assets = generate_automatic_assets!
assets.concat auto_assets.map{|a| [a]}
@ -227,10 +224,18 @@ class Plugin::Instance
register_assets! unless assets.blank?
# TODO possibly amend this to a rails engine
# TODO: possibly amend this to a rails engine
# Automatically include assets
Rails.configuration.assets.paths << auto_generated_path
Rails.configuration.assets.paths << File.dirname(path) + "/assets"
# Automatically include rake tasks
Rake.add_rakelib(File.dirname(path) + "/lib/tasks")
# Automatically include migrations
Rails.configuration.paths["db/migrate"] << File.dirname(path) + "/db/migrate"
public_data = File.dirname(path) + "/public"
if Dir.exists?(public_data)
target = Rails.root.to_s + "/public/plugins/"

View file

@ -12,9 +12,9 @@ export default Em.Component.extend({
}.property("poll.options.@each.{html,votes}"),
average: function() {
const total_votes = this.get("poll.total_votes");
return total_votes == 0 ? 0 : round(this.get("totalScore") / total_votes, -2);
}.property("totalScore", "poll.total_votes"),
const voters = this.get("poll.voters");
return voters === 0 ? 0 : round(this.get("totalScore") / voters, -2);
}.property("totalScore", "poll.voters"),
averageRating: function() {
return I18n.t("poll.average_rating", { average: this.get("average") });

View file

@ -3,7 +3,7 @@ export default Em.Component.extend({
classNames: ["results"],
options: function() {
const totalVotes = this.get("poll.total_votes"),
const totalVotes = this.get("poll.voters"),
backgroundColor = this.get("poll.background");
this.get("poll.options").forEach(option => {
@ -20,6 +20,6 @@ export default Em.Component.extend({
});
return this.get("poll.options");
}.property("poll.total_votes", "poll.options.[]")
}.property("poll.voters", "poll.options.[]")
});

View file

@ -13,7 +13,7 @@ export default Em.Controller.extend({
// - user wants to see the results
showingResults: Em.computed.or("isClosed", "post.topic.closed", "post.topic.archived", "showResults"),
showResultsDisabled: Em.computed.equal("poll.total_votes", 0),
showResultsDisabled: Em.computed.equal("poll.voters", 0),
hideResultsDisabled: Em.computed.alias("isClosed"),
poll: function() {
@ -37,10 +37,6 @@ export default Em.Controller.extend({
return _.map(this.get("poll.options").filterBy("selected"), o => o.get("id"));
}.property("poll.options.@each.selected"),
totalVotesText: function() {
return I18n.t("poll.total_votes", { count: this.get("poll.total_votes") });
}.property("poll.total_votes"),
min: function() {
let min = parseInt(this.get("poll.min"), 10);
if (isNaN(min) || min < 1) { min = 1; }

View file

@ -14,8 +14,6 @@
{{/if}}
</div>
<p>{{totalVotesText}}</p>
{{#if isMultiple}}
<p>{{multipleHelpText}}</p>
{{d-button class="cast-votes" title="poll.cast-votes.title" label="poll.cast-votes.label" disabled=castVotesDisabled action="castVotes"}}

View file

@ -98,10 +98,8 @@
}
// that's our poll!
var result = ["div", attributes].concat(contents);
// add a small paragraph displaying the total number of votes
result.push(["p", I18n.t("poll.total_votes", { count: 0 })]);
var pollContainer = ["div", { "class": "poll-container" }].concat(contents);
var result = ["div", attributes, pollContainer];
// add some information when type is "multiple"
if (attributes[DATA_PREFIX + "type"] === "multiple") {
@ -144,6 +142,7 @@
});
Discourse.Markdown.whiteListTag("div", "class", "poll");
Discourse.Markdown.whiteListTag("div", "class", "poll-container");
Discourse.Markdown.whiteListTag("div", "data-*");
Discourse.Markdown.whiteListTag("a", "class", /^button (cast-votes|toggle-results)/);

View file

@ -59,7 +59,7 @@ div.poll {
}
.poll-container {
margin: 0;
margin: 0 0 5px;
span {
font-size: 1.125em;
line-height: 2

View file

@ -8,7 +8,7 @@
en:
js:
poll:
total_votes:
voters:
zero: "No votes yet. Want to be the first?"
one: "There's only 1 vote."
other: "There are %{count} total votes."

View file

@ -8,7 +8,7 @@
es:
js:
poll:
total_votes:
voters:
zero: "Sin votos todavía. ¿Quieres ser el primero?"
one: "Sólo hay 1 voto."
other: "Hay %{count} votos en total."

View file

@ -8,7 +8,7 @@
fr:
js:
poll:
total_votes:
voters:
zero: "Pas encore de votes. Soyez le premier !"
one: "Il n'y a qu'un vote."
other: "Il y a au total %{count} votes."

View file

@ -0,0 +1,29 @@
class RenameTotalVotesToVoters < ActiveRecord::Migration
def up
PostCustomField.where(name: "polls").find_each do |pcf|
polls = ::JSON.parse(pcf.value)
polls.each_value do |poll|
next if poll.has_key?("voters")
poll["voters"] = poll["total_votes"]
poll.delete("total_votes")
end
pcf.value = polls.to_json
pcf.save
end
end
def down
PostCustomField.where(name: "polls").find_each do |pcf|
polls = ::JSON.parse(pcf.value)
polls.each_value do |poll|
next if poll.has_key?("total_votes")
poll["total_votes"] = poll["voters"]
poll.delete("voters")
end
pcf.value = polls.to_json
pcf.save
end
end
end

View file

@ -14,15 +14,6 @@ VOTES_CUSTOM_FIELD ||= "polls-votes".freeze
after_initialize do
# PERF, avoids N+1 in serializer
TopicView.add_post_custom_fields_whitelister do |user|
POLLS_CUSTOM_FIELD
end
TopicView.add_post_custom_fields_whitelister do |user|
VOTES_CUSTOM_FIELD
end
# remove "Vote Now!" & "Show Results" links in emails
Email::Styles.register_plugin_style do |fragment|
fragment.css(".poll a.cast-votes, .poll a.toggle-results").each(&:remove)
@ -66,7 +57,7 @@ after_initialize do
vote = votes[poll_name] || []
# increment counters only when the user hasn't casted a vote yet
poll["total_votes"] += 1 if vote.size == 0
poll["voters"] += 1 if vote.size == 0
poll["options"].each do |option|
option["votes"] -= 1 if vote.include?(option["id"])
@ -125,7 +116,7 @@ after_initialize do
# extract polls
parsed.css("div.poll").each do |p|
poll = { "options" => [], "total_votes" => 0 }
poll = { "options" => [], "voters" => 0 }
# extract attributes
p.attributes.values.each do |attribute|
@ -217,9 +208,10 @@ after_initialize do
# only care when raw has changed!
return unless self.raw_changed?
extracted_polls = DiscoursePoll::Poll::extract(self.raw, self.topic_id)
polls = {}
extracted_polls = DiscoursePoll::Poll::extract(self.raw, self.topic_id)
extracted_polls.each do |poll|
# polls should have a unique name
if polls.has_key?(poll["name"])
@ -297,7 +289,7 @@ after_initialize do
next unless previous_polls.has_key?(poll_name)
next unless polls[poll_name]["options"].size == previous_polls[poll_name]["options"].size
polls[poll_name]["total_votes"] = previous_polls[poll_name]["total_votes"]
polls[poll_name]["voters"] = previous_polls[poll_name]["voters"]
for o in 0...polls[poll_name]["options"].size
polls[poll_name]["options"][o]["votes"] = previous_polls[poll_name]["options"][o]["votes"]
end

View file

@ -17,7 +17,7 @@ describe ::DiscoursePoll::PollsController do
expect(response).to be_success
json = ::JSON.parse(response.body)
expect(json["poll"]["name"]).to eq("poll")
expect(json["poll"]["total_votes"]).to eq(1)
expect(json["poll"]["voters"]).to eq(1)
expect(json["vote"]).to eq(["5c24fc1df56d764b550ceae1b9319125"])
end
@ -36,7 +36,7 @@ describe ::DiscoursePoll::PollsController do
xhr :put, :vote, { post_id: poll.id, poll_name: "poll", options: ["e89dec30bbd9bf50fabf6a05b4324edf"] }
expect(response).to be_success
json = ::JSON.parse(response.body)
expect(json["poll"]["total_votes"]).to eq(1)
expect(json["poll"]["voters"]).to eq(1)
expect(json["poll"]["options"][0]["votes"]).to eq(0)
expect(json["poll"]["options"][1]["votes"]).to eq(1)
end