Является ли наследование одной таблицы правильным решением для моей проблемы с Rails? - PullRequest
2 голосов
/ 22 сентября 2010

Привет, все,

Я работаю над приложением в Ruby on Rails, где нам необходимо отслеживать набор внешних сервисов для каждого пользователя (например, Facebook, MySpace, Google, SalesForce, Twitter, WordPress и т. Д.), Которое приложение будет доступ от имени пользователя. Для некоторых служб нам потребуется хранить (зашифрованное) имя пользователя и пароль, для некоторых нам потребуется сохранить данные OAuth, некоторые данные OAuth2 и т. Д. По мере роста приложения нам необходимо будет поддерживать еще больше типов учетных записей, каждая из которых будет иметь свой собственный набор данных для аутентификации.

Каждый пользователь может создавать сообщения в приложении, и мы возьмем эти сообщения и отправим их во внешние службы для публикации для пользователя. Затем мы отслеживаем ответ на опубликованный пост (ретвиты в Twitter, лайки / публикации в Facebook и т. Д.).

Итак:

class User < ActiveRecord::Base
  has_many :services
  has_many :posts
end

class Post < ActiveRecord::Base
  belongs_to :user
  has_many :publishes
end

class Publish < ActiveRecord::Base
  has_one :service
  belongs_to :post
end

class Service < ActiveRecord::Base
  belongs_to :user
  belongs_to :publish
end

Я спорю между использованием наследования одной таблицы для моих типов Service (например, WordpressService, FacebookService, TwitterService и простым сериализацией простого хэша для сохранения данных аутентификации) и использованием традиционного Нормализованная схема, где у каждого вида услуг есть своя модель и таблица. Я хотел бы иметь возможность легко перебирать все сервисы, связанные с пользователем, и публикация должна быть связана с любым типом сервисов (например, публикация может быть отправлена ​​на WordPress, Facebook или Twitter) .

Могу ли я достичь такого рода модельных отношений, используя традиционный нормализованный подход? Или это именно то, что STI должен был решить?

Спасибо.

Ответы [ 4 ]

2 голосов
/ 03 апреля 2011

В качестве альтернативы ИППП вы можете использовать полиморфные ассоциации:

class AccountAuth < AR::Base
  belongs_to :account
  belongs_to :authentication, :polymorphic => true
end
# account_id          :integer
# authentication_id   :integer
# authentication_type :string

module Auth
  #common logic
end

class FacebookAuth < AR::Base
  include Auth
  has_one :account_auth,:as=>:authentication
  has_one :account, :through => :account_auth
end

class Account < AR::Base
  has_many :account_auths
  has_many :authentications, :through => :account_auths
end

Это и это может вам помочь.

2 голосов
/ 23 октября 2010

Возможно, вы захотите воспользоваться omniauth-плагином , который довольно прост в настройке и позволяет хранить учетные данные для проверки подлинности для ряда служб из коробки. Есть пара железнодорожных передач, которые показывают, как это настроить. Если ничего другого, вы могли бы увидеть, как они предлагают хранить вещи.

0 голосов
/ 27 сентября 2010

Хотя я до сих пор не уверен, что это «правильный» способ решения этой проблемы, я решил использовать наследование одной таблицы, чтобы можно было легко получить список всех службчто другая модель has_many из (поскольку каждый подкласс Service также Service, я могу позвонить model_instance.services, чтобы получить их все).

Чтобы решить проблему дублирования кода, я создалмодуль для использования в любой модели, которая должна has_many :services, а также каждый тип услуги:

module HasServices
  extend ActiveSupport::Concern
  included do
    has_many :services
    has_many :facebook_services
    has_many :twitter_services
    has_many :wordpress_services
  end
end

Service также знает о своих подклассах, так что меню и т. д. могут быть легко созданы:

class Service < ActiveRecord::Base

  @child_classes = []

  ...

  protected

    def self.inherited(child)
      @child_classes << child
      super
    end

    def self.child_classes
      @child_classes
    end
end
0 голосов
/ 22 сентября 2010

Сколько миллионов пользователей вы будете хранить, сколько раз в секунду вы будете запрашивать таблицу? В целом, я бы сказал, что ваш физический дизайн будет страдать от такого типа хранилища, но аппаратное обеспечение преодолеет эти недостатки дизайна для большого числа приложений. Если вы не работаете с крупномасштабной датой или крупномасштабной транзакцией, все будет в порядке с чем угодно.

...