2012-04-11 5 views
7

У меня есть волшебник формы в Rails 3. В принципе, я создаю объект отеля, а затем, когда все это будет завершено, я хочу создать объект местоположения для этого Гостиница. Мой код контроллера для создания отеля выглядит следующим образом:Рельс 3: переменная экземпляра недоступна после перенаправления

def create 
    @hotel = Hotel.new(params[:hotel]) 

    respond_to do |format| 
     if @hotel.save 
     @location = Location.new 
     format.html { redirect_to '/set_location'} 
     else 
     format.html { render action: "new" } 
     end 
    end 
    end 

Затем на странице «/ set_location» У меня есть форма, которая устанавливает местоположение. Тем не менее, я получаю ошибку 'undefined method model_name for NilClass:Class' на html.erb для переменной экземпляра @location.

Это действительно странно, когда я использую render '/ set_location' вместо redirect_to, тогда он отлично работает. Тем не менее, я хочу использовать метод redirect_to, чтобы предотвратить дублирование записи.

Заранее благодарим за помощь.

+1

что дубликатом представление об ошибке? redirect_to перенаправляет вас к другому действию контроллера, если у вас нет установленной переменной экземпляра, он будет терпеть неудачу. – shime

+0

Его дубликат _record_ подчинения - в основном дубликаты данных, находящихся в базе данных. Означает ли это, что переменные экземпляра, которые я имел в одном действии контроллера, теряются после того, как я ударил другого? Есть ли способ передать переменные между этими действиями? Положить его на сеанс, может быть? Плохая практика нет? – Ger

ответ

15

HTTP является без гражданства по дизайну. Если вы хотите разделить состояние между запросами (перенаправление ведет к другому запросу), вы должны использовать хэш-код session. Как это:

session[:hotel_id] = @hotel.id 

И тогда вам получить Hotel в /set_location так:

Hotel.find(session[:hotel_id]) 
+1

Как это поможет устранить недостаток @location? – Nobita

+0

Это не поможет. Переменные не могут передаваться между запросами. Я думаю, что автор получил идею: использовать сеансы. – jdoe

1

Я считаю, что вы хотите сделать, это:

  1. Определить, какой контроллер и действие отвечает к запросу «/ set_location».
  2. Там вы увидите, что вам не хватает этой строки @location = Location.new. Вам нужно создать его там.

Переменные в Rails часто используются для передачи информации между контроллером и вашей точки зрения, и поэтому при выполнении визуализации, вы не получите эту ошибку. Представления Rails знают о переменных экземпляра из контроллеров.

Однако вы делаете перенаправление, и поэтому вы вызываете другого контроллера, который понятия не имеет, что такое @location.

0

Я считаю, что ответ Нобита здесь является наиболее полным и отвечает на точный вопрос ОП. Пожалуйста, проголосуйте (@Ger).

В ответе jdoe я ожидал бы или хотел бы увидеть больше объяснений вокруг его/ее (jdoe's) использования «запроса» в своих объяснениях, поскольку «запрос» можно интерпретировать как запрос на представление (или шаблон) в других рамках, так что это заявление может быть немного вводит в заблуждении нового разработчика Rails (включая меня) при чтении с точки зрения Rails:.

«Переменные не может быть передан между запросами Я думаю, что автор получил Идея: использовать сеансы ».

В некотором смысле переменные действительно могут передаваться, когда вы запрашиваете представление/шаблон с контроллера с помощью «рендеринга». Поэтому, если ваш метод контроллера отображает представление, это представление будет знать о @variable, которое вы определили в этом контроллере.

Кроме того, использование сеансов на самом деле не является единственным способом передачи переменной между запросами.Вы можете изменить ваш перенаправлены на маршрут, чтобы поймать переменную:

Рассмотрим (в routes.rb файле):

match 'surveys/result(/:id)' => "surveys#result", via: [:get], as: 'surveys_result' 

Теперь, в «обследования» контроллера «результат» метод действия вы будете иметь :id параметр. Вы бы назвали его params[:id], например, чтобы найти объект в своей базе данных с этим идентификатором. Я считаю, есть также способ скрыть :id из URI/URL, если вы не хотите, чтобы пользователь видел его там.

@shime: В связи с вашим вопросом о «двойной записи», я считаю, что OP ссылается на визуализацию представления по запросу POST. Представьте, что если POST был успешным, вы можете отправить дублируемую запись в базу данных при каждом обновлении страницы после того, как вы уже отправили эту форму (метод перенаправления заботится о том, чтобы этого не произошло, и, таким образом, это стандартный способ на пути из ваших запросов POST) и в этом пункте я нашел имеет одну из самых ясных объяснений того, что происходит на обеих реализаций:

https://gist.github.com/jcasimir/1210155#redirect

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