# lib/questions_crafter/controller_helpers.rb module QuestionsCrafter module ControllerHelpers def self.included(base) base.class_eval do extend ClassMethods include InstanceMethods end end module ClassMethods # Class methods for controllers using QuestionsCrafter def handles_questions(questions_class, on_success:) underscore_questions_class_name = questions_class.name.underscore define_method :questions_action_name do underscore_questions_class_name end define_method :questions_class do questions_class end define_method :questions_params do question_definitions = questions_class.questions permitted_params = question_definitions.map do |q| if q[:type] == :checkbox_group # For checkbox groups, permit an array of values { q[:name] => [] } else q[:name] end end params.require(underscore_questions_class_name).permit(permitted_params) end # This is the action that gets injected into the controller with the name of the provided class # but with underscore for example SignUpQuestions -> sign_up_questions # It is meant to handle both the GET and the POST verbs define_method underscore_questions_class_name do if request.post? send("#{underscore_questions_class_name}_post") elsif request.get? send("#{underscore_questions_class_name}_get") end end # The POST action is used to handle the form submission and redisplay if there are still validation errors define_method "#{underscore_questions_class_name}_post" do questions_object = questions_class.new(questions_params) success = false method_res = if questions_object.valid? success = true send(on_success, questions_object) end # method_res has a 302 if a redirect happened in the on_success method # TODO: should we halt the chain and handle the redirect after showing the confirmation with the read only form? # Maybe we should be able to render the form with a confirmation message and a countdown to redirect # TODO: What should we do here if all goes well? Display the form again with the values already filled but NON editable render QuestionsCrafter::Ui::Components::QuestionsPage.new( questions_object: questions_object, form_url: "#", form_method: :post, read_only: success ) unless method_res == 302 end # The GET action is used to display the form define_method "#{underscore_questions_class_name}_get" do questions_object = questions_class.new render QuestionsCrafter::Ui::Components::QuestionsPage.new( questions_object: questions_object, form_url: "#", form_method: :post, read_only: false ) end end end module InstanceMethods # Instance methods for controllers using QuestionsCrafter end end end