1

topic_id当我通过 PUT 请求更改外键(在我的情况下)时,控制器似乎不知道帖子的“位置” 。

我不完全确定为什么会发生这种情况,但是在为此挣扎了几天之后,我真的需要一些见解。这个应用程序应该更新一个名为的对象post,除此之外,分配一个topic_id. 该Topic模型通过 PostsController 通过 has_many (posts) belongs_to (topic) 关系进行更新。

事实 + 对象通过控制台和浏览器创建、编辑和销毁 + 当我手动更改 topic_id 时,帖子在浏览器中可见

我怀疑我的控制器应该受到责备,但不确定。

问题

  • 为什么我的重定向不起作用?

问题示例:

  1. 考虑以下路线:localhost:3000/blog/topics/3/posts/1. 当我将此记录更新到topic_id = 1浏览器时,会返回以下异常:

    ActiveRecord::RecordNotFound in Blog::PostsController#show

    找不到 id=1 的帖子 [WHERE "posts"."topic_id" = 3]

  2. 不奇怪。但是,当我真正去路线时localhost:3000/blog/topics/1/posts/1,对象就存在了。此外,当主题更新时,posts 对象会从索引中消失——但这完全是另一回事。

  3. 我尝试通过以下方式重构我的重定向,它们都重新创建了上述相同的错误:

    • 重定向到 blog_topic_post_url([@topic,@post])..
    • 重定向到 blog_topic_post_url([@post])..
    • 重定向到 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 %>
4

3 回答 3

1

如果您观察到更新代码,它会重定向到带有旧主题对象的发布 url。实际上它应该更新一个,即@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

于 2012-02-25T18:09:16.593 回答
0

你应该这样做@topic.update_attributes(params[:post])吗?这似乎是有问题的。应该是@topic.update_attributes(params[:post][:topic])吗?

另外,我认为您的第一个重定向失败了,因为您使用的是在Topic中找到的原始fetch_topic文件,该原始文件不再与Post. 您可能只是明确地传递新的帖子主题:

redirect_to blog_topic_post_url([@post.topic, @post])
于 2012-02-25T16:06:06.090 回答
0

这可能是排序问题,fetch_post 需要设置@topic,因为两者都在 before_filter 中。

你可以发布错误吗?

于 2012-02-24T00:31:04.273 回答