开发者

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

开发者 https://www.devze.com 2023-02-09 02:51 出处:网络
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:

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?


You should use Polymorphic classes instead of STI

UPD

some links:

  • http://www.alexreisner.com/code/single-table-inheritance-in-rails
  • http://wiki.rubyonrails.org/howtos/db-relationships/polymorphic

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 :)


You may consider using the store_accessor method from ActiveRecord::Store.

The STI store approach given here demonstrates how you can give individual sub-classes different accessors, which are serialized in to a single column on the super-class.

If you're using PostgreSQL >= 9.2 then this works perfectly with its JSON type, if not then you can let Rails do the serializing (by using store instead of store_accessor.

TLDR (assuming PostgreSQL >= 9.2):

Add a migration:

add_column :mail_settings, :vendor_settings, :json

Define relevant attributes in sub-classes:

class MailChimp < MailSetting
    store_accessor :vendor_settings, :api_key
    validates :api_key, presence: true
end 


It looks to me like your schema is sufficiently formless that you'd be better off using a schema-free database. One of the "NoSQL" document based solutions, perhaps? That way you can add and remove fields to your records as you please.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号