Rails: form_for doesn't turn parameters - ruby-on-rails

I'm basically trying to create a Rails form_for but it simply does not turn parameters. I've checked the server log and it receives the parameter but cannot capture on the create function. I'm watching andrewperk's tutorial (http://www.youtube.com/watch?v=unq1yubL6lQ) about create and save methods. What could I possible done wrong?. Here is my Users controller;
def new
#user=User.new
end
def create
#user=User.new(params[:user])
if #user.blank?
render :new
else
#user.save
render :index
end
end
And here is my form;
<h1>Add an available user</h1>
<%= form_for #user do |a| %>
<p>
<%= a.label :name %>
<%= a.text_field :name %>
</p>
<p>
<%= a.label :surname %>
<%= a.text_field :surname %>
</p>
<p>
<%= a.submit "Add new available user"%>
</p>
<% end %>

You should use params[:user] in your controller, because this is how the HTML form fields are named by default (you can check page source).
Also I'd suggest refactoring the create method a bit. It is a convention that you redirect to index page instead of just rendering it after creating a record.
def create
#user = User.new(params[:user])
if #user.save
redirect_to users_path
else
render :new
end
end

Related

When I try to load my create.html.erb page, I get this error "param is missing or the value is empty"

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 want a seperate link only for change password in ruby on rails !!! How Can i do?

I dont want change password option in devise (edit registrations). rather, i would like to add a link or form for changing password in separate page. can anyone help me !!!
This is easy to do, using simple CRUD methods. Create an edit view for your Users, with a Rails form that targets Devise's password fields.
edit.html.erb (in Users folder of Views):
<%= form_for(#user) do |f| %>
<%= f.label :password %>
<%= f.text_field :password %>
<%= f.label :password_confirmation %>
<%= f.text_field :password_confirmation %>
<%= f.submit %>
<% end %>
In your Users controller:
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update(user_params)
redirect_to #user, notice: 'User was successfully updated.'
else
render :edit
end
end
private
def user_params
params.require(:user).permit(:password, :password_confirmation)
end
Make sure you also have resources :users in your config/routes.rb file
The link to the edit view would be something like:
<%= link_to 'Edit User', edit_user_path %>

How to "Create" after second step _form?

So in step one the user creates his challenge.
<%= form_for(#challenge) do |f| %>
<%= f.text_field :action %>
<%= f.submit %>
<% end %>
Then he is directed to another _form to finish adding details about that challenge.
<%= form_for(#challenge) do |f| %>
<%= f.text_field :action %>
<%= f.date_select :deadline %>
<%= f.check_box :conceal %>
<%= f.submit %>
<% end %>
Once he adds those details and clicks "Save" I want the challenge to be created via the Create action of the challenges_controller.
def step_one
??
end
def create
#challenge = Challenge.new(challenge_params)
#challenge.save
redirect_to challenging_url(#challenge)
end
If you want to create a record across two requests, you need to persist data from the first request, and re-submit it along with the second request.
The easiest and most "Rails"y way of accomplishing this is to accept the incoming "name" attribute from your first request and render the second stage form with the name persisted as a hidden field.
app/controllers/challenge_controller
# Show "step 1" form
def new
#challege = Challenge.new
end
# Show "step 2" form, OR, attempt to save the record
def create
#challenge = Challenge.new(params[:challenge])
if params[:step] == '2'
if #challenge.save
redirect_to #challenge, notice: "Challenge saved!"
end
end
# Fall through to render "create.html.erb"
end
app/views/challenges/new.html.erb
<%= form_for #challenge do |f| %>
<%= f.input_field :name %>
<%= f.submit %>
<% end %>
app/views/challenges/create.html.erb
<%= form_for #challenge do |f| %>
<%= f.hidden_field :name %>
<%= hidden_field_tag :step, 2 %>
<%= f.text_field :action %>
<%= f.date_select :deadline %>
<%= f.check_box :conceal %>
<%= f.submit %>
<% end %>
There are a few things to note here:
create renders a different form than new. This is atypical for a Rails application
The "step 2" form rendered by create uses hidden_field_tag to attach an extra value to the submission, outside of the params[:challenge] attributes
Validation is unhandled - it's up to you to display errors if somebody submits an empty name in step 1, or other invalid attributes in step 2
The answer is more likely "it depends what you are trying to do", but the simplest solution is to redirect (in create after save) to the edit action/view which contains all or the other fields, not just the limited fields you provided in the new action/view.
def create
#challenge = Challenge.new(challenge_params)
if #challenge.save
redirect_to edit_challenge_url(#challenge), notice: "Saved!"
else
render :new
end
end

Validate form called through another controller

Im writing a blog engine, So I have a post view (show.html.erb) that shows a post, comments list and a comments form.
I call the form this way:
<%= render :partial => 'comments/form', :locals => {:comment => #post.comments.new} %>
Im not sure if passing the comment that way is correct, but at least I get the post_id on the new comment.
This is my form (_form.html.erb on comments view):
<%= form_for comment, :action => "create" do |f| %>
<% if comment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(comment.errors.count, "error") %> prohibited this comment from being added:</h2>
<ul>
<% comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :post_id %>
<p>
<%= f.label :name %>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :email %>
<%= f.text_field :email %>
</p>
<p>
<%= f.label :url %>
<%= f.text_field :url %>
</p>
<p>
<%= f.label :content %>
<%= f.text_area :content %>
</p>
<p class="no-border">
<%= f.submit "Post", :class => "button" %>
</p>
<% end %>
And this the action:
def create
#comment = Comment.new(params[:comment])
respond_to do |format|
if #comment.save
format.html { redirect_to :back }
else
format.html { redirect_to :back }
end
end
end
A bit verbose but I want to add more stuff.
I can add comments perfectly but I can't view validation errors.
I leave all blank (my model have validation stuff) and I see that the comment created in the create action have the errors and go to the else path.
But... The form doesn't show any errors.
I think that I have an object with the erorrs but when I redirect back, the object I pass to the form is a new one again and doesn't have the errors.
So, where is the problem?
EDIT: Extra stuff:
Im my show.html.erb I also have this (before the form):
<ol class="commentlist">
<%= render #post.comments %>
</ol>
So, When in the show action I put the extra variable:
def show
#post = Post.find(params[:id])
#comment = #post.comments.new
It seems that the render wants to render the empty comment too and make an exception.
How to bypass that?
When you redirect back, you are calling the PostsController#show action again which will reset all of the instance variables. If you wanted to save state after the failed CommentsController#create call, you would need to call render 'posts/show' instead of redirect :back which would reuse the instance variables which were declared in the current action
def create
# assuming you have nested the comments routes underneath posts...
#post = Post.find(params[:post_id])
#comment = #post.comments.build(params[:comment])
respond_to do |format|
if #comment.save
format.html { redirect_to :back }
else
format.html do
# remember to declare any instance variables that PostsController#show requires
# e.g. #post = ...
render 'posts/show'
end
end
end
end
You would also need to make sure that the partial uses #comment instead of creating a new comment each time
<%= render :partial => 'comments/form', :locals => {:comment => #comment } %>
And make sure the PostsController declares #comment
# e.g. inside PostsController
def show
#post = Post.find(params[:id])
#comment = Comment.new
end
The most important thing to remember is to make sure that the code inside the failed create call initializes all the instance variables that the PostsController#show action template requires otherwise you'll get errors.

rails multiple input record

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?

Resources