I am a beginner in rails, and I'm having an issue in a registration form.
I have users and emails in different tables (take a look) but the user registration form has an email field mixed with all the other fields such as username and password.
At first render there's no issue, but when trying to save, if any error occurs (such as duplicated username or email) I follow steps here, where it says (don't redirect_to, just do render 'new' to keep previously inserted info. That's when it throws an error saying email is not known.
I don't want to create the field email in the users table, since I already removed it from the original model. How do I fix that?
Form code
<%= form_for :user, url: users_path do |f| %>
<p>
<%= f.label :username %>
<%= f.text_field :username %>
</p>
<p>
<%= f.label :name %>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :email %>
<%= f.email_field :email # Error is thrown in this line %>
</p>
<p>
<%= f.label :password %>
<%= f.password_field :password %>
</p>
<p>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>
</p>
<p>
<%= f.submit %>
</p>
Controller code
def create
# render plain: params[:user].inspect
#user = User.new(user_registration_params)
if #user.save
email_params = {email: params[:user][:email], primary: true}
#email = Email.new(email_params)
#email.user = #user
if #email.save
redirect_to #user
else
#user.destroy
end
else
render 'new'
end
end
If you have connected the both models via belongs_to you can set up your form to update/create both models.
You have to declare you user with accepts_nested_attributes_for.
See a full example here:
http://railscasts.com/episodes/196-nested-model-form-part-1
Related
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.
I have the following simple rails page:
<h1> New User </h1>
<%= form_for :user, url:users_path do |f| %>
<p>
<%= f.label :email %>
<%= f.text_field :email %>
</p>
<p>
<%= f.label :password %>
<%= f.text_field :password %>
</p>
<%= f.submit %>
<% end %>
The create action gets executed and I want to access the :email attribute.
def create
render text: params[:email].inspect
end
The above always displays nil.
form_for :user will place all parameters beneath a :user key
render text: params[:user][:email].inspect
I am trying to have a form show up for a related model, but it is not displaying when I view the page in a browser. How do I url field in my fields_for to display?
Here is my code:
User Model:
class UsersController < ApplicationController
def new
#user = User.new
#user.websites.build
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to root_url, :notice => "Signed up!"
else
render "new"
end
end
end
Website Model:
class Website < ActiveRecord::Base
belongs_to :user
end
Users View:
<h1>Sign Up</h1>
<%= form_for #user do |f| %>
<% if #user.errors.any? %>
...
<% end %>
<p>
<%= f.label :email %><br/>
<%= f.text_field :email %>
</p>
<p>
<%= f.label :password %><br/>
<%= f.password_field :password %>
</p>
<p>
<%= f.label :password_confirmation %><br/>
<%= f.password_field :password_confirmation %>
</p>
<% f.fields_for :websites do |builder| %>
<%= builder.label :url %><br/>
<%= builder.text_field :url %>
<% end %>
<p class="button"><%= f.submit %></p>
<% end %>
Final output:
You missed the equals sign in your erb tag.
<% f.fields_for :websites do |builder| %>
.. should be ..
<%= f.fields_for :websites do |builder| %>
Does that fix it?
It looks like you're maybe confusing singular and plural in your fields_for as well. Calling it with the plural websites then treating the block as a singular website doesn't make sense.
Im trying to set up a log-in and password page for my site. This will be on the index page. I have a Model Class: "User" and a controller class "users_controller".
The behavior that Im trying to implement is this:
Users type in the url of the site and it opens the index page as shown below. Then the users signs in and is brought to a different page where they have access to the content of the site.
Now the question is what do I need to put in the "def index" function so that it accepts the form's paramters and passes these to another function called "self.authenticate(parameters)" to check and return a status
Here is the code for the users_controller
class UsersController < ApplicationController
def index
#user = User.new
respond_to do |format|
format.html
#index.html.erb
end
end
def show
#user = User.find(params[:id])
#title = #user.name
end
def edit
#user = User.find(params[:id])
#title = #user.name
end
def destroy
#user = User.find(params[:id])
end
def new
#user = User.new
#title = "Sign Up"
end
def create
end
end
Here is the form:
<html>
<h1>Returning Users- Sign In</h1>
<%= form_for(#user) do |f| %>
<div class="field">
<%=f.label :email %><br/>
<%= f.text_field :email %>
</div>
<div class = "field">
<%= f.label :password %><br/>
<%= f.password_field :password %>
</div>
<div class = "actions">
<%= f.submit "Sign In" %>
</div>
<% end %>
<h1>New Users- Sign Up</h1>
<%= form_for(#user) do |f| %>
<div class="field">
<%=f.label :name %><br/>
<%= f.text_field :name %>
</div>
<div class="field">
<%=f.label :email %><br/>
<%= f.text_field :email %>
</div>
<div class = "field">
<%= f.label :password %><br/>
<%= f.password_field :password %>
</div>
<div class = "field">
<%= f.label :password_confirmation, "Confirm Password" %><br/>
<%= f.password_field :password_confirmation %>
</div>
<div class = "actions">
<%= f.submit "Sign Up" %>
</div>
<%end%>
<br/>
<%= debug(params) if Rails.env.development? %>
<br/>
</body>
Any help would be great. Thanks
Have a look at the recent RailsCast Authentication from Scratch from Ryan Bates. You can also use a common authentication plugin like AuthLogic or Devise.
I'm going to explain to you what you want to do.
You can get the params by using the hash params:
params[]
Then, you can get the value of a field by passing it's identification, like:
params[:id]
or
params[:name]
Now pass it to the self.authenticate(parameters) in the way you can(I don't know how this method is implemented).
I have a simple signup form:
<h1>Signup as a new user</h1>
<%= form_for(#user) do |f| %>
<p>
<%= f.label :username %>
<%= f.text_field :username %>
</p>
<p>
<%= f.label :password %>
<%= f.password_field :password %>
</p>
<p>
<%= f.submit "Save" %>
</p>
<% end %>
That redirects to the create method of the UsersController:
def create
password = params[:password].crypt("$1$}")
#user = User.new(:username => params[:username], :password => password)
#user.save
flash[:message] = "User #{User.username} created!"
redirect_to user_path(#user)
end
But this throws an error undefined method crypt' for nil:NilClass. Why would the password be Nil? I checked the HTML params and got this:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"aAcaURTLKfwmXULEUzLX36tZAKER/kMxKKOROOXgoU8=", "user"=>{"username"=>"Chris", "password"=>"[FILTERED]"}, "commit"=>"Save"}
Does "[FILTERED}" mean it isn't a string? How can I access it from params?
Its not nil, it just exists inside of :user, so try
params[:user][:password].crypt("$1$")
In fact all of your params work here is incorrect, all the fields are scoped by :user, this is one of the things that form_for does for you automatically.
So to get the username, you'd want to say params[:user][:username].