Not updating attribute in my rails app - ruby-on-rails

I have creating a web application using Ruby on Rails but now I'm troubling a issue which is post updating, I'm trying to solve this issue which followed this also this. Below is my code:
def update
#edit = Post.find(params[:post_id])
params.permit!
if #edit.update_attributes(params[:post])
redirect_to home_path
flash[:notice] = "Your post updated"
else
flash[:notice] = "Wrong"
end
end
When I use this code then showing
When assigning attributes, you must pass a hash as an argument.
After that
def update
#edit = Post.find(params[:post_id])
params.permit!
if #edit.update_attributes(update_params)
redirect_to home_path
flash[:notice] = "Your post updated"
else
flash[:notice] = "Wrong"
end
end
private
def update_params
params.require(:post).permit(:title, :details, :summery)
end
When I use this then showing
param is missing or the value is empty: post
Where is my actual fault?

It's your form that is causing this error. It means that you aren't passing the values nested inside post. If you view your params (raise params.inspect) you'll be able to see that post doesn't exist.
If you use form_for (or simple_form or formtastic) this is handled for you, but if you are using form_tag or manually creating a form with HTML, or submitting data via ajax you need to add this.
In ajax, you can add by serializing the data before submitting - in a form_tag you can do it this way:
form_tag post_path(#post)

Related

Ruby on rails passing object in named routes

I was reading rails guides - http://guides.rubyonrails.org/
I am not able to understand the syntax: redirect_to #article inside the method :
def create
#article = Article.new(article_params)
if #article.save
redirect_to #article
else
render 'new'
end
end
and also I am not able to comprehend the syntax- url: article_path(#article)
inside the defination of form
<%= form_for :article, url: article_path(#article), method: :patch do
Here we are creating a Article using create method. The block is first creating a article using the article_params send from the form and if the newly created Article is saved to database then we are redirected to the article itself else we are redirected to the form showing errors.
When you create any article in RoR platform then ideal tutorial is This guide, when you use Rails form then don't need to mention method because rails form built in some method like get post put/patch & destroy he automatically understood what kind of your request just follow this also this
def create
#article = Article.new(article_params)
#article.save
redirect_to #article
end
private
def article_params
params.require(:article).permit(:title, :text) #-> passing article parameters
end

Where does params[:id] come from in rails?

I am a beginner of Rails. I am learning rails with the book 'Beginning Rails 4' now. I want to ask you about 'parameter' passed to params method. The following is one of typical rails controllers.
class CommentsController < ApplicationController
before_action :load_article
def create
#comment = #article.comments.new(comment_params)
if #comment.save
redirect_to #article, notice: 'Thanks for your comment'
else
redirect_to #article, alert: 'Unable to add comment'
end
end
def destroy
#comment = #article.comments.find(params[:id])
#comment.destroy
redirect_to #article, notice: 'Comment Deleted'
end
private
def load_article
#article = Article.find(params[:article_id])
end
def comment_params
params.require(:comment).permit(:name, :email, :body)
end
end
Yes, this is just a typical comment controller used to create a comment attached to an article. The Comment model 'belongs to' the Article model, and the Article model 'has many' comments.
Take look at the destroy method.
def destroy
#comment = #article.comments.find(params[:id])
-- snip --
end
It finds the comment associated with the article by find(params[:id]). My question is, where on earth does params[:id] come from?
Does it come from URL? Or does rails save params hash automatically whenever any comment record is created? So we can find any comment by find(params[:id])?
The load_article method is similar.
def load_article
#article = Article.find(params[:article_id])
end
It finds an article by params[:article_id]. Where does this params[:article_id] come from? How does rails find an article by this?
params[:id] is meant to be the string that uniquely identifies a (RESTful) resource within your Rails application. It is found in the URL after the resource's name.
For example, for a resource called my_model, a GET request should correspond to a URL like myserver.com/my_model/12345, where 12345 is the params[:id] that identifies that specific instance of my_model. Analogies follow for the other HTTP requests (PUT, DELETE etc) and their RESTful counterparts.
You should read about Rails routing and its interpretation of RESTful architecture if you're still confused about these concepts and terminologies.
params[:id] does come from the URL. When you use resources in your routes file, Rails will automatically generate the standard REST routes for you. In your destroy example, that would usually be a be a request to /comments/:id using the DELETE HTTP method, in which that :id is added to the params hash, i.e. params[:id].

How do I display the name of a deleted element in Ruby on Rails?

I have a simple Rails application where I create objects (such as posts). So far I can edit and delete them, one by one, but now I want to have a <%= notice %> echoing the name of the deleted object after confirming its deletion. Is this possible? If so, how?
This is an extremely common task in Rails, and the idiomatic solution is to forward some data about the deleted record to the subsequent GET request via the the flash array.
Your controller's destroy action should look something like this:
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to posts_path, notice: "#{#post.name} was deleted"
end
In your index action, you'll be able to access flash[:notice] to get the string generated in the previous action.
You need to store the details you want to echo (e.g. the name) somewhere, because the object itself will be gone after a redirect. I would use the flash for that:
# in the controller
def destroy
thing = Thing.find(params[:id])
thing.destroy
redirect_to things_path, :notice => "Thing #{thing.name} was deleted"
end
# in the index view
<% if flash[:notice] %>
<div class="notice"><%= flash[:notice] %></div>
<% end %>

Redirect_to in Rails 4

For example I have a controller PostController in RoR 4. and actions in it:
def index
#posts = Post.all.order('created_at DESC')
end
def new
#post = Post.new #second question
end
def create
#post = Post.new(post_params)
post.save
redirect_to #post #first question
end
def show
#post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:title, :body)
end
so, the first question is: Why when we write redirect_to #post it automatically redirect to show/id? How rails know, that it must go to show view?
second question: why I must write #post = Post.new in new action? when I comment it, I also can create a Post. What is the deference write it in new action or missing it?
I'm new in rails and there are many magic in it
Q1). This is part of one of main RoR's mantras - convention over configuration. It just assumes, when performing redirect_to #post, you actually want to see the #post resource. The standard REST action of "reading" the resource is show.
But, if - for example - in your view you will do something like
<%= link_to #post.title, #post, method: :delete %>
What will be generated by that will take you to destroy action of #post's resource.
Having conventions like this make you write less code, and - make you happy!
Q2). I'm surprised if what you mentioned worked. It shouldn't, because similar magic is performed in your form_for #post tag in your views. If #post is empty, form_for shouldn't be able to resolve what url to generate, or how to behave in general - depending on Post.new stored in #post it assumes you want to create the resource, and prepare your <form> tag to submit with POST method, but if in #post there is stored already persisted resource, say Post.find(1), it will create the <form> to be submitted with PATCH method.
Again - based on convention, you can write less code, to achieve more.
I strongly advise against omitting something like #post = Post.new. It may lead to hard to identify bugs, even if it worked for you at the moment
Hope it clarifies things!
Good luck!
First questions: it redirects you to the show page using the url_for method (you can read its source if you are curious), remember that #book has an id so it takes that id and includes it in the url of the /books/:id
Second question : you need #post for when you submit an invalid form, then #post will be populated with the errors and displayed on the new page. try to submit an invalid post, you will get complains about a not defined method.
to display the errors of an invalid submission :
<%= form_for :post posts_path do |f| %>
<% if #post.errors.any? %>
See how we used #post above? just to get the errors in it.
When passing a record to redirect_to the url will be generated by calling url_for, which will return a named url for that record. For this it uses the class name for lookup. So passing the Post record will attempt to use the post_path route with the original record as parameter which will resolve in /posts/:id.
First question
Rails magic.
As you pass an ActiveRecord object to redirect, the restful routing interprets this as you wanting to go to the show page of that object.
Plenty of different ways to use redirect_to here.
Second question
Usually #post = Post.new is required as you reference #post in the new action as your forms when constructed with form_for .. useful for validation and dealing with errors.
Technically you could use a form_tag and define Post.new right there in the form. This would mean the #post = Post.new is redundant and works when you comment it out. This way would mean you have no way to pass your objects errors back to the user on the new page though.

Ruby on Rails - Forbidden Attributes on params?

Im trying to redirect someone after they click a button and I keep getting the following error:
ActiveModel::ForbiddenAttributesError
Extracted source (around line #20):
It is throwing the error on the #post = Post.new line.
def create
#post = Post.new(params[:post])
if #post.save
redirect_to posts_path, :notice => "Your post was saved"
I am very new to Ruby and at the moment I am very confused of what this means. I am just following a tutorial and mine isnt working. If anyone could help that would be awesome :D
#post = Post.new(params[:post])
... is no longer used in the latest versions of rails. The problem is that it provided weak security. Someone who was updating their user profile (for example) could theoretically insert an attribute like "administrator: true" to change themselves into an administrator (if that's how admin flag is stored)
Strong parameters now require that you explicity specify which attributes you want to allow to be entered.
So nowadays we do...
#post = Post.new(post_params)
And we have a method later in the controller that specifies the permitted attributes, and looks like...
def post_params
params.require(:post).permit(:title, :body)
end
While I don't have quite enough of your code to specifically answer the question, I can probably get pretty close (minus some column/attribute naming). With strong_params now the standard for Rails applications, you'd probably be looking to do something more like:
def create
#post = Post.new(post_params)
if #post.save
redirect_to posts_path, :notice => "Your post was saved"
else
#other stuff here
end
end
private
def post_params
params.require(:post).permit(:content, ....etc) #I took a guess at the attributes you are passing through your params on the create.
end
For a little extra easy-reading on the history/reason: http://blog.8thlight.com/will-warner/2014/04/05/strong-parameters-in-rails.html
Let me know if you'd like any additional clarification.

Resources