当控制器在不同的模块中时,Rails 3响应create返回json或json格式的位置



在Rails 3.2.8中。如果你有这条路线:

namespace :some_module do
resources :some_models
end

并且相应的SomeModel不在模块中,那么在SomeModule::SomeModelsController中如果您将位置指定为模型实例(就像在创建中一样),那么它对url的假设将是错误的:

respond_with @some_model, location: @some_model

因为它将假设url是somemodel_instanceurl而不是somemodule somemodel_ininstanceurl。

出于某种原因,当我试图变得棘手,并在创建方法中对我认为正确的url进行通用评估时(因为这是在控制器中包含的通用模块中):

respond_with @some_model, location: send("#{self.class.name.chomp('Controller').gsub('::','_').underscore.singularize}_url")

结果是:No route matches {:action=>"show", :controller=>"some_module/some_models"}(它是复数,因此没有路由)

这似乎有点令人困惑。

但只是做:

respond_with @some_model

当控制器设置为通过:用json响应时

respond_to :json

对我来说,返回一个204,没有创建实例的id的指示,而且似乎需要一些包括id的指示,以便客户端使用它(在不返回id的情况下创建某些东西不是一个好做法)。

在与模型不同的模块中的控制器中的创建方法中使用responsd_with的正确方法是什么,并且我们希望返回所创建对象的id的一些指示?

在控制器中,如果控制器和模型都不是模块,那么要指定位置,可以使用:

respond_with @some_model, location: @some_model

但是,控制器在另一个模块中,因此如果您在控制器的创建方法中这样做,它将尝试评估方法some_model_url(id),但在控制器上定义的是some_module_some_model_url[id]。

因此,你可以这样做的方法之一是:

respond_with @some_model, location: some_module_some_model_url(@some_model.id)

对于包含在控制器中的通用模块,实例方法可能看起来像这样:

def initialize
super
qualified_controller_name = self.class.name.chomp('Controller')
@model_class = qualified_controller_name.split('::').last.singularize.constantize
@model_singular_name_url_method_name_sym = "#{qualified_controller_name.gsub('::','_').underscore.singularize}_url".to_sym
class_eval "def #{@model_singular_name}(id); #{@model_singular_name_url_method_name_sym}(id); end"
end
def create
@value = @model_class.new(...)
@value.save
respond_with @value, location: send(@model_singular_name_url_method_name_sym, @value.id)
end

这将在位置响应标头中以url的形式返回位置,因此在您的规范测试中,它可能会在发布后这样做:

location = response.headers['Location']
# now check that location looks correct, etc.

但是,正如一位同事所指出的,如果你定义,你不必指定位置

def some_module_some_model_url(record)
some_model_url(record)
end

所以,一般来说,添加这个:

class_eval "def #{@model_singular_name}_url(record); #{@model_singular_name_url_method_name_sym}(record); end"

然后你只需要:

def create
@value = @model_class.new(...)
@value.save
respond_with @value
end

最新更新