:has_many,: через модели ActiveResource
Три модели в пользовательском Rails-приложении UserService:
class User < ActiveRecord::Base
has_many :services
has_many :members
has_many :groups, :through => :members
has_many :managed_groups, :class_name => "Group"
accepts_nested_attributes_for :managed_groups, :services, :groups
end
class Group < ActiveRecord::Base
has_many :members
has_many :users, :through => :members
belongs_to :manager, :class_name => "User", :foreign_key => :user_id
accepts_nested_attributes_for :users
end
class Service < ActiveRecord::Base
belongs_to :user
end
class Member < ActiveRecord::Base
belongs_to :group
belongs_to :user
end
Три модели ActiveResource в отдельном интерфейсе Rails
class User < ActiveResource::Base
self.site = "http://localhost:8801"
end
class Group < ActiveResource::Base
self.site = "http://localhost:8801"
end
class Service < ActiveResource::Base
self.site = "http://localhost:8801"
end
Из Front-end работает
Service.first.user_id = User.first
Потому что Service.user_id - это принадлежность... это одно свойство.
Однако я не могу сделать либо
User.first.groups << Group.first
или же
Group.first.users << User.first
Ничего не происходит, потому что ActiveResource просто порождает GET-запросы.
В интересах полноты, выполнение таких вещей, как следующие (на входной стороне) также не удается.
u = User.first
g = Group.first
u.groups.push(g)
и так далее. Я предполагал, что прохождение метода users_controller::update будет работать, но теперь я задаюсь вопросом, возможно ли это вообще.
Кто-нибудь сделал:has_many,: через две модели ActiveResource? Есть ли способ повлиять на коллекцию модели AR? Нужно ли манипулировать таблицей соединений вручную? (Тем самым создавая members_controller?)
1 ответ
Это может быть чем-то большим, чем Stackru- больше для основной команды.
Кажется, что либо ActiveResource глупо говорит о том, как он общается с RESTful-клиентом, либо ActiveRecord глупо говорит о том, как он слушает одного (или альтернативный и гораздо более вероятный вариант, эти две вещи просто принципиально не могут говорить с друг друга.)
То есть: учитывая User, Service и Group выше, мой внешний интерфейс после размещения запроса PUT на внутреннем сервере по адресу /users/1.xml внутренний журнал регистрирует следующие параметры (некоторые значения удалены для краткости):
{"user"=>
{"created_at"=>2011-06-23 02:58:15 UTC,
"id"=>1,
"name"=>"John Metta",
"updated_at"=>2011-06-23 02:58:15 UTC,
"managed_groups"=>[],
"services"=>[
{"created_at"=>2011-06-23 02:58:15 UTC,
"id"=>1,
"updated_at"=>2011-06-23 02:58:15 UTC,
"user_id"=>1}
],
"groups"=>[
{"created_at"=>2011-06-23 02:56:37 UTC,
"id"=>1,
"updated_at"=>2011-06-23 02:56:37 UTC,
"user_id"=>nil,
"users"=>[
{"created_at"=>2011-06-23 03:36:28 UTC,
"id"=>6,
"name"=>"Jefferey",
"updated_at"=>2011-06-23 03:36:28 UTC},
{"created_at"=>2011-06-23 02:59:36 UTC,
"id"=>2,
"name"=>"George",
"updated_at"=>2011-06-23 03:05:13 UTC}
]
},
{"created_at"=>2011-06-23 02:56:37 UTC,
"id"=>1,
"name"=>"Site Admin",
"updated_at"=>2011-06-23 02:56:37 UTC,
"user_id"=>nil,
"users"=>[
{"created_at"=>2011-06-23 03:36:28 UTC,
"id"=>6,
"name"=>"Jefferey",
"updated_at"=>2011-06-23 03:36:28 UTC},
{"created_at"=>2011-06-23 02:59:36 UTC,
"id"=>2,
"name"=>"George",
"updated_at"=>2011-06-23 03:05:13 UTC},
{"created_at"=>2011-06-23 02:58:15 UTC,
"id"=>1,
"name"=>"John Metta",
"updated_at"=>2011-06-23 02:58:15 UTC}
]
}
]
},
"id"=>"1"}
Итак, я вижу несколько проблем с ActiveResource (или, более вероятно, как я пытаюсь использовать ActiveResource), но главное заключается в следующем:
Поскольку ActiveResource, кажется, ничего не знает об ассоциациях, он просто тупо объединяет все. Другими словами, ActiveResource тупо говорит: "Да, у вас есть список групп, поэтому я назову его" группами "вместо того, чтобы знать, что для того, чтобы это действительно работало, нужно сказать:" Хм, у вас есть список групп, а Group - это другая модель, я назову ее groups_attributes, чтобы ее можно было перестроить в список групп на другом конце.
Теперь, прежде чем я разгорячился, я понимаю, что 'groups_attributes' - это словарное слово ActiveRecord, а не общее слово REST, поэтому, если ActiveResource начнет его использовать, он сломает, скажем, мой другой бэкэнд, работающий на Scala.
Однако, учитывая, что Rails должен быть в состоянии работать с Rails, и учитывая, что ActiveResource должен быть тупым в этом, тогда кажется, что ActiveRecord должен быть в состоянии выяснить, что "Эта входящая модель RESTful содержит объекты, которые сопоставляются известным моделям, которые ссылки, давайте попробуем создать эти модели и заставить его работать.
Работоспособное решение:
Я не думал об этом достаточно, чтобы чувствовать себя комфортно, предполагая, что ActiveRecord всегда должен автоматически пытаться отобразить включенные параметры входящего набора параметров с именами MODEL в MODEL. Это потребует дополнительного тестирования и обдумывания. Однако мое решение состояло в том, чтобы перехватить этот входящий набор параметров в users_controller примерно следующим образом:
…
begin
groups = []
params[:user][:groups].each do |g|
groups << Group.find(g[:id])
end
params[:user][:groups] = groups
rescue
# Do something not incredibly stupid here
end
…
Который, кажется, захватывает вещи относительно чисто. Я боюсь, что это кажется довольно громоздким для Rails- который обычно имеет гораздо более элегантные решения для вещей - и что я упускаю что-то простое.
(В интересах завершения я понимаю, что с этой строкой параметров есть и другие проблемы, например: поскольку я связываю группу с пользователем и пользователем с группой, я обязательно передаю тонну данных (например,, всю группу и всех ее пользователей), когда я передаю пользователя. Для этого нужен какой-то прокси-сервер, например список идентификаторов групп или что-то в этом роде. Скорее всего, в моих моделях ActiveResource должны быть методы, обертывающие эти объекты. эти проблемы выходят за рамки этой проблемы.)