: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 должны быть методы, обертывающие эти объекты. эти проблемы выходят за рамки этой проблемы.)

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