Rails: 'Email has already been taken' for every email I enter - ruby-on-rails

Update:
Checking the console, a lot of the users are actually going into the database, even when this error message appears!
Even weirder, you will notice that I have a redirect to root_path on a successful save to the database. it never goes there. This is the log. If it saves, it sometimes goes to the show action but there's actually a moment when the browser appears to get stuck, everything blanks it and I have to click in the address field to push it through to show.index.html.
Redirected to http://localhost:3000root_path
Completed 302 Found in 34ms
[2012-01-08 18:08:27] ERROR URI::InvalidURIError: the scheme http does not accept registry part: localhost:3000root_path (or bad hostname?)
/Users/mel/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/uri/generic.rb:746:in `rescue in merge'
/Users/me/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/uri/generic.rb:743:in `merge'
/Users/me/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/webrick/httpresponse.rb:163:in `setup_header'
/Users/me/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/webrick/httpresponse.rb:101:in `send_response'
/Users/me/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/webrick/httpserver.rb:86:in `run'
/Users/me/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/webrick/server.rb:183:in `block in start_thread'
Original Question:
I'm creating a form for users to sign up to win an ipad. It's got two fields, email and name.
When I submit the form, I keep getting the same error message no matter what email i enter
1 error prohibited this from being saved:
There were problems with the following fields:
Email has already been taken
Strangely, when I debug params, it shows whatever new email address I enter.
utf8: "\xE2\x9C\x93"
authenticity_token: UgkHFLBfKYM2tZ11u6ItWvPS5XeTIMhFuJDwvhgqe30=
ipad: !map:ActiveSupport::HashWithIndifferentAccess
name: Amy
email: franz#gmail.com
commit: Sign up
action: create
controller: ipads
Anyone have any idea? I'm a bit of a noob...
I'm just adding this code to an Enki blog I'm making on Rails...
I have this validation on my ipad.rb model (note, I had a column for a Twitter address in the migration that I'm just ignoring in the form)
attr_accessible :name, :email, :twitter
validates :name, :presence => true,
:length => { :maximum => 50 }
validates :email, :presence => true,
:uniqueness => true
This is my ipads_controller.rb
class IpadsController < ApplicationController
def new
#ipad = Ipad.new
#title = "iPad Contest"
end
def create
#ipad = Ipad.new(params[:ipad])
if #ipad.save
redirect_to 'root_path'
else
#title = "Poo"
render 'new'
end
end
end
This is my new.html.erb
<h1>Win an iPad</h1>
<%= #title %>
<h1>Sign up for iPad</h1>
<%= form_for(#ipad) do |f| %>
<%= render 'shared/errror_messages' %>
<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="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= debug params %>

Using redirect_to root_path instead of redirect_to 'root_path' fixed it. Noob error.

Related

rails validation before action

Here's what happens in my app:
customer enters phone number
phone number is searched in customer model to see if it exists
if it does exist, go to the customer show page
if it does not exist, go to customer new page to create new customer
According to my understanding, model validations are for data that is entered/edited/deleted into the database.
However, how can we check (use the validation) before anything searches in the database? And if it is incorrect (example: using letters instead of digits for phone number), then would show the error.
I was implementing html form input options to prevent someone from inputting letters in the phone number input box like this:
<%= form_tag(new_customer_path, method: :get) do %>
<%= telephone_field_tag :phone, nil, placeholder: "Phone Number", required: true, pattern: "[0-9]{10}", title: "Number must be 10 digits", maxlength: "10", class: "input-lg" %>
<%= submit_tag "Enter", class: "btn btn-primary btn-lg" %>
<% end %>
However my form was getting big because I would then put the html form input box options on everything (phone, zip-code, email, ect.).
What is more proper "Rails" way? Using active record validations to show errors, or providing html form input options to validate the data beforehand? Or is it the combination of both (max secure? client side and before database)?
Model
class Customer < ActiveRecord::Base
validates_presence_of :first_name, :last_name, :phone, :email, :zip_code
validates_uniqueness_of :phone, :email
validates :phone, :zip_code, :numericality => {:only_integer => true}
validates_length_of :phone, is: 10
validates_length_of :zip_code, is: 5
end
Controller
def new
if #customer = Customer.find_by(phone: params[:phone])
flash[:success] = "Welcome back"
redirect_to #customer
else
#customer = Customer.new(phone: params[:phone])
flash.now[:warning] = "Customer not found, please sign up!"
end
end
error messages partial
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>">
×
<ul>
<li>
<p><%= value %></p>
</li>
</ul>
</div>
<% end %>
The rails validation is probably good enough but if you're worried about it you could add a javascript validation on the client side. There are several plugins you could use if you want to do form validations client side or you could write your own. This might be helpful: http://www.tutorialspoint.com/javascript/javascript_form_validations.htm
Just add front end validations with JavaScript and HTML. Your Rails validations looks fine.
Html: required attribute.
Jquery: Check out this link - http://jqueryvalidation.org/

trying to view error messages in rails

class Person < ActiveRecord::Base
before_save {self.email = email.downcase}
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { maximum: 6}
end
I am really new to Ruby. I was learning from Michael Hartl's tutorial. When creating signup form (tutorial 7) I got stuck in displaying error messages ( like if we leave any field blank there should be notifications in red right?).I added error_messages.html.erb file. Rendered it in form. Still there are no messages.
What I guessed is, I am using :user in my form creation to save the user. where as it should be #user. So that it can create user?
but when I did so, It gave me anonymous error of user_path. I searched for that display of error messages on stack but was not able to find.
Kindly help me with it. I am stuck since very long.
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(:person) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.email_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>
</div>
</div>
<% if #person.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
the form contains <%= #person.errors.count %> errors.
</div>
<ul>
<%= #person.errors.full_messages.each do |msg| %>
<li> <%= msg %> </li>
<% end %>
</ul>
</div>
<% end %>
class PersonsController < ApplicationController
def show
#person = Person.find(params[:id])
end
def new
#person = Person.new
end
def create
#person = Person.new(user_params)
if #person.save
else
render new
end
end
private
def user_params
params.require(:person).permit(:name, :email, :password, :password_confirmation)
end
end
Rails.application.routes.draw do
get 'persons/show'
root 'staticpages#home'
get 'help' => 'staticpages#help'
get 'about' => 'staticpages#about'
get 'signUp' => 'persons#new'
resource :person
resources :persons
end
// error when i use #user in form. Instead of :user
NoMethodError in PersonsController#new
undefined method `users_path' for #<#<Class:0x007fdb68c0ee78>:0x007fdb68c0e428>
Extracted source (around line #220):
if options.empty?
recipient.send(method, *args)
else
recipient.send(method, *args, options)
end
Based on the code I have seen in the GitHub repo, the major problem I identified was with the naming. There was a large level of conflict in the name person in that its plural is people and not persons.
Rails has its way of pluralizing model names so User has a UsersController and Person has PeopleController and so forth.
Following are the changes required to fix the problems with sign up:
You need to change your controller name from PersonsController to PeopleController (both class name and file name).
In the PeopleController, the strong parameters method Person_params needs to change to lowercase (person_params). Otherwise, Rails would treat it as a constant name and start hunting for it and wouldn't find it.
You'll have to update the persons folder name in the app/views folder to people for the same reason specified above.
In your routes.rb file, there are two changes required. Change resource :person to resources :people and get 'signUp' should match to 'people#new' instead of 'persons#new' (now you know why).
Create a new file in app/views/people called create.html.erb. Once a person is created, Rails automatically renders this file and will throw an exception if it does not find it.
In the file app/views/people/new.html.erb, change the variable passed to form_for from :person to #person. #person is an instance variable initialized when that page is visited (see the new action in the PeopleController).
I'm not sure if this change will be needed, but if you face any errors after making the above changes, add gem 'therubyracer' to your Gemfile and run bundle install. This will install the rubyracer gem which I believe will be required for this version of Rails.
You should really familiarize yourself with the fundamentals of the framework and the Ruby language. It'll help you identify and debug these issues yourself. But I figured since you're new to it, this lengthy answer might help get rid of your frustration :).
You have used the User model in multiple places. The actual model is called Person. Switch to this model name in all the controllers and the model class.
And I'd also like to make a suggestion. When studying the tutorial, please do not blindly copy and paste snippets. Understand what their purpose is and write them in your files on your own.

Add a contact form to Hartl's tutorial

I'm learning Rails by following Hartl's tutorial and making my own adjustments to it. Now, I would like to extent it and add a contact form that sends an email message. Such is not included in the tutorial, but by the end of chapter 10 we're learned to use the mailer method and we've configured SendGrid on Heroku.
I already have the view set up in the routes and think it would require the following additional steps:
1) Terminal. rails generate mailer ContactForm
2) In app/mailers/contactform.rb:
def send_contactform_email(visitor)
#visitor = visitor
mail( :to => myemail#example.com, :from => visitor.email, :subject => 'Contact form' )
end
3) app/views/contactform_mailer/ (the view for the mail message) for example:
<h1>Website contact form</h1>
<p>On <$= ... %> <%= "#{#visitor.name} (#{#visitor.email} sent the following message:" %></p>
<p><%= #visitor.message %></p>
4) app\controllers\static_pages_controller (or another location?)
# Sends contact form email.
def send_contact_form_email
ContactFormMailer.send_contactform_email(visitor).deliver_now
redirect_to contact_path, notice: 'Message sent'
end
5) app\views\static_pages\contact.html.erb (I'm not sure about the first line, should I also do something in the routes.rb? My guess is this first line will have to tell to execute the method in step 4, which is not going to work the way it is now.)
<%= form_for(:static_pages, url: contactform_path) do |f| %>
<i class="pt-row-icon glyphicon glyphicon-user"></i> <%= f.label :name %>
<%= f.text_field :name, placeholder: 'Name', class: 'form-control' %>
<i class="pt-row-icon glyphicon glyphicon-envelope"></i> <%= f.label :email %>
<%= f.email_field :email, placeholder: 'Email', class: 'form-control' %>
<i class="pt-row-icon glyphicon glyphicon-envelope"></i> <%= f.label :message %>
<%= f.text_area :message, placeholder: 'Your message…', class: 'form-control' %>
<%= f.submit "Send", class: "btn btn-primary" %>
<% end %>
I don't think this is 100% correct yet, particularly the bold sections. What are your thoughts?
UPDATE, VERSION 2: I've tried to make the updates as suggested by Ven and now have the code below. The idea as I understand it is that
the controller in def contact sets the #message variable.
the form_for knows it should fill this variable with params[:message].
the controller adopts the values from the form_for and passes them to the mailer.
the mailer uses the mailer view to design the message to be sent.
the mailer sends it back to the controller that send the message.
1) App/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
before_action :valid_email?, only: [:send_message_email]
# Shows the contact form page
def contact
#message = message(message_params)
end
# Sends the message.
def send_message_email
#message = message(message_params)
if #message.valid?
MessageMailer.new_message(#message).deliver_now
redirect_to contact_path, notice: "Your messages has been sent."
else
flash[:alert] = "An error occurred while delivering this message."
render :new
end
end
private
def message_params
params.require(:message).require(:name, :email, :content)
end
def valid_email?(email)
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
email.present? && (email =~ VALID_EMAIL_REGEX)
end
end
2) Contact form in app\views\static_pages\contact.html.erb:
<%= form_for(message: params[:message], url: contact_path) do |f| %>
<%= f.label :name %> <%= f.text_field :name, placeholder: 'Name', class: 'form-control' %>
<%= f.label :email %> <%= f.email_field :email, placeholder: 'Email', class: 'form-control' %>
<%= f.label :content %> <%= f.text_area :content, placeholder: 'Your message…', class: 'form-control' %>
<%= f.submit "Send", class: "btn btn-primary" %>
<% end %>
3) Routes.rb
get 'contact' => 'static_pages#contact', as: 'contact'
post 'contact' => 'static_pages#send_message_email'
4) App/views/message_mailer.text.erb (and html.erb)
<%= #message[:name] %> <%= #message[:email] %> wrote:
<%= #message[:content] %>
5) App/mailers/message_mailer.rb
class MessageMailer < ApplicationMailer
default to: "myemail#example.com>"
def new_message(message)
#message = message
mail to: "myemail#example.com"
mail from: #message[:email]
mail subject: "Message from #{message[:name]}"
end
end
Now when I try to visit the contact form on the server, I get the error message: param is missing or the value is empty: message. It refers to the params.require(:message).require(:name, :email, :content) line. Not sure what I'm doing wrong. Changing it to params.require(:message).permit(:name, :email, :content) makes no difference.
4) app\controllers\static_pages_controller (or another location?)
This seems to be correct, if this is the github repo for said app.
def send_contact_form_email
You controller has an issue: this action will try to send the email, not matter if it's used in POST or GET. You should use two different actions, one for displaying the view (using GET), and one for sending the email (using the mailer class you created). (at this point, you might want to create another controller)
ContactFormMailer.send_contactform_email(visitor).deliver_now
Then, moving on: what you pass to your mailer is "visitor". There's no such variable.
You probably want to access something out of the params hash (which contains parameters for GET and POST requests), and use the same key as your form (form_for(:visitor ... => params[:visitor] (so you want to change that :static_pages)).
<p>On <$= ... %> <%= "#{#visitor.name} (#{#visitor.email} sent the following message:" %></p>
As this returns an object, and not a hash, #visitor.email needs to be #visitor[:email] inside the mailer.
One last thing: simply using params[:visitor] will mean people could leave the field blanks. You might want to look into strong parameters, that were added in Rails 4 (the book seems somewhat outdated?).
And lastly, you need to add routes to be able to reach these actions (one for the GET request - display the view - and one for the POST request - to submit the form).
PS:
mail( :to => myemail#example.com, :from => visitor.email, :subject => 'Contact form' )
Warning: here, you forgot to quote the email address. Also, you swapped the to/from parameters. You want to send TO your visitor email, not from it.
EDIT
params.require(:message).require(:name, :email, :content)
This will require said keys, but AFAIK on the same "level" as :message - the top one. You want to use permit:
params.require(:message) # require "namespace"
.permit(:name, :email, :content) # permit keys
#message = message(message_params)
Where is the message function defined?
mail to: "myemail#example.com"
mail from: #message[:email]
mail subject: "Message from #{message[:name]}"
This sends 3 different emails, since you called the mail function 3 times.

In Rails with Globalize, update seems to ignore empty string fields

I am very new to Rails and I am facing a somehow weird problem, and my googling didn't helped me so far...
I have implemented a classical CRUD ressource following the Getting Started with Rails guide and I am blocking on the "update" part:
http://guides.rubyonrails.org/getting_started.html#updating-articles
This is part of my model "Devwork":
class Devwork < ActiveRecord::Base
validates :short_title, presence: true, uniqueness: true
validates :title_fr, presence: true, allow_blank: false
translates :title, :summary, :description
globalize_accessors
end
I am using the Globalize gem to persist localized data, and Globalize-accessor for the helpers.
Here is the controller's update action:
class DevworksController < ApplicationController
def update
#devwork = Devwork.find(params[:id])
if #devwork.update(devwork_params)
redirect_to #devwork
else
render :edit
end
end
private
def devwork_params
params.require(:devwork)
.permit!
end
end
And part of the form:
<%= form_for #devwork do |f| %>
<p>
<%= f.label :short_title %>
<%= f.text_field :short_title %>
</p>
<p>
<%= f.label :title_fr %>
<%= f.text_field :title_fr %>
<%= f.label :title_en %>
<%= f.text_field :title_en %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
short_title and title_fr are mandatory, while there exist another field title_en which is not. I want the update form to be shown again if the update fails (typically because of empty title_fr).
But it doesn't work. The update never fails (never entering render :edit) even if title_fr is empty. In fact, the update does nothing if one of the field is empty, it only updates non-empty fields.
I surely missed something somewhere, but I can't figure it out... perhaps a missuses of Globalize ?
Thanks for your help !

Rails - Validation across two forms

I have what seems to be a non-standard signup process:
[welcome! enter your email and password] => [cool, enter a lot more information] => [registered]
I'm having trouble getting rails to recognize that I want to validate only the email and password on page 1, and all the other stuff on page 2.
When the user hits the site, they see my welcome page:
class WelcomeController < ApplicationController
def index
#user = User.new
end
end
<%= form_for(#user) do %>
<div class="formItem">
<%= label_tag(:email, "Your email address:") %>
<%= text_field(:user, :email) %>
<br clear="all" />
</div>
<div class="formItem">
<%= label_tag(:password, "Select a password:") %>
<%= password_field_tag(:password) %>
<br clear="all" />
</div>
<%= submit_tag("Sign up today - it's free and easy!", :class => "submitForm") %>
<% end %>
=
class UsersController < ApplicationController
def create
#user = User.new(params[:user])
if #user.save
redirect_to(edit_user_path(#user, :noticeHeader => true ), :notice => 'Please take a minute and answer these additional questions.')
else
render :action => "welcome/index"
end
end
=
Once they click Sign Up, they see my next page of form fields.
The problem I'm running into is that I validates_presence_of fields that are on both pages, in the user model. Since these fields aren't on the welcome page, I get a "undefined local variable or method" error upon submitting the welcome page. For example, I validates_presence_of :title because I want title to be required, but it's only listed on page 2, so page 1 doesn't validate properly.
Thoughts on how to handle this?
Thanks.
Have a look into one of these plugins/gems where you can create Wizard based forms.
http://ruby-toolbox.com/categories/rails_wizards.html my favourite is "ActsAsWizard"

Resources