collectiveidea / interactor

Interactor provides a common interface for performing complex user interactions.
MIT License
3.36k stars 212 forks source link

Using interactor along with ActiveModel, is it possible? #93

Closed adis-io closed 9 years ago

adis-io commented 9 years ago

Before sign up user, I need validate all params. Where should I put this validations stuff? Now I'm using form object for validation using ActiveModel.

module Profile
  class Register
    include Interactor::Organizer

    organize ValidateSignup, Create, CreateUser, LinkUser, SendConfirmation
  end
end
module Profile
  class ValidateSignup
    include Interactor

    def call
      form = ApiSignup.new(context.profile_params)
      if form.valid?
        context.user_params = form.as_json(only: ['email', 'password'])
        context.profile_type = form.type
      else
        errors = form.errors.keys.map do |property|
          {
            resource: "User",
            field: property,
            message: form.errors.full_messages_for(property)
          }
        end
        context.message = "Validation Failed"
        context.errors = errors
        context.fail!
      end
    end
  end
end
class ApiSignup
  include ActiveModel::Model

  attr_accessor :email, :password, :type

  validates :email, presence: true
  validates_format_of :email, :with => /@/
  validates :password, presence: true, length: { minimum: 6 }
  validates :type, presence: true, inclusion: { in: %w(individual business),
    message: "is not valid" }

  validate :email_is_unique

  def persisted?
    false
  end

  def email_is_unique
    errors.add(:email, "has already been taken") if User.exists?(email: email)
  end
end
laserlemon commented 9 years ago

Right now, Interactor doesn't have any concept of validations. One of the main reasons for this decision is that any number of behaviors might be expected if an interactor's validations were violated, so we're opting (at the moment) for flexibility. So what I see above looks just fine to me!

I've toyed with the idea of introducing an Interactor::Model module that could combine an interactor with the sort of form/virtual model you're using above but I haven't fully pursued it yet, nor do I know whether it's a good idea!

Thanks for the question and I hope that helps!