Search code examples
ruby-on-railsmodelssti

STI and extending Subclasses to include 'extra' columns in a database?


Maybe STI isn't what I want, and I'm open to all suggestions, but for the sake of this questions let's assume the following real world situation:

You want your app to house API data for different Mail Vendors. Using STI, you have the following models

class MailSetting < ActiveRecord::Base
belongs_to :user

end


class MailChimp < MailSetting

end

class AWeber < MailSetting

end

class PostageApp < MailSetting

end

Now let's pull up some console action:


user = User.first
setting = user.create_mail_setting(:type => "MailChimp")

Ok, now you want to add the API key settings. MailChimp just uses an api_key. Aweber may user an api_key and signature, and Postageapp, say, uses an api_key and token system.

Would you extend each subclass to include whatever columns you needed in the database? Would you scrap STI all together and just make regular classes say, MailChimp, that inherits from AR?

My reasoning for STI was that i know all of my users will have a MailSetting, it's the type that may expand over time. However, i find it a pain in the butt to extend these subclasses this way cause you can't do things like user.mail_setting.connect without knowing what subclass they are from, and then, what i needed to connect these guys?

Thoughts?


Solution

  • You should use Polymorphic classes instead of STI

    UPD

    some links:

    UPD 2

    Imagine, we need Post model. And we have Article and Topic that inherit from Post.

    rails g model Post title:string body:text content_type:string content_id:integer
    

    So title and body are common fields for Topic and Article. Lets now create other models with user_id field in Topic and link in Article

    rails g model Topic user_id:integer
    rails g model Article link:string
    

    Now we will edit models:

    class Post < ActiveRecord::Base
      belongs_to :content, :polymorphic => true, :dependent => :destroy
    end
    
    class Topic < ActiveRecord::Base
      has_one :post, :as => :content, :dependent => :destroy
    end
    
    class Article < ActiveRecord::Base
      has_one :post, :as => :content, :dependent => :destroy
    end
    

    It can be quite complicated, but digg this way :)