Rails Devise在控制器中构建嵌套模型

时间:2014-02-13 21:06:18

标签: ruby-on-rails devise controller

我正在使用Devise并尝试在RegistrationsController中构建嵌套模型。

虽然这不起作用。我可以通过

构建嵌套模型
resource.build_nested_model

在视图中,但不在控制器本身中。

这是我 registrationscontrollers的新动作

  def new
    super
    resource.build_user_info
    resource.user_info.languageskills.build
    if params[:is_driver].to_i == 1
      resource.build_driver
    end
    Rails.logger.debug(resource.build_user_info.inspect)
  end

这是它生成的输出

Started GET "/en/sign_up?is_driver=1" for 127.0.0.1 at 2014-02-13 13:20:01 +0100
Processing by RegistrationsController#new as JS
  Parameters: {"is_driver"=>"1", "locale"=>"en"}
  Rendered registrations/_new_user_fields.html.erb (12.1ms)
  Rendered registrations/new.html.erb within layouts/application (27.8ms)
  Rendered layouts/_header.html.erb (2.8ms)
  Rendered layouts/_messages.html.erb (0.2ms)
  Rendered layouts/_footer.html.erb (0.6ms)
   (0.2ms)  begin transaction
   (0.1ms)  commit transaction
#<UserInfo id: nil, user_id: nil, first_name: nil, last_name: nil, year_of_birth: nil, city: nil, created_at: nil, updated_at: nil, gender_id: nil, interests: nil, about: nil, country_alpha2: nil>
Completed 200 OK in 117ms (Views: 96.5ms | ActiveRecord: 0.4ms)

为什么不可能?我想当我构建关联模型时,设计不会保存对资源的更改。我看到的唯一出路是定义我自己的变量,其中包含更新资源的完整副本。不过,这不是一个好习惯。

你会做什么?

1 个答案:

答案 0 :(得分:1)

我认为问题在于默认RegistrationsController.new只是:

def new
  build_resource({})
  respond_with self.resource
end

(这取决于你的设计版本,但在相当长的时间内似乎是这个或相当的。)

这意味着在您覆盖的respond_with中添加嵌套模型之前,视图会呈现(new),因为您在调用super后执行此操作。我认为你有两个选择:

  1. 请勿致电super。只需将new的第一行放在new的开头,将最后一行放在默认new的最后一行。
  2. 覆盖build_resource而不是new。在被覆盖的build_resource开始时,请致电super,然后在new super之后添加build_resource中的代码。您需要做的唯一额外事情是检查build_resource是使用nil调用还是空哈希,在这种情况下,您构建空白user_info等,或者是否使用非调用-empty hash然后不添加你的空白user_info等,因为build_resource必须是从create调用的,所以哈希将包含你的用户在表单上为user_info输入的内容,所以你不要我想用空白版本覆盖! (你也许可以查看当前的url或类似的东西,而不是检查hash参数,但我个人更喜欢那样。)
  3. 我过去曾使用过选项2。我喜欢它,因为它仍然调用super,所以我们仍然使用设计build_resource的实现,而选项1完全忽略了设计new的实现 - 如果它们使一些重要将来你改为他们的new你会错过吗? (例如,曾经有一个resource变量位于new的本地变量,但它现在位于self,正如您在上面的代码中所看到的那样。)选项2只是更加繁琐因为您需要检查是否应该添加空白的user_info等。所以这取决于您的口味!