Controller PUTs both old value and new value?
-
12-11-2019 - |
Вопрос
The controller does not update seem to know 'where' a post goes when I change the foreign key (in my case topic_id
) via a PUT request.
I am not entirely sure why this happens, but after struggling with this for a few days I really need some insight. This application is supposed to update an object called post
and among other things, assign a topic_id
. The Topic
model is updated via the PostsController via a has_many (posts) belongs_to (topic) relationship.
Facts + Objects are created, edited and destroyed via console and from browser + When I manually change the topic_id the post is visible in the browser
I suspect my controllers are to blame, but not sure.
Question
- Why is my redirect not working?
Example of Problem:
Consider the following route:
localhost:3000/blog/topics/3/posts/1
. When I update this record totopic_id = 1
the browser returns the following exception:ActiveRecord::RecordNotFound in Blog::PostsController#show
Couldn't find Post with id=1 [WHERE "posts"."topic_id" = 3]
Not surprising. But, when I actually go to the route
localhost:3000/blog/topics/1/posts/1
the object is present. Also, posts objects vanish from the index when the topic is updated-but that is another matter entirely.I have tried refactoring my redirect in the following ways and they all recreate the same error above:
- redirect_to blog_topic_post_url([@topic, @post])..
- redirect_to blog_topic_post_url([@post])..
- redirect_to blog_topic_post_url(@post)..
When I try the first two redirect_to calls the route redirects to http://localhost:3000/blog/topics/blog/1/3/posts/3
, demonstrating the object is storing both topics (1 and 3)???
Object Parameters
{"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"}
Here are my work steps:
Controller
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 %>
Нет правильного решения