Is subclassing a User model really bad to do in Rails?

后端 未结 3 1197
我寻月下人不归
我寻月下人不归 2021-01-04 23:30

I am getting lots of push back from Rails because I have subclassed User into many different subclasses. In my application, not all users are equal. There\'s actually a lot

相关标签:
3条回答
  • 2021-01-04 23:38

    Generally speaking, inheritance is discouraged in Ruby in favor of mixin behavior and delegation. Ruby and Rails can do that stuff but it tends to result in the push back you mentioned

    Your particular example sounds like a case for delegation: have a User class which belongs to an employee (or vice versa). The type-specific behavior of that employee (eg director, instructor, etc) is all in that specific employee class. Then the user will delegate how to handle specific scenarios to the employee that it's joined with

    0 讨论(0)
  • 2021-01-04 23:52

    It's basically about "say what you mean",

    the framework has no way of knowing when you say redirect_to @user if you meant the generic user form or the specialized employee user form.

    This leads to a lot of redirect_to @user.becomes(User) which you're free to DRY up

    def to_base_class
      becomes User
    end
    alias_method :to_b, :to_base_class
    

    and write redirect_to @user.to_b when your intention is to redirect to User and not Employee resource

    Basically, elegant syntax like redirect_to @user represents very deep coupling between model and view/controller and as you make the model and view/controller logics more complex cracks due to this coupling will begin to show and some additional effort in domain separation will need to be made or a bit more code will need to be written.

    Rails isn't punishing you for using OOP, you're experiencing increased complexity of model <-> view <-> controller relationship:

    once upon a time you model was your view and vice versa, now you have two model classes mapped to two view classes and if you want to use one view for the other model you will have to say it

    0 讨论(0)
  • 2021-01-04 23:56

    Here's a trick I figured out. Don't assume it's intended behaviour though:

    class UserSubclass < User
    
      def self.model_name
        User.model_name
      end
    
    end
    

    Basically all models (that derive from ActiveModel) identify themselves, by default, based on the concrete class name. That's done through the class method #model_name (it returns an instance of ActiveModel::Name with self as the parameter. Overriding it to return a specific class puts Rails on the right track. This way you keep that logic in your model and out of your templates.

    0 讨论(0)
提交回复
热议问题