2

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

单独的 Rails 前端中的三个 ActiveResource 模型

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 是一个belongs_to……它是一个单一的属性。

但是我也做不到

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 方法会起作用,但现在我质疑这是否可能。

有人用两个 ActiveResource 模型做过 :has_many, :through 吗?有什么方法可以影响 AR 模型的收集吗?我需要手动操作连接表吗?(从而创建一个members_controller?)

4

1 回答 1

0

这可能不仅仅适用于 StackOverflow,也适用于核心团队。

似乎ActiveResource 对它如何与 RESTful 客户端对话是愚蠢的,或者ActiveRecord在它如何听一个方面是愚蠢的(或者,替代方案,更有可能的选择,这两件事根本无法对话另一个。)

也就是说:给定上面的用户、服务和组,我的前端,在 /users/1.xml 的后端服务器上放置 PUT 请求后,后端记录以下参数(为简洁起见删除了一些值) :

{"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 愚蠢地说“Duh,你有一个组列表,所以我称它为'组'”而不是知道,为了让它真正起作用,它应该说“Hrm,你有一个组列表,而 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 来说似乎相当庞大——它通常有更优雅的解决方案——而且我缺少一些基本的东西。

(为了完成,我意识到该参数字符串还有其他问题,例如:由于我将组与用户捆绑在一起,并将用户与组捆绑在一起,因此我必然会传递大量数据(例如, 整个组, 以及所有它的用户) 当我传递用户时. 这需要某种代理 - 比如组 ID 列表或其他东西. 更有可能的是, 我的 ActiveResource 模型应该有包装这些对象的方法. 我正在考虑这些问题超出了这个问题的范围。)

于 2011-06-23T15:48:39.180 回答