Как определить связь между activerecord и activeresource, используя внешние ключи?

У меня есть модель локального пользователя, которая использует activerecord. У пользователя есть поле электронной почты. У меня также есть модель активных ресурсов, называемая задачами, в которой есть поле create_by, в котором хранится адрес электронной почты отправляющих пользователей. Я хотел бы связать их, но я борюсь с правильным синтаксисом или даже с тем, возможно ли это.

Основная ветка ActiveResource, похоже, даже не поддерживает внешний ключ. Я нашел альтернативную ветку, но все равно ничего не получилось.

class User < ActiveRecord::Base
   has_many :tasks
end

class Task < ActiveResource::Base
  belongs_to :user
  schema do
    string 'created_by' #email
    # other fields
  end
end

2 ответа

Ваш код должен работать нормально, если у вас есть user_id атрибут на Task действовать как внешний ключ, или вы можете указать внешний ключ в ассоциации на User модель следующим образом:

class User < ActiveRecord::Base
  has_many :tasks, foreign_key: "uid"
end

Теперь проблема в том, что вы не можете использовать belongs_to на ActiveResource так что если вам не нужно получить user из экземпляра Task класс, вы можете просто удалить его, и другая сторона отношения будет по-прежнему работать, однако, если вам нужно получить user тогда вам придется реализовать свой собственный метод поиска следующим образом:

class Task < ActiveResource::Base
  schema do
    string 'created_by' #email
    # other fields
  end

  def user
    @user ||= User.find self.user_id # use the attribute name that represents the foreign key
  end

  def user=(user)
    @user = user
    self.update_attribute(:user_id, user.id)
  end
end

Это будет в основном вести себя так же, как вы ожидаете на ActiveRecord модель, однако это может быть утомительно, если у вас есть несколько ассоциаций, поэтому вы можете вместо этого расширить ActiveResource модуль для добавления belongs_to следующее:

module BelongsToActiveResource

    def self.included(base)
      base.extend(ClassMethods)
    end

    module ClassMethods

    def belongs_to( name, options = {} )
      class_eval %(
        def #{name}
          @#{name} ||= name.to_s.classify.find( name.id )
        end

        def #{name}=(obj)
          @#{name} ||= obj
          self.update_attribute((name.to_s + "_id").to_sym, @#{name}.id
        end
      )
    end

  end

end   

ActiveResource::Base.class_eval { include BelongsToActiveResource }

Это позволит вам использовать own_to на любом ActiveResource модель.

PS: вышеприведенное решение было вдохновлено /questions/948104/relsyi-310-prinadlezhat-activeresource-bolshe-ne-rabotaet/948113#948113

Вы не можете, но вы можете подделать это, внедрив методы доступа самостоятельно.

class User < ActiveRecord::Base
  #has_many :tasks
  def tasks
    Task.find(:all, params: {created_by: email})
  end
end

class Task < ActiveResource::Base
  #belongs_to :user
  def user
    User.where(email: created_by).first
  end

  schema do
    string 'created_by' #email
    # other fields
  end
end

Это позволит вам написать код, как если бы ваши объекты были связаны (т.е. User.first.tasks.length). Тем не менее, они на самом деле не присоединились. Это значит звонить User.first.tasks собирается попасть в базу данных, а затем сделать дополнительный HTTP-запрос для получения задач. В зависимости от структуры вашего кода вы можете столкнуться с неожиданными проблемами с производительностью.

Кроме того, вы не можете выполнить один запрос, чтобы получить пользователя и все связанные задачи (так как это два отдельных хранилища данных), и вы не можете делать такие причудливые вещи, как User.joins(:tasks).where({tasks: field_1: true}),

Другие вопросы по тегам