2014-02-13 5 views
0

Я использую Devise и пытаюсь построить вложенные модели в своем RegistrationsController.Rails Devise Построить вложенную модель в контроллере

Хотя это не работает. Я могу построить вложенные модели через

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

Я думаю, что проблема в том, что по умолчанию 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 и т. Д., Или если он был вызван с непустым хэшем, тогда не добавляйте ваш пустой user_info и т. д., потому что build_resource должен был быть вызван от create, поэтому хеш будет содержать то, что ваш пользователь ввел в форму для user_info, поэтому вы не хотите перезаписывать пустую версию! (возможно, вы можете проверить текущий URL-адрес или что-то подобное вместо проверки параметра хэша, но мне лично это нравится немного меньше.)

Я использовал опцию 2 в прошлом. Мне нравится, потому что он по-прежнему вызывает super, поэтому мы по-прежнему используем реализацию devision build_resource, тогда как опция 1 полностью игнорирует реализацию devision new - и что, если они в будущем вносят некоторые важные изменения в их new, которые вы затем упускаете на? (Например, когда-то была переменная resource, локальная по отношению к new, но теперь она находится на self, как вы можете видеть в приведенном выше коде.) Вариант 2 - это немного более странно, потому что вам нужно проверить, нужно ли добавлять пустую user_info и т. Д. Так что это зависит от вашего вкуса!

Смежные вопросы