From 19ee3047f57807f342cb7cefd1b6589aff15ea6b Mon Sep 17 00:00:00 2001
From: Joe Ferris
Date: Thu, 7 Feb 2013 16:57:02 -0500
Subject: [PATCH] Replace Subclasses with Strategies: Step Thirteen
* Always instantiate the same root class
---
.../app/controllers/questions_controller.rb | 4 ++--
.../app/controllers/types_controller.rb | 4 ++--
example_app/app/models/question.rb | 10 +++++++---
.../_multiple_choice_submittable.html.erb} | 2 +-
...multiple_choice_submittable_form.html.erb} | 0
.../_open_submittable.html.erb} | 0
.../_open_submittable_form.html.erb} | 0
.../app/views/questions/_form.html.erb | 4 ++--
example_app/app/views/questions/edit.html.erb | 12 ++++++++---
.../_scale_submittable.html.erb} | 2 +-
.../_scale_submittable_form.html.erb} | 0
example_app/app/views/surveys/show.html.erb | 20 +++++++++++++------
example_app/app/views/types/new.html.erb | 2 +-
.../20130207214017_remove_questions_type.rb | 16 +++++++++++++++
example_app/db/schema.rb | 3 +--
example_app/spec/factories/application.rb | 11 +++++-----
example_app/spec/models/question_spec.rb | 8 +++-----
.../spec/support/features/survey_taker.rb | 6 +++---
18 files changed, 68 insertions(+), 36 deletions(-)
rename example_app/app/views/{multiple_choice_questions/_multiple_choice_question.html.erb => multiple_choice_submittables/_multiple_choice_submittable.html.erb} (75%)
rename example_app/app/views/{multiple_choice_questions/_multiple_choice_question_form.html.erb => multiple_choice_submittables/_multiple_choice_submittable_form.html.erb} (100%)
rename example_app/app/views/{open_questions/_open_question.html.erb => open_submittables/_open_submittable.html.erb} (100%)
rename example_app/app/views/{open_questions/_open_question_form.html.erb => open_submittables/_open_submittable_form.html.erb} (100%)
rename example_app/app/views/{scale_questions/_scale_question.html.erb => scale_submittables/_scale_submittable.html.erb} (77%)
rename example_app/app/views/{scale_questions/_scale_question_form.html.erb => scale_submittables/_scale_submittable_form.html.erb} (100%)
create mode 100644 example_app/db/migrate/20130207214017_remove_questions_type.rb
diff --git a/example_app/app/controllers/questions_controller.rb b/example_app/app/controllers/questions_controller.rb
index 50148c6..70fb08a 100644
--- a/example_app/app/controllers/questions_controller.rb
+++ b/example_app/app/controllers/questions_controller.rb
@@ -31,13 +31,13 @@ def update
private
def build_question
- @question = type.constantize.new(question_params)
+ @question = Question.new(question_params)
@question.build_submittable(type, submittable_params)
@question.survey = @survey
end
def type
- params[:question][:type]
+ params[:question][:submittable_type]
end
def question_params
diff --git a/example_app/app/controllers/types_controller.rb b/example_app/app/controllers/types_controller.rb
index d98ade7..a91ff1a 100644
--- a/example_app/app/controllers/types_controller.rb
+++ b/example_app/app/controllers/types_controller.rb
@@ -2,7 +2,7 @@ class TypesController < ApplicationController
def new
@question = Question.find(params[:question_id])
assign_type
- @new_question = type.constantize.new
+ @new_question = Question.new
@new_question.build_submittable(type, {})
end
@@ -37,6 +37,6 @@ def submittable_attributes
end
def type
- params[:question][:type]
+ params[:question][:submittable_type]
end
end
diff --git a/example_app/app/models/question.rb b/example_app/app/models/question.rb
index 89c3851..0306286 100644
--- a/example_app/app/models/question.rb
+++ b/example_app/app/models/question.rb
@@ -1,10 +1,14 @@
class Question < ActiveRecord::Base
include ActiveModel::ForbiddenAttributesProtection
- QUESTION_TYPES = %w(OpenQuestion MultipleChoiceQuestion ScaleQuestion).freeze
+ QUESTION_TYPES = %w(
+ OpenSubmittable
+ MultipleChoiceSubmittable
+ ScaleSubmittable
+ ).freeze
validates :submittable, associated: true
- validates :type, presence: true, inclusion: QUESTION_TYPES
+ validates :submittable_type, presence: true, inclusion: QUESTION_TYPES
validates :title, presence: true
belongs_to :submittable, polymorphic: true
@@ -33,7 +37,7 @@ def summarize(summarizer)
def switch_to(type, new_attributes, submittable_attributes)
attributes = self.attributes.merge(new_attributes)
cloned_attributes = attributes.except('id', 'type', 'submittable_type')
- new_question = type.constantize.new(cloned_attributes)
+ new_question = Question.new(cloned_attributes)
new_question.build_submittable(type, submittable_attributes)
new_question.id = id
diff --git a/example_app/app/views/multiple_choice_questions/_multiple_choice_question.html.erb b/example_app/app/views/multiple_choice_submittables/_multiple_choice_submittable.html.erb
similarity index 75%
rename from example_app/app/views/multiple_choice_questions/_multiple_choice_question.html.erb
rename to example_app/app/views/multiple_choice_submittables/_multiple_choice_submittable.html.erb
index 70763df..57cd008 100644
--- a/example_app/app/views/multiple_choice_questions/_multiple_choice_question.html.erb
+++ b/example_app/app/views/multiple_choice_submittables/_multiple_choice_submittable.html.erb
@@ -1,5 +1,5 @@
- <% submittable.options.each do |option| -%>
+ <% multiple_choice_submittable.options.each do |option| -%>
-
<%= submission_fields.radio_button :text, option.text, id: dom_id(option) %>
<%= content_tag :label, option.text, for: dom_id(option) %>
diff --git a/example_app/app/views/multiple_choice_questions/_multiple_choice_question_form.html.erb b/example_app/app/views/multiple_choice_submittables/_multiple_choice_submittable_form.html.erb
similarity index 100%
rename from example_app/app/views/multiple_choice_questions/_multiple_choice_question_form.html.erb
rename to example_app/app/views/multiple_choice_submittables/_multiple_choice_submittable_form.html.erb
diff --git a/example_app/app/views/open_questions/_open_question.html.erb b/example_app/app/views/open_submittables/_open_submittable.html.erb
similarity index 100%
rename from example_app/app/views/open_questions/_open_question.html.erb
rename to example_app/app/views/open_submittables/_open_submittable.html.erb
diff --git a/example_app/app/views/open_questions/_open_question_form.html.erb b/example_app/app/views/open_submittables/_open_submittable_form.html.erb
similarity index 100%
rename from example_app/app/views/open_questions/_open_question_form.html.erb
rename to example_app/app/views/open_submittables/_open_submittable_form.html.erb
diff --git a/example_app/app/views/questions/_form.html.erb b/example_app/app/views/questions/_form.html.erb
index 5b7a3b2..31114c8 100644
--- a/example_app/app/views/questions/_form.html.erb
+++ b/example_app/app/views/questions/_form.html.erb
@@ -1,8 +1,8 @@
<%= simple_form_for question, as: :question, url: url do |form| -%>
- <%= form.hidden_field :type %>
+ <%= form.hidden_field :submittable_type %>
<%= form.input :title %>
<%= render(
- "#{question.to_partial_path}_form",
+ "#{question.submittable.to_partial_path}_form",
submittable: question.submittable,
form: form
) %>
diff --git a/example_app/app/views/questions/edit.html.erb b/example_app/app/views/questions/edit.html.erb
index cef71cc..1f5c56e 100644
--- a/example_app/app/views/questions/edit.html.erb
+++ b/example_app/app/views/questions/edit.html.erb
@@ -5,20 +5,26 @@
<%= link_to(
'Scale Question',
- new_question_type_path(@question, question: { type: 'ScaleQuestion' })
+ new_question_type_path(
+ @question,
+ question: { submittable_type: 'ScaleSubmittable' }
+ )
) %>
<%= link_to(
'Multiple Choice Question',
new_question_type_path(
@question,
- question: { type: 'MultipleChoiceQuestion' }
+ question: { submittable_type: 'MultipleChoiceSubmittable' }
)
) %>
<%= link_to(
'Open Question',
- new_question_type_path(@question, question: { type: 'OpenQuestion' })
+ new_question_type_path(
+ @question,
+ question: { submittable_type: 'OpenSubmittable' }
+ )
) %>
diff --git a/example_app/app/views/scale_questions/_scale_question.html.erb b/example_app/app/views/scale_submittables/_scale_submittable.html.erb
similarity index 77%
rename from example_app/app/views/scale_questions/_scale_question.html.erb
rename to example_app/app/views/scale_submittables/_scale_submittable.html.erb
index ee6e4cc..d2f5317 100644
--- a/example_app/app/views/scale_questions/_scale_question.html.erb
+++ b/example_app/app/views/scale_submittables/_scale_submittable.html.erb
@@ -1,5 +1,5 @@
- <% submittable.steps.each do |step| -%>
+ <% scale_submittable.steps.each do |step| -%>
-
<%= submission_fields.radio_button :text, step %>
<%= submission_fields.label "text_#{step}", label: step %>
diff --git a/example_app/app/views/scale_questions/_scale_question_form.html.erb b/example_app/app/views/scale_submittables/_scale_submittable_form.html.erb
similarity index 100%
rename from example_app/app/views/scale_questions/_scale_question_form.html.erb
rename to example_app/app/views/scale_submittables/_scale_submittable_form.html.erb
diff --git a/example_app/app/views/surveys/show.html.erb b/example_app/app/views/surveys/show.html.erb
index caa9ab3..06c9f13 100644
--- a/example_app/app/views/surveys/show.html.erb
+++ b/example_app/app/views/surveys/show.html.erb
@@ -6,17 +6,26 @@
<%= link_to(
'Add Multiple Choice Question',
- new_survey_question_path(@survey, question: { type: 'MultipleChoiceQuestion' })
+ new_survey_question_path(
+ @survey,
+ question: { submittable_type: 'MultipleChoiceSubmittable' }
+ )
) %>
<%= link_to(
'Add Open Question',
- new_survey_question_path(@survey, question: { type: 'OpenQuestion' })
+ new_survey_question_path(
+ @survey,
+ question: { submittable_type: 'OpenSubmittable' }
+ )
) %>
<%= link_to(
'Add Scale Question',
- new_survey_question_path(@survey, question: { type: 'ScaleQuestion' })
+ new_survey_question_path(
+ @survey,
+ question: { submittable_type: 'ScaleSubmittable' }
+ )
) %>
<%= simple_form_for [@survey, @completion] do |form| -%>
@@ -26,9 +35,8 @@
<%= form.fields_for "answers_attributes[#{question.id}]", Answer.new do |submission_fields| -%>
<%= submission_fields.label :text, label: question.title %>
<%= render(
- question,
- submission_fields: submission_fields,
- submittable: question.submittable
+ question.submittable,
+ submission_fields: submission_fields
) %>
<%= link_to 'Edit', edit_question_path(question) %>
<% end -%>
diff --git a/example_app/app/views/types/new.html.erb b/example_app/app/views/types/new.html.erb
index 9833384..74d2cf7 100644
--- a/example_app/app/views/types/new.html.erb
+++ b/example_app/app/views/types/new.html.erb
@@ -4,7 +4,7 @@
url: question_types_path(@question)
) do |form| -%>
- <%= form.hidden_field :type %>
+ <%= form.hidden_field :submittable_type %>
<%= render(
"#{@new_type}s/#{@new_type}_form",
question: @new_question,
diff --git a/example_app/db/migrate/20130207214017_remove_questions_type.rb b/example_app/db/migrate/20130207214017_remove_questions_type.rb
new file mode 100644
index 0000000..1c4e641
--- /dev/null
+++ b/example_app/db/migrate/20130207214017_remove_questions_type.rb
@@ -0,0 +1,16 @@
+class RemoveQuestionsType < ActiveRecord::Migration
+ def up
+ remove_column :questions, :type
+ end
+
+ def down
+ add_column :questions, :type, :string
+
+ connection.update(<<-SQL)
+ UPDATE questions
+ SET type = REPLACE(submittable_type, 'Submittable', 'Question')
+ SQL
+
+ change_column_null :questions, :type, true
+ end
+end
diff --git a/example_app/db/schema.rb b/example_app/db/schema.rb
index 78dd0f7..281c459 100644
--- a/example_app/db/schema.rb
+++ b/example_app/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20130207164259) do
+ActiveRecord::Schema.define(:version => 20130207214017) do
create_table "answers", :force => true do |t|
t.integer "completion_id", :null => false
@@ -68,7 +68,6 @@
create_table "questions", :force => true do |t|
t.string "title", :null => false
- t.string "type", :null => false
t.integer "survey_id", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
diff --git a/example_app/spec/factories/application.rb b/example_app/spec/factories/application.rb
index 87fc3c2..087307d 100644
--- a/example_app/spec/factories/application.rb
+++ b/example_app/spec/factories/application.rb
@@ -29,19 +29,20 @@
text 'Hello'
end
- factory :question, class: 'OpenQuestion' do
- survey
+ factory :question do
sequence(:title) { |n| "Question #{n}" }
+ submittable factory: :open_submittable
+ survey
- factory :multiple_choice_question, class: 'MultipleChoiceQuestion' do
+ factory :multiple_choice_question do
submittable factory: :multiple_choice_submittable
end
- factory :open_question, class: 'OpenQuestion' do
+ factory :open_question do
submittable factory: :open_submittable
end
- factory :scale_question, class: 'ScaleQuestion' do
+ factory :scale_question do
submittable factory: :scale_submittable
end
end
diff --git a/example_app/spec/models/question_spec.rb b/example_app/spec/models/question_spec.rb
index 500941e..da6a304 100644
--- a/example_app/spec/models/question_spec.rb
+++ b/example_app/spec/models/question_spec.rb
@@ -1,13 +1,13 @@
require 'spec_helper'
describe Question do
- it { should validate_presence_of :type }
+ it { should validate_presence_of :submittable_type }
Question::QUESTION_TYPES.each do |type|
- it { should allow_value(type).for(:type) }
+ it { should allow_value(type).for(:submittable_type) }
end
- it { should_not allow_value('Other').for(:type) }
+ it { should_not allow_value('Other').for(:submittable_type) }
it { should validate_presence_of :title }
@@ -71,7 +71,6 @@
{ minimum: 1, maximum: 2 })
new_question.errors.should be_empty
- new_question.should be_a(ScaleQuestion)
submittable = new_question.submittable
submittable.should be_a(ScaleSubmittable)
submittable.minimum.should eq 1
@@ -85,7 +84,6 @@
new_question = question.switch_to('ScaleQuestion', {}, { minimum: 1 })
new_question.errors.should be_present
- new_question.should be_a(ScaleQuestion)
new_question.submittable.should be_a(ScaleSubmittable)
new_question.submittable.minimum.should eq 1
end
diff --git a/example_app/spec/support/features/survey_taker.rb b/example_app/spec/support/features/survey_taker.rb
index c88b726..6a826c5 100644
--- a/example_app/spec/support/features/survey_taker.rb
+++ b/example_app/spec/support/features/survey_taker.rb
@@ -23,10 +23,10 @@ def start
def answer(question_title, answer_text)
question = Question.find_by_title!(question_title)
- case question
- when OpenQuestion
+ case question.submittable
+ when OpenSubmittable
fill_in question_title, with: answer_text
- when ScaleQuestion, MultipleChoiceQuestion
+ when ScaleSubmittable, MultipleChoiceSubmittable
within %{li:contains("#{question_title}")} do
choose answer_text
end