Как определить связь между 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})
,