I have a really simple Rails app. Basically an article with comments. I want the article page to show the article, comments underneath and then a textbox to write a comment and a submit button to submit it.
I got it all working except for one (big) problem. When the page loads.. example.com/article/1
a blank comment is submitted to the database.
I fixed that by including "validates_presence_of :body" in the Comment model. But that results in the following image when the page loads:
This is my code by the way:
def show
#place = Article.find(params[:id])
#comment = Article.find(params[:id]).comments.create(params[:comment])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #article }
end
end
and
<% form_for([#article, #comment]) do |f| %>
<p>
<%= f.label :commenter %><br />
<%= f.text_field :commenter %>
</p>
<p>
<%= f.label :body %><br />
<%= f.text_area :body %>
</p>
<p>
<%= f.submit "Create" %>
</p>
<% end %>
It's because you made a create.
Create try save object and like is invalid, an error is generate.
Made :
#comment = Article.find(params[:id]).comments.build(params[:comment])
Fix your problem I think
Related
I got this error on loading the page and I would guess that it has somethinng to do with my create method in the controller
My controller looks like this
class StoryController < ApplicationController
def index
#story = Story.all
end
def new
#story = Story.new
end
def create
#story = Story.new(story_params)
if #story.save
flash[:notice] = "Story created successfully"
flash[:color]= "valid"
else
flash[:notice] = "Story is invalid, man"
flash[:color]= "invalid"
end
end
def show
#story = Story.find(params[:id])
end
private
def story_params
params.require(:story).permit(:story_title, :story_body)
end
end
My create.html.erb looks like
<%= form_for #story ,url: story_path do |f| %>
<%= label :story, :title %><br />
<%= text_field :story, :story_title %>
<%= label :story, :body %><br />
<%= text_field :story, :story_body %>
<%= submit_tag 'Create story' %>
<% end %>
My create.html.erb didnt look like this before, I changed it to that after I read some questions about how form_for would work instead of form_tag for the story_params.
But either way, I still get the error anyways and I would like to know why and if there is a fix for it.
very first, you don't need to specify a path if you are using form_for and if you don't want to submit a form on the custom route.
If you are using new object then it will submit form on create method and for existing object it will submit form on update method.
So your form will be,
<%= form_for #story do |f| %>
<%= f.label :title %><br />
<%= f.text_field :story_title %>
<%= f.label :body %><br />
<%= f.text_field :story_body %>
<%= submit_tag 'Create story' %>
<% end %>
And this form needs to be in new.html.erb file.
This form will submit your form to create action with post method and from there you need to do render or redirection depending upon condition. So your controller will be,
class StoryController < ApplicationController
def index
#story = Story.all
end
def new
#story = Story.new
end
def create
#story = Story.new(story_params)
if #story.save
flash[:notice] = "Story created successfully"
flash[:color]= "valid"
redirect_to story_path(#story)
else
flash[:notice] = "Story is invalid, man"
flash[:color]= "invalid"
render :new
end
end
def show
#story = Story.find(params[:id])
end
private
def story_params
params.require(:story).permit(:story_title, :story_body)
end
end
If you do rake routes in the termial, you can see all methods with its expected methods
Also according to rails conventions, if you have story model then you can directly create :title & :body attributes instead of :story_title and :story_body
The create method is a POST... so when he enters story/create he's already expecting those values... that's why he says he can't find the params... i didn't look at the code deeply but it seems fine. Just change the name of the view to new.html.erb. New is the setup for create.
In new you setup the values and then invoke create where the controller actually creates the story.
Just change the name of the view to new.html.erb and change it to this
<%= form_for #story do |f| %>
<%= f.label :title %><br />
<%= f.text_field :story_title %>
<%= f.label :body %><br />
<%= f.text_field :story_body %>
<%= submit_tag 'Create story' %>
<% end %>
as the other user said. you need to say that those inputs belong to form |f| the text_field belongs to f, f.text_field
And of course you access that view through stories/new
Try this make changes in the create.html.erb
<%= form_for #story ,url: story_path do |f| %>
<%= f.label :title %><br />
<%= f.text_field :story_title %>
<%= f.label :body %><br />
<%= f.text_field :story_body %>
<%= submit_tag 'Create story' %>
<% end %>
Are you sure your attributes for the Story object are named story_title and story_body ?
If not, your story_params should be like this :
def story_params
params.require(:story).permit(:title, :body)
end
And also, apply #koshlendra suggestion, he's right.
I suggest you to generate a scaffolding for a fake resource to see how it's supposed to work :
rails g scaffold Fake title:string body:text
Then look at the generated controller and views to understand fully how it works.
I am stuck with persisting data on button click. Is it possible to get the parameters to different controller function from another page.
Controller
def create
#login=Login.new
#login.name=params[:name]
#login.email=params[:email]
#login.password=params[:password]
#login.phone_number=params[:phone_number]
if #login.save
render :action => 'success'
else
puts (#login.errors.full_messages)
render :action => 'failure'
end
end
def operation
if params[:commit] == "Clicked"
puts ("Inside CLICKED")
redirect_to action: 'clicked'
else
redirect_to action: 'create'
end
end
view (create.html.erb)
<h1>Welcome to DemoSite.com</h1>
<p></p>
<%= form_for (#login), :url => {:action => "create"} do |f| %>
<p>
<%= f.label :Name %><br>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :Email %><br>
<%= f.text_field :email %>
</p>
<p>
<%= f.label :Phone_Number %><br>
<%= f.telephone_field :phone_number %>
</p>
<p>
<%= f.label :Password %><br>
<%= f.password_field :password %>
</p>
<p>
<%= f.label :password_confirmation %><br>
<%= f.password_field :password_confirmation %>
</p>
<p>
<%= f.submit('Submit') %>
</p>
<% end %>
index.html.erb
<h1>Welcome to DemoSite.com</h1>
<p></p>
<%= form_tag "/logins/operation", :method => "post" do %>
<p>
<%= label_tag(:username, "Username") %><br>
<%= text_field_tag(:username) %>
</p>
<p>
<%= label_tag(:password, "Password") %><br>
<%= password_field_tag(:password) %>
</p>
<p>
<%=submit_tag "Create" %>
<%= submit_tag "Clicked" %>
</p>
When I run this, it directs me to failure.html.erb directly from index.html.erb when I click create button, without hitting the create.html.erb. Also, how can I persist the data inside create method after button click?
Your operation action redirects to create and your create action either renders failure or succes, your create action never does the default thing (namely rendering your create-view).
Most of the times the new action renders the form, and the create action (which should be POST) actually creates (saves) the data.
The redirect to create as you do it now, will never succeed, because it will not receive any data, so it will always fail to create the user, so it will always show the failure screen.
[UPDATE] simplest (but still dirty way) to fix it :
If you redirect to your create action, it is a GET request, not POST.
So the simplest fix is this:
def create
if request.post?
#login = Login.new(params)
if #login.save
render :action => 'success'
else
puts (#login.errors.full_messages)
render :action => 'failure'
end
else
#login = Login.new
end
end
So if it is a POST: try to save and check the errors. If it is a GET just render the create.html.erb.
The best, clean REST way, is to redirect to the new action from your operation action, and your form will POST to the create action. This is how it is supposed to be.
while i am creating a comment associated with the posts, i am getting this error::
My comments controller ::
class CommentsController < ApplicationController
def new
#comments = Comment.new
end
def create
#post = Post.find (params[:post_id])
#comments = #post.comments.create(params[:comments].permit(:commenter, :body))
redirect_to post_path(#post)
end
end
// The form for the comments ///
<strong>Title:</strong>
<%= #post.Title %>
</p>
<p>
<strong>Text:</strong>
<%= #post.Text %>
</p>
<%= form_for([#post, #post.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br />
<%= f.text_field :commenter %>
</p>
<p>
<%= f.label :body %><br />
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
i am getting error on this line::
#comments = #post.comments.create(params[:comments].permit(:commenter, :body))
Please point me out where i am wrong..
One edit :: My actual error statement ::
NoMethodError in CommentsController#create
The correct syntax to use strong parameter is
params.require(:comments).permit(:commenter, :body)
But I think params will contain comment not comments
So you should use
params.require(:comment).permit(:commenter, :body)
well, as the error message states, params[:comments] is nil.
You should be using params.require(:comments).permit(:commenter, :body) so that if comments isn't present, it won't go any further.
Also, the actual param being submitted is comment, not comments. You can verify this by looking at the submitted params in your logs.
I'm getting an error with routes and I can't find where is the problem, I'm creating a simple CRUD and get this trouble with the create method.
Error
No route matches [POST] "/usuarios/new"
Controller
def new
#usuario = Usuarios.new
end
def create
#usuario = Usuarios.new(params[:usuario])
if #usuario.save
redirect_to usuario_path, :notice => "Cadastrado realizado com sucesso!"
else
render "new"
end
end
new.html.erb
<h1>Add new user</h1>
<%= form_for (:usuario) do |f| %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :idade %><br />
<%= f.text_field :idade %>
</p>
<p>
<%= f.label :email %><br />
<%= f.text_field :email %>
</p>
<p>
<%= f.submit "send" %>
</p>
<% end %>
As Flexoid has pointed out, you probably haven't add the new method in the controller.
So, put this
def new
#usuario = Usuario.new
end
EDIT
You have to pay more attention.
Take a look:
def new
#usuario = Usuario.new # not Usuarios.new, that's wrong.
end
def create
#usuario = Usuario.new(params[:usuario]) # not usuarios, first letter should be capital
if #usuario.save
redirect_to usuarios_path, :notice => "Cadastrado realizado com sucesso!" # usuario_path requires an id parameter like `usuario_path(#usuario)` or you could redirect to the `index` with `usuarios_path`
else
render "new"
end
end
Change
<%= form_for (:usuario) do |f| %>
to
<%= form_for (#usuario) do |f| %>
Seems like you forgot about configuring of the Rails Router.
Try to add this to your config/routes.rb file:
resources :usuarios
For the reference you can read rails guide Rails Routing from the Outside In.
I'm new to rails. I have some question that's been quite a headache to me, so here it is:
For example i have this controller & view:
Controller:
class OrdersController < ApplicationController
def new
#Order = Order.new
end
def create
#Order = Order.new(params[:order])
if #Order.save
flash[:notice] = "Successfully created order."
redirect_to #Order
else
render :action => 'new'
end
end
View:
<% title "Menu Order" %>
<%= form_for #Order do |f| %>
<%= f.error_messages %>
<div id="form-order">
<p>
<%= f.label :name%><br />
<%= f.text_field :name, %>
</p>
<p>
<%= f.label :menu_order %><br />
<%= f.text_field :menu_order %>
</p>
</div>
<%= f.submit %>
So my question is :
before displaying the form above, I want to have a text_field_tag that specify how many forms (roughly said, duplicate the form div) I want to generate based on count, and then insert the data to the database simultaneously,
the idea is to speed things up, so that the user don't have to input the data only one at a time, but multiple record at single submit
How do I do that?