如何在浅层嵌套路由中使用ActiveResource?

16

我有一个Rails应用程序,具有一个名为Company的资源,并带有嵌套资源Employee。我正在使用浅层路由,因此要操作Employee,我的路由如下:

GET     /employees/1
PUT     /employees/1
DELETE  /employees/1
POST    /companies/1/employees

如何使用ActiveResource创建、读取、更新和删除雇员?

要创建雇员,可以使用以下代码:

class Employee < ActiveResource::Base
  self.site = "http://example.com/companies/:company_id"
end

但如果我尝试这样做:

e=Employee.find(1, :params => {:company_id => 1})

当使用浅层路由时,我会收到404错误,因为路由/companies/:company_id/employees/:id未定义。

要阅读、编辑和删除员工,我可以使用:

class Employee < ActiveResource::Base
  self.site = "http://example.com"
end

由于公司的外部路由缺失,似乎没有办法创建新的员工。

一种解决方案是定义不同的CompanyEmployee和Employee类,但这似乎过于复杂。

我如何在ActiveResource中使用单个Employee类执行所有四个CRUD操作?

4个回答

14

我正在使用Rails 3.0.9。你可以这样设置前缀:

class Employee < ActiveResource::Base
  self.prefix = "/companies/:company_id/"
end

然后

Employee.find(:all, :params => {:company_id => 99})
或者
e = Employee.new(:name => "Corey")
e.prefix_options[:company_id] = 1

它会用 prefix_options 中的值替换 :company_id。


10

你可以重写名为collection_path的受保护实例方法。

class Employee < ActiveResource::Base
  self.site = "http://example.com"

  def collection_path(options = nil)
    "/companies/#{prefix_options[:company_id]}/#{self.class.collection_name}"
  end
end

那么你就能用这个来创建员工。

e = Employee.new(:name => "Corey")
e.prefix_options[:company_id] = 1
e.save

似乎除了在克隆方法中,prefix_options并未被文档记录下来,所以这可能会在未来的版本中有所改变。


工作得很好,只是我需要使用"/companies/#{prefix_options[:company_id]}/#{self.class.collection_name},xml",否则POST不会被解释为XML。 - Rich Apodaca
4
应该使用 self.prefix = "/companies/:company_id/" 代替覆盖 collection_path - tybro0103

0
我发现最好覆盖ActiveResource :: Base.element_path,并使用库中定义的相同功能,但在返回值中省略prefix_options的使用。没有。
class Employee < ActiveResource::Base
  self.site = 'http://example.com'
  self.prefix = '/companies/:company_id/'

  # Over-ride method and omit `#{prefix(prefix_options)}` from the returned string
  def self.element_path(id, prefix_options = {}, query_options = nil)
    "/#{collection_name}/#{URI.parser.escape id.to_s}.#{format.extension}"
  end
end

Employee类将像往常一样运行,无需像其他解决方案中建议的那样为实例分配prefix_options。

0
请参考这篇文章:http://blog.flame.org/2009/11/04/activeresource-and-shallow-nested-routes.html 在这里,作者建议覆盖类方法collection_path。这是有道理的,因为该方法也被new_element_path使用,并且在两种情况下都会检索相同的路径。
例如:
class Employee < ActiveResource::Base
  self.site = "http://example.com"

  def self.collection_path(prefix_options = {},query_options=nil)
    super
    "/companies/#{query_options[:company_id]}/#{collection_name}.#{format.extension}#{query_string(query_options)}"
  end
end

你可以通过以下方式为公司找到员工:

company = Company.find(:first)
Employee.find(:all, :params => {:company_id => company.id })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接