Proper Edit And Update Method In RUBY ON RAILS - ruby-on-rails

the update method doesn't update the record, it creates a new one.
how can I change the code to do the proper job?
here the controller bit:
def edit
#post = Post.find(params[:id])
end
def update
if #post.update(post_params)
redirect_to #post
else
render 'edit'
end
end
the edit view:
= form_for :post, url: posts_path do |f|
%p
= f.label :title
= f.text_field :title
%p
= f.label :content
= f.text_area :content
%p
= f.submit

Change your form tag:
= form_for #post do |f|
It isn't using the variable you set up in your controller so it doesn't know it isn't a new object.
You also shouldn't need to specify the url, so long as you have the resource defined in your routes file.

Related

Rails 5.0 Error: ActiveModel::ForbiddenAttributesError [duplicate]

This question already has answers here:
ActiveModel::ForbiddenAttributesError when creating new user
(8 answers)
Closed 6 years ago.
I'm attempting to make a blog post on my web-app updatable from the browser, but when I click update in the edit for, I get this error:
ActiveModel::ForbiddenAttributesError
error in pots_controller line 33:
if #post.update_attributes(params[:post])
this is my edit.html.erb code:
<h1>Edit Post</h1>
<%= form_for #post do |f| %>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %><br />
</p>
<p>
<%= f.label :body %><br />
<%= f.text_field :body %><br />
</p>
<p>
<%= f.select :category_id, Category.all.collect {|x| [x.name, x.id]}, {:include_blank => "Select One"} %><br />
</p>
<p>
<%= f.submit "Update post" %>
</p>
<% end %>
<%= link_to "Go Back", post_path %>
this is my posts_controller.rb code:
class PostsController < ApplicationController
def index
#posts = Post.find(4,5)
end
def show
#post = Post.find(params[:id])
end
def new
#post = Post.new
#category = Category.all
end
def create
#post = Post.new(params[:post])
if #post.save
redirect_to posts_path, :notice => "Your post has been saved"
else
render "new"
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update_attributes(params[:post])
redirect_to post_path, :notice => "Your post has been updated"
else
render "edit"
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to posts_path, :notice => "Your post has been deleted"
end
end
hope and thank anyone can help. Best, M
Strong Parameters
Rails uses a security mechanism called Strong Parameters by default. Its purpose is to ensure that only certain fields can be updated via a user submitted form.
#post.update_attributes(params[:post]) is an old-style syntax which does not work with strong parameters.
The updated convention is as follows
class PostsController
def update
# ...
#post.update(post_params) # instead of passing params[:post] directly, you pass it a strong parameters whitelist (see below)
end
def post_params
# we construct a strong parameters whitelist below
# require(:post) means that the `params` hash MUST contain a :post key
# permit(:title, :body, ...) = here we enumerate the attributes which we will accept from the form parameters; it acts as a whitelist
params.require(:post).permit(:title, :body, ...)
end
end
If you use rails g scaffold you can see an example of a controller which uses strong parameters.
DON'T DO THIS: To disable using strong parameters by default, you can set the following config value
config.active_record.whitelist_attributes = false
I included this for completeness' sake, however you should not do this as it will unnecessarily introduce security vulnerabilities to your code.
Additional Resources
ActiveModel::ForbiddenAttributesError when creating new user
http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html
https://github.com/rails/strong_parameters

Doing Subtracting on my Rails App with user input

