: has_many,: через модели ActiveResource - PullRequest
2 голосов
/ 23 июня 2011

Три модели в бэкэнд-приложении UserService Rails:

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

В интерфейсе это работает, чтобы сделать

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,: through с двумя моделями ActiveResource?Есть ли способ повлиять на коллекцию модели AR?Нужно ли манипулировать таблицей соединений вручную?(Тем самым создавая member_controller?)

1 Ответ

0 голосов
/ 23 июня 2011

Это может быть нечто большее, чем StackOverflow, больше для основной команды.

Кажется, что либо ActiveResource глупо о том, как он общается с RESTful-клиентом, или ActiveRecord глупо о том, как он слушает одного (или альтернатива, и гораздо более вероятный вариант, эти две вещи просто принципиально не могут разговаривать друг с другом.)

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

...