Skip to content

Add question types to surveys#1398

Merged
beagleknight merged 17 commits intofeature/surveysfrom
feature/surveys-question-types
May 30, 2017
Merged

Add question types to surveys#1398
beagleknight merged 17 commits intofeature/surveysfrom
feature/surveys-question-types

Conversation

@beagleknight
Copy link
Copy Markdown
Contributor

@beagleknight beagleknight commented May 24, 2017

🎩 What? Why?

This adds question types to survey questions:

  • Short answer: Users fill in the answer in a simple text input
  • Long answer: Users fill in the answer in a textarea
  • Single option: Users must choose a single answer of the given ones.
  • Multiple option: Users can check as many answers as they want of the given ones.

In this PR I also included a lot of refactors for the JS code. I built a mini library to add/remove dynamic fields from a form. I have not included documentation yet because the code is changing in every PR. I save the final docs before merging the feature branch.

📌 Related Issues

📋 Subtasks

  • Refactor templates
  • Admin can select question types
  • Add short and long answer question types
  • Admin can fill in option answers for a question
  • Add single and multiple option question types

📷 Screenshots (optional)

image
image
image
image

👻 GIF


def label_for_question(survey, question)
return survey.published? ? t('.question') : "#{icon("move")} #{t('.question')}".html_safe if question.persisted?
"#{icon("move")} #{t('.question')} #${questionLabelPosition}".html_safe
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer double-quoted strings inside interpolations.

end

def label_for_question(survey, question)
return survey.published? ? t('.question') : "#{icon("move")} #{t('.question')}".html_safe if question.persisted?
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.
Prefer double-quoted strings inside interpolations.

@beagleknight beagleknight force-pushed the feature/surveys-question-types branch from 1a25fa9 to cabe8ee Compare May 24, 2017 10:08
@codecov
Copy link
Copy Markdown

codecov bot commented May 24, 2017

Codecov Report

Merging #1398 into feature/surveys will increase coverage by 0.02%.
The diff coverage is 100%.

@@                 Coverage Diff                 @@
##           feature/surveys    #1398      +/-   ##
===================================================
+ Coverage            94.86%   94.89%   +0.02%     
===================================================
  Files                  444      445       +1     
  Lines                 7554     7593      +39     
===================================================
+ Hits                  7166     7205      +39     
  Misses                 388      388

described_class.from_model(survey)
described_class.from_model(survey).with_context({
current_feature: survey.feature
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indent the right brace the same as the first position after the preceding left parenthesis.

subject do
described_class.from_model(survey)
described_class.from_model(survey).with_context({
current_feature: survey.feature
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use 2 spaces for indentation in a hash, relative to the first position after the preceding left parenthesis.


subject do
described_class.from_model(survey)
described_class.from_model(survey).with_context({
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant curly braces around a hash parameter.

subject do
described_class.from_model(survey_answer).with_context({
current_feature: survey.feature
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indent the right brace the same as the first position after the preceding left parenthesis.


subject do
described_class.from_model(survey_answer).with_context({
current_feature: survey.feature
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use 2 spaces for indentation in a hash, relative to the first position after the preceding left parenthesis.

let!(:survey_answer) { create(:survey_answer, user: user, survey: survey, question: survey_question) }

subject do
described_class.from_model(survey_answer).with_context({
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant curly braces around a hash parameter.

@beagleknight beagleknight changed the title Add question types Add question types to surveys May 24, 2017
@beagleknight beagleknight mentioned this pull request May 24, 2017
8 tasks
@beagleknight beagleknight force-pushed the feature/surveys-question-types branch from cabe8ee to b14d909 Compare May 24, 2017 10:13
@beagleknight beagleknight force-pushed the feature/surveys-question-types branch from b14d909 to 29bbda5 Compare May 24, 2017 13:17
},
position: 0
position: 0,
question_type: "short_answer"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing whitespace detected.

"position" => "0"
"position" => "0",
"question_type" => "short_answer",
"answer_options" => []
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing whitespace detected.

end

def label_for_question(survey, question)
return survey.published? ? t(".question") : "#{icon("move")} #{t(".question")}".html_safe
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant return detected.

"${tabsId}"
end

def label_for_question(survey, question)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused method argument - question. If it's necessary, use _ or _question as an argument name to indicate that it won't be used.

end
end
end
end No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final newline missing.

@mention-bot
Copy link
Copy Markdown

@beagleknight, thanks for your PR! By analyzing the history of the files in this pull request, we identified @lastpotion and @mrcasals to be potential reviewers.


# Private: answer options should be mapped manually.
def map_model(model)
self.answer_options = model.answer_options
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be needed :/

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is needed! I did some tests with Virtus stuff and the problem is answer_options is not a real model, just a serialized field and he doesn't know how to build the actual form field.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't it call the method? I mean, you are not changing anything here. We usually use this method because of some form field names not matching the model method, so we need to manually set them. Here you are not doing anything special, you're calling the same method name that you are setting so it should be done automatically :/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like @mrcasals is right, but 🤷‍♂️

# Custom helpers, scoped to the surveys engine.
#
module ApplicationHelper
def tabs_id_for_question(question)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs for all methods?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will do a PR with all the documentation because the API is changing too much.

belongs_to :survey, class_name: Survey, foreign_key: "decidim_survey_id"

def answer_options
self[:answer_options] || []
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This smells like you're missing a default: [] value in the migration that adds this column

@@ -0,0 +1,5 @@
class AddAnswerOptionsToSurveysQuestions < ActiveRecord::Migration[5.0]
def change
add_column :decidim_surveys_survey_questions, :answer_options, :jsonb
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a default non-nil value. See the comment I left in the model

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

default: [] should be goos enough, if you need an array here

josepjaume
josepjaume previously approved these changes May 30, 2017
Copy link
Copy Markdown
Contributor

@josepjaume josepjaume left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!! Outstanding work!


# Private: answer options should be mapped manually.
def map_model(model)
self.answer_options = model.answer_options
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like @mrcasals is right, but 🤷‍♂️

@beagleknight
Copy link
Copy Markdown
Contributor Author

@josepjaume @mrcasals 🤷‍♂️

# Rectify can't handle a hash when using the from_model method so
# the answer options must be converted to struct.
def answer_options
self[:answer_options].map { |option| OpenStruct.new(option) }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LOL

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes me cry so hard

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@beagleknight beagleknight merged commit 25d95a1 into feature/surveys May 30, 2017
@beagleknight beagleknight deleted the feature/surveys-question-types branch May 30, 2017 12:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants