Как использовать ActiveResource с мелкими вложенными маршрутами?

У меня есть приложение Rails, у которого есть ресурс компании с вложенным ресурсом 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, потому что маршрут/компании/: company_id/employees/: id не определен, когда используются мелкие маршруты.

Чтобы читать, редактировать и удалять сотрудников, я могу использовать:

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

Но тогда, похоже, не существует способа создать новых сотрудников из-за отсутствия внешних маршрутов компаний.

Одним из решений было бы определить отдельные классы CompanyEmployee и Employee, но это кажется слишком сложным.

Как я могу использовать один класс Employee в ActiveResource для выполнения всех четырех операций CRUD?

Ответы

Ответ 1

Существует защищенный метод экземпляра с именем 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 документируется иначе, чем в методе clone, поэтому это может измениться в будущих выпусках.

Ответ 2

Я использую 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

Он заменит: company_id значением из prefix_options.

Ответ 3

Смотрите эту статью: 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 })