Контроллер ставит как старое, так и новое значение? - PullRequest
1 голос
/ 24 февраля 2012

Контроллер не обновляется, кажется, знает, «куда» отправляется сообщение, когда я меняю внешний ключ (в моем случае topic_id) с помощью запроса PUT.

Я не совсем уверен, почему это происходит, но после нескольких дней борьбы с этим мне действительно нужно понимание.Предполагается, что это приложение обновит объект с именем post и, среди прочего, назначит topic_id.Topic модель обновляется через PostsController через отношение has_many (posts) own_to (topic).

Facts + Объекты создаются, редактируются и уничтожаются через консоль и из браузера + КогдаЯ вручную изменяю topic_id сообщение видно в браузере

Я подозреваю, что виноваты мои контроллеры, но не уверен.

Вопрос

  • Почему мой редирект не работает?

Пример проблемы:

  1. Рассмотрим следующий маршрут: localhost:3000/blog/topics/3/posts/1.Когда я обновляю эту запись до topic_id = 1, браузер возвращает следующее исключение:

    ActiveRecord :: RecordNotFound в блоге :: PostsController # show

    Не удалось найти сообщение с id = 1 [ГДЕ"posts". "topic_id" = 3]

  2. Не удивительно.Но когда я действительно иду по маршруту localhost:3000/blog/topics/1/posts/1, объект присутствует.Кроме того, объекты публикаций исчезают из индекса при обновлении темы, но это совсем другое дело.

  3. Я попытался рефакторинг своего перенаправления следующими способами, и все они воссоздают ту же ошибкувыше:

    • redirect_to blog_topic_post_url ([@ topic, @post]) ..
    • redirect_to blog_topic_post_url ([@ post]) ..
    • redirect_to blog_topic_post_url (@post) ..

Когда я пытаюсь первые два вызова redirect_to, маршрут перенаправляет на http://localhost:3000/blog/topics/blog/1/3/posts/3, демонстрируя, что объект хранит обе темы (1и 3) ???

Параметры объекта

{"utf8"=>"✓",
 "_method"=>"put",
 "authenticity_token"=>"TibKWeeC8dGkxR8Jb4bQprGvllUBmiQ5+HtYAPlhn1Q=",
 "post"=>{"title"=>"---- maxime",
 "description"=>"---- et- facere- sunt- et- illo- reprehenderit- dolor- quis- debitis- vel",
 "content"=>"---\r\n- Et asperiores eaque rem maxime laboriosam. Quos dolor perferendis in labore fugit.\r\n  Delectus quam vero optio cum eius perferendis sed.\r\n- Veniam eum explicabo error minima. Dolore reprehenderit cumque reiciendis. Molestiae\r\n  quo est error aut quas ut aperiam quia.\r\n- Et at quo esse aut ut accusantium alias tempore. Accusamus consequuntur sunt mollitia.\r\n  Quas ut voluptate quia sit quia iste corporis. Id rerum placeat voluptas sequi non.\r\n",
    **"topic_id"=>"1",**
    "tags_attributes"=>{"0"=>{"_destroy"=>"0",
    "tag_name"=>"---- velit",
    "id"=>"1"},
    "1"=>{"_destroy"=>"0",
    "tag_name"=>"---- ea",
    "id"=>"2"},
    "2"=>{"_destroy"=>"0",
    "tag_name"=>"---- impedit",
    "id"=>"3"}}},
    "commit"=>"Update Post",
    **"topic_id"=>"3",**
    "id"=>"1"}

Вот мои рабочие шаги:

Контроллер

before_filter :fetch_topic,   only: [:show, :edit, :update, :destroy]
before_filter :fetch_post,    only: [:show, :edit, :update, :destroy]

def edit

end

def update 
 respond_to do |format|
  if @topic.update_attributes(params[:post]) and @post.update_attributes(params[:post])
   format.html {redirect_to blog_topic_post_url([@post]), success: 'Post was successfully updated.'}
   else 
    format.html {render :edit, error: 'Post was not updated. Please try again.'}
   end
  end
 end

 # I call these on both actions with before_filter. Works on all other relevant actions.
def fetch_topic
 @topic = Topic.find(params[:topic_id])
end

def fetch_post
  @post =  @topic.posts.find(params[:id]) 
end

form.html.erb

 <%= form_for([:blog, @topic, @post]) do |f| %>
  ...
  ...
 <div class="field">
   <%= f.fields_for(:topic) do |build_topic| %>
    <%= build_topic.label :topic_name, "Select a topic" %>
    <%= collection_select(:post, :topic_id, Topic.all - [@post], :id, :topic_name, prompt: true) %>
   <%end%>

  ....
<div class="actions">
 <%= f.submit %>
</div>
<% end %>

Ответы [ 3 ]

1 голос
/ 25 февраля 2012

Если вы наблюдаете за кодом обновления, он перенаправляет на ссылку со старым тематическим объектом. На самом деле он должен обновить тот, который @post.topic. Кроме того, вам не нужно обновлять объект темы.

def update 
  if @post.update_attributes(params[:post])
    flash[:success]  = 'Post was successfully updated.'
    redirect_to [@post.topic, @post]
  else 
    flash[:error] = 'Post was not updated. Please try again.'
    render :action => :edit 
  end
 end

Еще одна проблема - это внутренняя форма представления. При выборе коллекции вы не хотите отображать текущую тему, поэтому она должна быть Topic.all - @topic

0 голосов
/ 25 февраля 2012

Должны ли вы делать @topic.update_attributes(params[:post])?Кажется, это было бы проблематично.Должно ли это быть @topic.update_attributes(params[:post][:topic])?

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

redirect_to blog_topic_post_url([@post.topic, @post])
0 голосов
/ 24 февраля 2012

Это может быть проблемой упорядочения, fetch_post требует установки @topic, поскольку оба находятся в before_filter.

Можете ли вы опубликовать ошибку?

...