I cannot seem to get validation to pass in Rails 4 app using regex for email.
Subscriber.rb
class Subscriber < ActiveRecord::Base
validates_uniqueness_of :email, :case_sensitive => false, message: "You're already subscribed!"
validates_format_of :email, :with => /#/i, message: "Email is invalid"
before_save { self.email = email.downcase if email}
end
No matter how simple my regex is, I get the "Email is invalid" message.
Any ideas or am I doing something obviously wrong (regex isn't a strong suit for me).
Thanks!
_subscribe.html.erb
<%= form_for Subscriber.new do |f| %>
<%= f.text_field :email, :class => "uppercase", :placeholder => "Stay in touch. Enter your email" %>
<%= f.submit :class => "submit uppercase", :value => 'submit' %>
<% end %>
Line that calls the partial:
<%= render :partial => 'shared/subscribe', :subscriber => Subscriber.new %>
subscribers_controller.rb
include SubscribersHelper
def create
#subscriber = Subscriber.new
if #subscriber.save(subscriber_params)
redirect_to(:back)
flash.notice = "You are now subscribed"
else
redirect_to(:back)
flash.alert = "There was an error with your subscription: "
flash.alert += #subscriber.errors.messages.values.join(", ")
end
end
SubscribersHelper.rb
def subscriber_params
params.require(:subscriber).permit(:email)
end
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
Above is a pretty failsafe email RegEx.
Related
I have a problem with simple_form's associations.
Here are the models "linked"
class Contact < ApplicationRecord
belongs_to :state
end
class State < ApplicationRecord
CATEGORIES = [ "not-contacted", "on-going", "called"]
has_many :contacts
validates :category, inclusion: { in: CATEGORIES }
end
I have also a State seed with the three states above.
I'm creating the new form for a contact.
Controller :
def new
#contact = Contact.new
#states = State.all
end
def create
#contact = Contact.new(contact_params)
if #contact.save
redirect_to contact_path(params[:id])
else
render :new
end
end
View:
<%= simple_form_for(#contact) do |f| %>
<%= f.input :last_name, label: 'Nom' %>
<%= f.input :first_name, label: 'Prénom' %>
<%= f.input :number, label: 'Téléphone' %>
<%= f.input :email, label: 'Mail' %>
<%= f.input :address, label: 'Adresse' %>
<%= f.association :state, collection: State.order(:category), prompt: "Choisir un état" %>
<%= f.input :grade, label: 'Note', collection:[1, 2, 3, 4, 5] %>
<%= f.submit 'Créer le contact', class:'btn-modifications' %>
<% end %>
But I have a collection not with a list of "on-going", "called", "not-contacted" but I have a list with this:
State:0x00007fcb3afcfca8
How can I display the list I want?
You need to change it to below
<%= f.association :state, collection: State.order(:category), label_method: :category, value_method: :id,prompt: "Choisir un état" %>
While i was trying to submit the form, following error occured: Validation failed: Images imageable must exist and render the same new.html.erb view.
If i comment the file field in new.html.erb. Product is being created successfully.
ProductsController:
def new
#product = Product.new
end
def create
#product = Product.create!(product_params)
if #product.save
redirect_to products_path, notice: "Product Created Successfully"
else
render "new"
end
end
def product_params
params.require(:product).permit(:name, :quantity, :price, images_attributes: [:id, :photo, :_destroy])
end
new.html.erb:
<%= nested_form_for #product, html: { multipart: true } do |f|%>
<h2>New</h2>
<P> <%= f.label :name %> <%= f.text_field :name %> </P>
<P> <%= f.label :quantity %> <%= f.text_field :quantity %> </P>
<P> <%= f.label :price %> <%= f.text_field :price %> </P>
<%= f.fields_for :images do |p| %>
<p> <%= p.label :photo %> <%= p.file_field :photo %> </p>
<%= p.link_to_remove "Remove Image" %>
<% end %>
<%= f.link_to_add "Add Image", :images %>
<%= f.submit "Add Product" %>
<% end %>
20160725102038_add_image_columns_to_imageable.rb:
class AddImageColumnsToImageable < ActiveRecord::Migration[5.0]
def up
add_attachment :images, :photo
end
def down
remove_attachment :images, :photo
end
end
Model:product.rb
class Product < ApplicationRecord
has_one :variant
has_many :images, as: :imageable, dependent: :destroy
accepts_nested_attributes_for :images, allow_destroy: true
end
Model:image.rb
class Image < ApplicationRecord
belongs_to :imageable, polymorphic: true
has_attached_file :photo, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
validates_attachment :photo, content_type: { content_type: ["image/jpg", "image/jpeg", "image/png", "image/gif"] }
end
In rails 5, belongs_to makes sure that the associated model must exist.
E.g In this polymorphic association, Image model has belongs_to :imageable and Product model has has_many :images.
So here in new.html.erb we are creating an image, but respective product not exist, so that's why error Image imageable must exist .
Solution
Add optional: true while making an association of belong_to in Image model.
Image Model now looks like:
class Image < ApplicationRecord
belongs_to :imageable, polymorphic: true, optional: true
has_attached_file :photo, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
validates_attachment :photo, content_type: { content_type: ["image/jpg", "image/jpeg", "image/png", "image/gif"] }
end
I'm facing this problem how to fix this issue?
This is my problem, always showing an error message:
This is my model:
validates :first_name, :presence => true, :length => { :in => 3..20 }
validates :last_name, :presence => true, :length => { :in => 3..20 }
validates :email, :presence => true, :uniqueness => true, format: { with: /\A[^#\s]+#([^#.\s]+\.)+[^#.\s]+\z/ }
# validates :passkey, :confirmation => true #password_confirmation attr
validates_length_of :passkey, :presence => true, :in => 6..20, :on => :register
This is my Controller:
def register
params.permit!
#jobseekers = Jobseeker.new(params[:jobseekers])
if #jobseekers.save
redirect_to home_path
else
render "register"
end
end
This is my view:
<%= form_for :jobseekers, url: register_path(#jobseekers), method: :patch do |f| %>
<%= f.text_field :first_name, placeholder: 'First Name'%>
<%= f.text_field :last_name, placeholder: 'Last Name'%>
<%= f.text_field :email, placeholder: 'Email'%>
<%= f.password_field :passkey, placeholder: 'Password'%>
<%= f.submit "Create Account" %>
<% end %>
<% if #jobseekers.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#jobseekers.errors.count, "error") %> prohibited this article from being saved:</h2>
<ul>
<% #jobseekers.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
I need show this error after click submit button, but now showing this error always.
Please help!
Now I'm using ruby 1.9.7 rails 4.2.5 & mysql2
The problem in your code is the controller action:
def register
params.permit!
#jobseekers = Jobseeker.new(params[:jobseekers])
if #jobseekers.save
redirect_to home_path
else
render "register"
end
end
if you take a look, then you don't just create a new object #jobseekers but try to save it right away. if #jobseekers.save will be false because the params[:jobseekers] is empty when you call the action for the first time. Since you have validations, it will automatically add errors, and your register view will be rendered with those errors. This is why usually there are 2 actions with forms- new and create.
To fix this split this into two actions
def register
#jobseekers = Jobseeker.new
end
def create_register
params.permit!
#jobseekers = Jobseeker.new(params[:jobseekers])
if #jobseekers.save
redirect_to home_path
else
render "register"
end
end
where create_register only has a post route and register has a get route (register will render the form for the first time, and then after submit the create_register will be called and render the form with errors if there are any)
This would then be your view(stating the method is not necessary in this case):
<%= form_for :jobseekers, url: create_register_path(#jobseekers) do |f| %>
<%= f.text_field :first_name, placeholder: 'First Name'%>
<%= f.text_field :last_name, placeholder: 'Last Name'%>
<%= f.text_field :email, placeholder: 'Email'%>
<%= f.password_field :passkey, placeholder: 'Password'%>
<%= f.submit "Create Account" %>
<% end %>
<% if #jobseekers.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#jobseekers.errors.count, "error") %> prohibited this article from being saved:</h2>
<ul>
<% #jobseekers.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
and your routes.rb entries:
get '/register', to: "jobseekers#register"
post '/register', to: "jobseekers#create_register"
Another take on Kkulikovskis' answer would be:
def register
params.permit!
#jobseekers = Jobseeker.new(params[:jobseekers])
return true if request.get? # <--- skip validations if not on form submit
if #jobseekers.save
redirect_to home_path
else
render "register"
end
end
I prefer this approach when the instantiation of #jobseeker is less trivial
PS params.permit! is a path to hell, don't do it
I am getting the following error while trying to do reset password by sending sending the link to email and open that link from that email.
Error:
NoMethodError in Admins#editpass
Showing C:/Site/swargadwar_admin/app/views/admins/editpass.html.erb where line #16 raised:
undefined method `Password_field' for #<ActionView::Helpers::FormBuilder:0x21c0108>
Extracted source (around line #16):
13: <% end %>
14: <p>
15: <label for "new_pass">New Password :</label>
16: <%= f.Password_field :password,placeholder:"Enter your new password" %>
17: </p>
18: <p>
19: <label for "new_pass">Confirm New Password :</label>
Rails.root: C:/Site/swargadwar_admin
Application Trace | Framework Trace | Full Trace
app/views/admins/editpass.html.erb:16:in `block in _app_views_admins_editpass_html_erb___904659562_17338176'
app/views/admins/editpass.html.erb:2:in `_app_views_admins_editpass_html_erb___904659562_17338176'
Please check my below codes and let me to know where i did the mistake as well as try to help me to resolve this.
views/admins/editpass.html.erb
<center>
<%= form_for :admin,:url => {:action => "setpass",:id => params[:id] } do |f| %>
<% if #admin.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#admin.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #admin.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<label for "new_pass">New Password :</label>
<%= f.Password_field :password,placeholder:"Enter your new password" %>
</p>
<p>
<label for "new_pass">Confirm New Password :</label>
<%= f.Password_field :password_confirmation,placeholder:"confirm your new password" %>
</p>
<p>
<%= f.submit "Submit" %>
</p>
<% end %>
</center>
controller/admins_controller.rb
class AdminsController < ApplicationController
def create_registration
#admin=Admin.new(params[:admin])
if #admin.save
flash[:notice]="User has created successfully"
flash[:color]="valid"
redirect_to :action => "index" , :controller => 'homes'
else
flash[:alert]="User could not created"
flash[:color]="invalid"
render 'homes/index'
end
end
def forget
#admin=Admin.new
end
def resetpass
#admin=Admin.find_by_email(params[:admin][:email])
if #admin.email==params[:admin][:email]
UserMailer.registration_confirmation(#admin).deliver
flash[:notice]="Check your email to reset the password"
flash[:color]="valid"
redirect_to :action => "index" , :controller => 'homes'
else
flash[:alert]="Invalid email id"
flash[:color]="invalid"
render 'homes/index'
end
end
def editpass
#admin=Admin.new
end
def setpass
#admin=Admin.find(params[:id])
if #admin.update_attributes(params[:admin])
flash[:notice]="Your password has updated successfully"
flash[:color]="valid"
redirect_to :action => "index" , :controller => 'homes'
else
flash[:alert]="Your password could not updated"
flash[:color]="invalid"
render 'homes/index'
end
end
end
model/admin.rb
class Admin < ActiveRecord::Base
attr_accessible :email, :password_hash, :password_salt, :picture, :user_name,:password_confirmation,:password, :remember_me
attr_accessor :password
attr_accessor :remember_token
before_save :encrypt_password
mount_uploader :picture, PictureUploader
EMAIL_REGEX = /\A[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\z/i
validates :email, :presence => true, :uniqueness => true, :format => EMAIL_REGEX
validates :user_name, :presence => true, :length => {:in => 3..10}
validates :password, :confirmation => true
validates_length_of :password, :in => 6..20, :on => :create
has_secure_password
def encrypt_password
if password.present?
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
end
end
def self.authenticate(email, password)
user = find_by_email(email)
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
def Admin.digest(string)
cost = 10
BCrypt::Password.create(string, cost: cost)
end
# Returns a random token.
def Admin.new_token
SecureRandom.urlsafe_base64
end
# Remembers a user in the database for use in persistent sessions.
def remember
self.remember_token = Admin.new_token
update_attribute(:remember_digest, Admin.digest(remember_token))
end
def forget
update_attribute(:remember_digest, nil)
end
end
Please help me.
You just have a typo: The method is named password_field, not Password_field. Just change the two method calls in app/views/admins/editpass.html.erb and you are done.
I've added some parameters to a small User class using the Devise gem and am having some trouble with current_password. On my account update form, I receive the error "Can't be blank" when I update an account and type in the current password. The account is subsequently not updated. I suspect it is being sanitized somewhere which deletes the input and then is read as blank. However I am not sure. I have included anything I thought to be relevant below.
User model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :username, :email, :password, :password_confirmation, :remember_me, :about_me
has_many :microposts
end
Application controller:
class ApplicationController < ActionController::Base
protect_from_forgery
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email)}
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email)}
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:username, :about_me, :email, :password, :password_confirmation, :current_password)}
end
end
password controller:
class Users::PasswordsController < Devise::PasswordsController
def resource_params
params.require(:user).permit(:email, :password, :password_confirmation, :current_password)
end
private :resource_params
end
Registration controller
class Users::RegistrationsController < Devise::RegistrationsController
before_filter :configure_permitted_parameters
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit(:username, :about_me, :email, :password, :password_confirmation)
end
devise_parameter_sanitizer.for(:account_update) do |u|
u.permit(:username, :about_me, :email, :password, :password_confirmation, :current_password)
end
end
end
routes for devise:
devise_for :users, :controllers => {:registrations => "users/registrations", :passwords => "users/passwords" }
the view in question (standard devise /registrations/edit form):
<h2>Edit <%= resource_name.to_s.humanize %></h2>
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :email, required: true, autofocus: true %>
<%= f.input :username, required: false, autofocus: true %>
<%= f.input :about_me, required: false, autofocus: true %>
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<p>Currently waiting confirmation for: <%= resource.unconfirmed_email %></p>
<% end %>
<%= f.input :password, autocomplete: "off", hint: "leave it blank if you don't want to change it", required: false %>
<%= f.input :password_confirmation, required: false %>
<%= f.input :current_password, hint: "we need your current password to confirm your changes", required: true %>
</div>
<div class="form-actions">
<%= f.button :submit, "Update" %>
</div>
<% end %>
<h3>Cancel my account</h3>
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %></p>
Again, the problem is that when the password to confirm changes is typed in, the error message "can't be blank" appears next to the field. Any ideas? Thank you
This is an issue I've had trouble in the past with, and something that requires a little bit of a work-around. By default, Devise's :registerable module allows a user to change their information, and requires the :password and :password_confirmation parameters to be entered. As I understand it, you're trying to require the user to enter and confirm their :current_password.
In order to implement the behavior you're looking for, you'll have to override Devise's RegistrationsController. I also don't think you'll need the PasswordsController, since Devise's RegistrationsController handles that for you. You'll need to write and implement a method that checks the validity of the user's :current_password, and then redirects them to the right places via the update action. You can write the following private method in your Users::RegistrationController class:
def needs_password?(user, params)
user.email != params[:user][:email] ||
params[:user][:password].present? ||
params[:user][:password_confirmation].present?
end
Then revise your update method in User::RegistrationsController as follows:
class Users::RegistrationsController < Devise::RegistrationsController
def update
#user = User.find(current_user.id)
successfully_updated = if needs_password?(#user, params)
#user.update_with_password(devise_parameter_sanitizer.sanitize(:account_update))
else
# remove the virtual current_password attribute
# update_without_password doesn't know how to ignore it
params[:user].delete(:current_password)
#user.update_without_password(devise_parameter_sanitizer.sanitize(:account_update))
end
if successfully_updated
set_flash_message :notice, :updated
# Sign in the user bypassing validation in case their password changed
sign_in #user, :bypass => true
redirect_to after_update_path_for(#user)
else
render "edit"
end
end
Hopefully that will help. You can also refer to Devise's documentation on how to do this: https://github.com/plataformatec/devise/wiki/How-To%3a-Allow-users-to-edit-their-account-without-providing-a-password.