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].
Related
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
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)
I'm working through the Apress "Beginning Rails 4, 3rd edition" book. The book introduces you to Rails by building a blog application step by step. I'm about halfway through, and have received the following error message:
ActiveModel::ForbiddenAttributesError in CommentsController#create
I've traced this to my comments_controller.rb file, which looks like this:
class CommentsController < ApplicationController
before_filter :load_article
def create
#comment = #article.comments.new(params[:comment])
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
end
Specifically, the problem seems to be caused by line 5:
#comment = #article.comments.new(params[:comment])
From what I've gathered, the problem seems to be that the book I'm working through was written for an earlier version of Rails. I'm using Rails 4.2.0, and it seems that I ned to use different syntax. What do I need to change to get my code to work?
You need a method that's private in your controller called comment_params (convention, you could call it anything)
Controller:
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
private
def comment_params
params.require(:comment).permit!
end
It's called strong_parameters and is a gem so you can google it to find it on github
params.require(:comment).permit! will permit anything though, you will probably want to limit it by passing attributes params.require(:comment).permit(:name, :message) - assuming you have name and message attributes.
You'll want to replace params[:comment] with the call to the comment_params method in your update method if you have one.
you need to do this before you create your model object. Rails has to sanitize the parameters before you are allowed to put it in there.
comment_params = params.require(:comments).permit(:attribute1, :attribute2)
#comment = #article.comments.new(comment_params)
Under the method load_article add the following method:
def comment_params
params.require(:comment).permit( ... )
end
and replace the three dots with the attributes you need to allow.
Then in your create function you can write
#comment = #article.comments.new(comment_params)
You will probably need to do something similar in your update function.
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.
A newbie question regarding the ActiveRecord's save method.
If i have this code (as in rails guide):
def create
#post = Post.new(params[:post])
if #post.save
redirect_to #post
else
.....
end
end
The save method returns the new created Post object? How, after the code #post.save, rails know how to substitute the redirect_to #post with the proper post_id (1 or 2 or 3 or ....) to build the link?
It's an OOP concept.
So, after create, the #post is updated with the id, and everything just works.
Take a look at this code.
Hope it helps.
I'm going to explain it by presenting another piece of code that should make things easy to understand
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
Now :user contains the following information based on the User model: id, name, email, telephone.
So that means we have actually assigned to #user the above hashes.
The redirect_to will retrieve the hashes that is already stored in #user and display the new profile page.
I hope it helped.