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| -%>
  1. <%= 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| -%>
    1. <%= 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