Search code examples
ruby-on-railsrubydeviseemail-validation

before_create in user model -- set integer based on email (RAILS)


I'm trying to assign a user to their companys group based on their email domain. I'm using devise + confirmation, so I avoided using regex (dont need to validate that its a valid email...), and am trying to do this in a simple way. So essentially, it would force the users company_id (which matches up with that table) to be assigned in sign up, and then not allow them to sign up if their company doesnt exist. So this will work for both [email protected] and [email protected]

In User model

before_create :company_placement

...

def company_placement
  user_domain = (:email).split('@').last

  while user_domain.split('.').count > 2
    user_domain = user_domain.split('.', 2).last
  end

  if Company.find_by_domain(user_domain) != nil
    (:company_id) = Company.find_by_domain(user_domain).id
  else
    #error out
  end
end

When I do this in rails console step by step, it seems to work. But in console when i run,

> user = User.create!(name: "test", email: "[email protected]", password: "foobar")

I get undefined local variable or method 'user' for #<'User....

Thanks for any help, still learning rails...


Solution

  • So I played with this some more and think i found a solution I like

    in user model

    before_validation :company_placement
    
    ...
    
    def company_placement
      user_domain = self.email.split('@').last
    
      while user_domain.split('.').count > 2
        user_domain = user_domain.split('.', 2).last
      end
    
      if Company.find_by_domain(user_domain) != nil
        self.company_id = Company.find_by_domain(user_domain).id
      end
    end
    

    Created devise registration controller -- controllers/registrations _ controller.rb

    in new registrations controller

    class RegistrationsController < Devise::RegistrationsController
      before_filter :verify_company, only: :create
    
      private
    
        def verify_company
          build resource #necessary for devise
    
          user_domain = resource.email.split('@').last
    
          while user_domain.split('.').count > 2
            user_domain = user_domain.split('.', 2).last
          end
    
          unless Company.find_by_domain(user_domain) != nil
            flash[:error] = 'Sorry, your company does not exist yet'
            redirect_to root_path
          end
        end
    end
    

    routes.rb

    devise_for :users, :controllers => { :registrations => "registrations" }
    

    So im sure there is a more elegant solution, but this works for me. Handles the errors/flash in the controller, and then if the company exists, it the user gets auto assigned to the company through the model.