多步形式创建与关系

时间:2018-02-06 20:33:00

标签: ruby-on-rails ruby

我尝试在本文后面实现多步骤表单:https://medium.com/@nicolasblanco/developing-a-wizard-or-multi-steps-forms-in-rails-d2f3b7c692ce

问题是我的模型有关系,并且在显示错误的步骤3中无法识别这些关系,请参阅下面的完整代码和错误消息:

class Evaluation < ApplicationRecord
    belongs_to :user
    belongs_to :teacher
    belongs_to :school
    belongs_to :subject

    has_many :evaluation_tags
    has_many :tags, through: :evaluation_tags

    accepts_nested_attributes_for :evaluation_tags

    validates :teacher_id, presence: true
    validates :subject_id, presence: true
    validates :school_id, presence: true
    validates :user_id, presence: true
    validates :rating, presence: true
end


module Wizard
  module Evaluation
    STEPS = %w(step1 step2 step3).freeze

    class Base
      include ActiveModel::Model
      attr_accessor :evaluation

      delegate *::Evaluation.attribute_names.map { |attr| [attr, "#{attr}="] }.flatten, to: :evaluation

      def initialize(evaluation_attributes)
        @evaluation = ::Evaluation.new(evaluation_attributes)
      end
    end

    class Step1 < Base
      validates :teacher_id, presence: true
    end

    class Step2 < Step1
      validates :subject_id, presence: true
    end

    class Step3 < Step2
      validates :school, presence: true
      validates :user, presence: true
      validates :rating, presence: true
    end
  end
end


class EvaluationsController < ApplicationController
    before_action :complete_sign_up, except: [:index]

    # before_action :load_evaluation_wizard, except: %i(validate_step)
    before_action :load_evaluation_wizard, except: [:validate_step, :new]

    def step1
        @teachers = Teacher.includes(:schools).where(schools: {id: current_user.student_details.last.school_id}).order(full_name: :ASC)
    end

    def step2
        @teacher_id = session[:evaluation_attributes]["teacher_id"]
        @subjects = Subject.includes(:teachers, :schools).where(teachers: {id: @teacher_id}).where(schools: {id: current_user.student_details.last.school_id}).order(name: :ASC)
    end

    def step3
        pp session[:evaluation_attributes]
    end


    def validate_step
        current_step = params[:current_step]

        @evaluation_wizard = wizard_evaluation_for_step(current_step)
        @evaluation_wizard.evaluation.attributes = evaluation_wizard_params
        session[:evaluation_attributes] = @evaluation_wizard.evaluation.attributes

        # pp session[:evaluation_attributes]

        if @evaluation_wizard.valid?
            next_step = wizard_evaluation_next_step(current_step)
            create and return unless next_step

            redirect_to action: next_step
        else
            render current_step
        end
    end


    def load_evaluation_wizard
        @evaluation_wizard = wizard_evaluation_for_step(action_name)
    end

    def wizard_evaluation_next_step(step)
        Wizard::Evaluation::STEPS[Wizard::Evaluation::STEPS.index(step) + 1]
    end

    def wizard_evaluation_for_step(step)
        raise InvalidStep unless step.in?(Wizard::Evaluation::STEPS)

        "Wizard::Evaluation::#{step.camelize}".constantize.new(session[:evaluation_attributes])
    end

    def evaluation_wizard_params
        params.require(:evaluation_wizard).permit(:teacher_id, :subject_id, evaluation_tags_attributes: {tag_ids: []}).merge(user: current_user, school: current_user.student_details.last.school)
    end

    class InvalidStep < StandardError; end

end


#STEP3.HTML.ERB

<%= f.collection_check_boxes(:tag_ids, Tag.all, :id, :name) do |tag| %>
  <%= tag.label(class: "tags tags-bom") { tag.check_box(class: "checkbox_tags") + tag.text} %>
<% end %>


#ERROR

undefined method `tag_ids' for #<Wizard::Evaluation::Step3:0x00007fadb2be6a88>

如何让该模块识别关系?

1 个答案:

答案 0 :(得分:0)

我认为您需要tag_ids的自定义验证。我不认为rails会一步验证多个项目。也许在应用程序控制器的底部添加自定义验证:

def validate_tag_ids
  if !tag_ids.is_a?
    errors.add(:tag_ids, :invalid)
  end
end

然后使用:

validates: :validate_tag_ids

而不是:

validates :tag_ids, presence: true