I'm just starting to learn Rails so please forgive the dumb question. In my web app, I was able to set up working models, forms, and view. A user is able to input their decimal answer and it shows on the web page perfectly. However, I want to subtract one user input from another user input. So if the user inputs 100 in one model "post.price" and 10 in another input model "ratings1.content" > I want it to show 90 in the "fprice.content3". Any help that you guys can give me would be so amazing, I feel like the issue might be in my controller for fprice. I have listed below all my relevant code. Thank you again :)
_form.html "post.price"
<%= simple_form_for #post do |f| %>
<%= f.input :title %>
<%= f.input :image %>
<%= f.input :price %>
<%= f.button :submit %>
<% end %>
_form.html "ratings1s.content"
<%= simple_form_for ([#post, #post.ratings1s.build]) do |f| %>
<%= f.input_field :content %>
<% end %>
_form.html "fprice.content3"
<%= simple_form_for ([#post, #post.fprices.build]) do |f| %>
<%= f.input_field :content3 %>
<% end %>
Rails Controller "fprices"
class FpricesController < ApplicationController
before_action :authenticate_user!
def create
#post = Post.find(params[:post_id])
#fprice = Fprice.create(params[:fprice].permit(:content3))
#fprice.content3 === #post.price - #ratings1.content
#fprice.user_id = current_user.id
#fprice.post_id = #post.id
if #fprice.save
redirect_to post_path(#post)
else
render 'new'
end
end
end
Rails Controller "ratings1s"
class Ratings1sController < ApplicationController
before_action :authenticate_user!
def create
#post = Post.find(params[:post_id])
#ratings1 = Ratings1.create(params[:ratings1].permit(:content))
#ratings1.content *= 10
#ratings1.user_id = current_user.id
#ratings1.post_id = #post.id
if #ratings1.save
redirect_to post_path(#post)
else
render 'new'
end
end
end
It appears that at no point in time are you every defining #ratings1 object, then you call the content method on it while the value of #ratings1 is nil and thats what cause the error. Maybe something like this should help:
class FpricesController < ApplicationController
before_action :authenticate_user!
def create
#post = Post.find(params[:post_id])
#fprice = Fprice.create(params[:fprice].permit(:content3))
#ratings1 = #post.ratings1s.last
#fprice.content3 = #post.price - #ratings1.content
#fprice.user_id = current_user.id
#fprice.post_id = #post.id
if #fprice.save
redirect_to post_path(#post)
else
render 'new'
end
end
end
I think this line is also a the problem
#fprice.content3 === #post.price - #ratings1.content
=== is an equality operator so I don't know why you would have it there replace it with this
#fprice.content3 = #post.price - #ratings1.content

Rails: User form_for for a post does not work

I'm trying to render a text area on a user's profile page to allow them to create a post. At the moment I can view all of a user's posts, but I can't get to their profile page because the form will not render.
I did try to changing some stuff around, but then the form would not post due to a routing error.
I feel like I'm posting to the wrong path but I'm not sure so and advice would be appreciated.
class PostsController < ApplicationController
def index
#posts = Post.all
end
def new
#post = Post.new
end
def create
#post = current_user.posts.build(post_params)
if #post.save
flash[:success] = "Posted!"
redirect_to root_url
else
flash[:notice] = "Post could not be submitted"
redirect_to users_path
end
end
private
def post_params
params.require(:post).permit(:user_id, :content)
end
end
_post_form.html.erb
<%= form_for :post, user_posts_path, {method: "create"} do |f| %>
<%= f.text_area :content, size: "60x12", placeholder: "What do you want to say?" %>
<%= f.submit "Post" %>
<% end %>
There's no such HTTP verb called create, you need to change the method mentioned in your form_for, instead of this:
<%= form_for :post, user_posts_path, {method: "create"} do |f| %>
try this:
<%= form_for :post, user_posts_path, {method: "post"} do |f| %>
Please check rake routes and I think you provided the
resources :users do
resources :posts
end
in routes.eb
so
<%= form_for :post, user_posts_path(#user), html: { method: "post"} do |f| %>
in controller
def new
#post = Post.new
#user = current_user
end

Rails form adding empty entry via model

I am new to ruby, trying to follow the official documentation and create a basic form for creating a post:
<%= form_for #post, :url => { :action => "create" }, :html => {:class => "nifty_form"} do |f| %>
<%= f.text_field :title %>
<%= f.text_area :entry, :size => "60x12" %>
<%= f.submit "Create" %>
<% end %>
The form is successfully adding an entry to the database, but an empty one, I think I must be missing something in my controller? Do I need to pass the variables somehow?
def create
#post = Main.create
end
A basic create action can look like this. You first initialize a new post. Depending on if it successfully saves you proceed.
# app/controllers/posts_controller.rb
class PostsController < ActionController::Base
def create
#post = Post.new(params[:post])
if #post.save
redirect_to #post, notice: 'Post has been created.'
else
render :new
end
end
end
You can shorten your form.
<%= form_for #post do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.text_area :entry, :size => "60x12" %>
<%= f.submit %>
<% end %>
You can see excellent example code along these lines when you generate a scaffold, so I would encourage you to try $ rails generate scaffold Post title body:text and learn by example.
Submitting a form passes the values entered into that form (along with some other information) to the controller as a hash called "params" - the params will contain a block labelled with the name of the form, in this case "post".
You need to use the post block from params in the creation of the new object.
def create
#post = Main.new(params[:post])
if #post.save
# handles a successful save
else
# handles validation failure
end
end
Try:
#post = Main.new(params[:post])
#post.save

Creating an object from the show action of another object in Rails

So I have a fairly typical blog application with posts and comments.
Each comment belongs to one post
A post can have many comments.
Basically I want to add a form for comments to the show action for posts, without having post_id under attr_accessible in the comment model.
In my posts controller I have:
def show
#post = Post.find(params[:id])
#poster = "#{current_user.name} #{current_user.surname} (#{current_user.email})"
#comment = #post.comments.build( poster: #poster )
end
I'm not entirely sure what I should be doing in the comments controller (I'm not confident that the code above is right either if I'm honest). At the moment I have:
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.build(params[:post])
if #comment.save
redirect_to #post, notice: "Comment posted"
else
redirect_to #post, error: "Error!"
end
end
My routes:
resources :comments
resources :posts do
resources :comments
end
and finally the form:
<%= form_for #post.comments.build do |f| %>
<%= f.label :content, "WRITE COMMENT" %>
<%= f.text_area :content, rows: 3 %>
<%= f.hidden_field :post_id, value: #post.id %>
<%= f.submit "Post" %>
<% end %>
The problem here is that I have no way of passing my post_id from the show action of the posts controller to the create action of the comments controller. Any help is much appreciated. Thank you in advance!
Your posts controller looks fine... but assuming your routes looks like
resources :posts do
resources :comments
end
then your CommentsController#create should/could look like:
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.build(params[:comment])
if #comment.save
redirect_to #post, notice: "Comment posted"
else
redirect_to #post, error: "Error!"
end
end
And your form:
<%= form_for [#post, #comment] do |f| %>
<%= f.hidden_field :poster, value: #poster %>
<%= f.label :content, "WRITE COMMENT" %>
<%= f.text_area :content, rows: 3 %>
<%= f.submit "Post" %>
<% end %>
I will assume that your post model has_many comments and comment belongs_to post
than you in your routes file you can do something like this
resources :posts do
resources :comments
end
this will give you a url schem such as
/posts/:post_id/comments , allowing you to always have post_id of the comment parrent
The URL for your show post should be like post/show/(:id).
Now, in the comment form, you can place a hidden field, with value of params[:id].
hidden_field(:post_id, :value => params[:id])
When you submit your form, you can get the value of post_id using the hidden field.
def create
#comment = Comment.new(params[:comment])
#comment.post_id = params[:post_id]
if #comment.save
flash[:notice] = 'Comment posted.'
redirect_to post_path(#comment.post_id)
else
flash[:notice] = "Error!"
redirect_to post_path(#comment.post_id)
end
end

Resources