I'm trying to create a user sign up form with Devise that will also allow for the creation of a new business associated with that user.
I have a business model setup and can't seem to save the business information to the database. Below is my code, I'm fairly new to rails so I apologize if I'm asking a question with an obvious answer.
new.html.erb (user)
<div class="content">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1>Sign Up</h1>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="form-group">
<label>Name</label>
<%= f.text_field :username, :autofocus => true, :class => "form-control", :placeholder => "Full Name" %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.text_field :email, :class => "form-control", :placeholder => "Email" %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, :class => "form-control", :placeholder => "Password" %>
<p class="help-block">Passwords must be a minimum of 8 characters.</p>
</div>
<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, :class => "form-control", :placeholder => "Retype Password" %>
</div>
<!-- Business Infomation -->
<h2>Business Information</h2>
<%= f.fields_for :business do |b| %>
<div class="form-group">
<%= b.label :name %>
<%= b.text_field :name, :class => "form-control", :placeholder => "Business Name" %>
</div>
<div class="form-group">
<%= b.label :address %>
<%= b.text_field :address, :class => "form-control", :placeholder => "Address" %>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<%= b.label :city %>
<%= b.text_field :city, :class => "form-control", :placeholder => "City" %>
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<%= b.label :state %>
<%= b.text_field :state, :class => "form-control", :placeholder => "State" %>
</div>
</div>
<div class="col-sm-4">
<div class="form-group">
<%= b.label :zip %>
<%= b.text_field :zip, :class => "form-control", :placeholder => "ZIP" %>
</div>
</div>
</div>
<div class="form-group">
<%= b.label :country %>
<%= b.text_field :country, :class => "form-control", :placeholder => "Country" %>
</div>
<% end %>
<div class="well">
<%= f.submit "Sign Up", :class => "btn btn-primary" %>
</div>
<% end %>
</div>
</div>
user.rb
class User
include Mongoid::Document
include Mongoid::Paperclip
rolify
include Mongoid::Timestamps
#embeds_many :businesses, :class_name => "Business"
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :role_ids, :as => :admin
attr_accessible :username, :email, :password, :password_confirmation, :remember_me, :business_ids,
:reset_password_sent_at, :reset_password_within, :address, :city, :state, :zip, :country, :phone, :business_attributes
has_one :businesses
accepts_nested_attributes_for :businesses
validates_format_of :email, :with=>email_regexp, :allow_blank => true, :message=> "Justin"
#intercom
attr_accessor :company_name
attr_accessible :company_name
## Database authenticatable
field :email, :type => String, :default => ""
field :encrypted_password, :type => String, :default => ""
## Recoverable
field :reset_password_token, :type => String
#field :reset_password_sent_at, :type => Time
field :reset_password_sent_at, :type => Time
## Rememberable
field :remember_created_at, :type => Time
#field :remember_created_at, :type => String
## Trackable
field :username, :type => String
field :sign_in_count, :type => Integer, :default => 0
#field :current_sign_in_at, :type => Time
#field :last_sign_in_at, :type => Time
field :current_sign_in_at, :type => Time
field :last_sign_in_at, :type => Time
field :current_sign_in_ip, :type => String
field :last_sign_in_ip, :type => String
field :first_name, :type => String
field :last_name, :type => String
#field :business_ids, :type => Array
field :address, :type => String
field :city, :type => String
field :state, :type => String
field :zip, :type => String
field :country, :type => String
field :phone, :type => String
# User Avatar
attr_accessible :avatar
has_mongoid_attached_file :avatar,
:styles => { :full => ["512x512>", :jpg], :medium => ["256x256>", :jpg] },
:convert_options => {:medium => "-background black -gravity center -extent 256x256"},
:default_url => "/assets/avatar-blank.png"
validates_attachment_size :avatar, :less_than => 5.megabytes
validates_attachment_content_type :avatar, :content_type => ['image/jpeg', 'image/jpg', 'image/png', 'image/gif']
## Confirmable
# field :confirmation_token, :type => String
# field :confirmed_at, :type => Time
# field :confirmation_sent_at, :type => Time
# field :unconfirmed_email, :type => String # Only if using reconfirmable
## Lockable
# field :failed_attempts, :type => Integer, :default => 0 # Only if lock strategy is :failed_attempts
# field :unlock_token, :type => String # Only if unlock strategy is :email or :both
# field :locked_at, :type => Time
## Token authenticatable
# field :authentication_token, :type => String
after_create :create_business
def create_business
Business.create(business_id: self.id)
end
def assign_default_role(b)
# assign a default role if no role is assigned
# IF, invite token make user an editor for business
# ELSE, make the user owner of the business
self.add_role "owner", b
end
#Returns a businesses for a user. The return type is an array of Business models.
def businesses
Business.find(get_business_ids)
end
#returns the user business_ids (Array of Strings)
def get_business_ids
Business.find_roles(nil, self).map{|b| b.resource_id.to_s}.to_a
end
end
Try override Devise's registration controller:
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def create
# save business here
end
end
And then tell devise to use customized controller:
# app/config/routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}
Related
Can anybody please help me to resolve the following error using rails version-3.2.19 ?When i am submitting values to database this error is coming.
Error
ActiveModel::MassAssignmentSecurity::Error in UsersController#create
Can't mass-assign protected attributes: con_password
My code snippets are as follows.
views/users/new.html.erb
<center>
<h1>Enter your data</h1>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-div">
<%= form_for :user,:url => {:action => 'create'} do |f|%>
<p>
<%= f.label :Name %>
<%= f.text_field :name,placeholder:"Enter your name" %>
</p>
<p>
<%= f.label :Email %>
<%= f.email_field :email,placeholder:"Enter your Email" %>
</p>
<p>
<%= f.label :Password %>
<%= f.password_field :password,placeholder:"Enter your password" %>
</p>
<p>
<%= f.label :password %>
<%= f.password_field :con_password,placeholder:"Enter your password again" %>
</p>
<p>
<%= f.label :content %>
<%= f.text_field :content,placeholder:"Enter your content" %>
</p>
<p>
<%= f.submit "Create User",:class => 'submit' %>
</p>
<% end %>
</div>
</center>
controller/users_controller.rb
class UsersController < ApplicationController
def index
end
def new
#user=User.new
end
def show
end
def create
#user=User.new(params[:user])
if #user.save
flash[:notice]="User has created successfully"
flash[:color]="valid"
redirect_to :action => 'index'
else
flash[:alert]="User could not create"
flash[:color]="invalid"
render :new
end
end
end
model/user.rb
class User < ActiveRecord::Base
attr_accessible :content, :email, :name, :password
EMAIL_REGEX = /\A[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\z/i
validates :name, :presence => true, :uniqueness => true, :length => { :in => 3..20 }
validates :email, :presence => true, :uniqueness => true, :format => EMAIL_REGEX
validates :password, :confirmation => true
validates_length_of :password, :in => 6..20, :on => :create
end
migrate\20150128062543_create_users.rb
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :email
t.string :password
t.string :content
t.timestamps
end
end
end
Please help me to solve this issue.
Instead of <%= f.password_field :con_password,placeholder:"Enter your password again" %>, you should name your field password_confirmation, because this is what your model expects if it has validates :password, confirmation: true:
<%= f.password_field :password_confirmation, placeholder: "Enter your password again" %>
You also have to add password_confirmation to attr_accessible in the model.
I am getting undefined method 'session_path' for #<#<Class:0x9859218>:0x8ebcbd0> when using devise with my custom controller and view, can anybody shed some light on what I have done wrong?
routes:
devise_for :users, :skip => [:sessions]
as :user do
get 'account/login' => 'account#login', :as => :new_user_session
post 'account/login' => 'account#login_user', :as => :user_session
delete 'account/logout' => 'account#logout', :as => :destroy_user_session
end
controller:
AccountController < Devise::SessionsController
def login
self.resource = resource_class.new(sign_in_params)
clean_up_passwords(resource)
respond_with(resource, serialize_options(resource))
end
def login_user
self.resource = warden.authenticate!(auth_options)
set_flash_message(:notice, :signed_in) if is_flashing_format?
sign_in(resource_name, resource)
yield resource if block_given?
respond_with resource, location: after_sign_in_path_for(resource)
end
def logout
signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
set_flash_message :notice, :signed_out if signed_out && is_flashing_format?
yield if block_given?
respond_to_on_destroy
end
view:
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<ul>
<li>
<%= f.label :login, "Email", :class => labels %>
<%= f.email_field :login, :autofocus => true, :class => "wideinput" %>
</li>
<li>
<%= f.label :password, :class => "labels" %>
<%= f.password_field :password, :autocomplete => "off" %>
</li>
<li class='button'>
<%= submit_tag "Login", :class => "btn1" %>
</li>
</ul>
<% end %>
Try to change this line
post 'account/login' => 'account#login_user', :as => :user_session
to
post 'account/login' => 'account#login_user', :as => :session
I updated to Rails4, and am now getting "wrong number of arguments (3 for 2)".
.col-md-6.col-md-offset-3
= form_for(resource, :as => resource_name, url: session_path(resource_name), :html => { :class => "search-form home-search"}) do |f|
= f.email_field :email, :id => 'beta_form', :class => 'beta_form', :placeholder => 'Email'
= f.password_field :password, :id => 'beta_form', :class => 'beta_form', :placeholder => 'Password'
= f.submit "Sign In", :class => 'btn btn-primary btn-lg btn-block beta_submit center-block'
= render "devise/shared/links"
All set. For some reason, I had to delete gem 'meta-search' after upgrading.
This is the error I am getting:
ArgumentError in Home#index
Showing /app/views/clients/_form.html.erb where line #6 raised:
You need to supply at least one validation
Extracted source (around line #6):
3: render :partial => "clients/form",
4: :locals => {:client => client}
5: -%>
6: <% client ||= Client.new
7: new_client = client.new_record? %>
8: <%= form_for(client, :html => { :class=>"ajax-form", :id => "client-ajax-form"}, :remote => true, :disable_with => (new_client ? "Adding..." : "Saving...")) do |f| %>
9: <div class="validation-error" style="display:none"></div>
My client model looks like this:
class Client < ActiveRecord::Base
# the user model for the client
belongs_to :user
has_many :projects, :order => 'created_at DESC', :dependent => :destroy
#The following produces the designers for a particular client.
#Get them from the relations where the current user is a client.
has_one :ownership, :dependent => :destroy
has_one :designer, :through => :ownership
validates :name, :presence => true,
:length => {:minimum => 1, :maximum => 128}
validates :number_of_clients
def number_of_clients
Authorization.current_user.clients.count <= Authorization.current_user.plan.num_of_clients
end
end
This is how the app/views/client/_form.html.erb partial looks:
<%#
Edit a single client
render :partial => "clients/form",
:locals => {:client => client}
-%>
<% client ||= Client.new
new_client = client.new_record? %>
<%= form_for(client, :html => { :class=>"ajax-form", :id => "client-ajax-form"}, :remote => true, :disable_with => (new_client ? "Adding..." : "Saving...")) do |f| %>
<div class="validation-error" style="display:none"></div>
<div>
<label for="client_name"><span class="icon name-icon"> </span></label>
<input type="text" class="name" size="20" name="client[name]" id="client_name" value="<%= client.name %>" > <%= f.submit(new_client ? "Add" : "Save", :class=> "green awesome")%>
</div>
<% end %>
<% content_for(:deferred_js) do %>
// From the Client Form
$('#client-ajax-form')
.bind("ajax:success", function(evt, data, status, xhr){
console.log("Calling Step View");
compv.updateStepView('client', xhr);
});
<% end %>
How do I fix that error ?
The problem is caused by the following line in your model:
validates :number_of_clients
When you use validates (s in the end) you have to follow the default rails validations like you did with the name validation. However, when you use a custom method to do the validation, you should use validate instead. So this should work:
validate :number_of_clients
So this is what my devise/sessions/new.html.erb looks like:
<div id="sign_in">
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
<%= f.text_field :f_name, :value => "First Name", :class => "clearField curved" %><div class="error"></div><br />
<%= f.text_field :l_name, :value => "Last Name", :class => "clearField curved" %><div class="error"></div><br />
<%= f.text_field :username, :value => "Username", :class => "clearField curved" %><div class="error"></div><br />
<%= f.password_field :password, :value => "Password", :class => "clearField curved" %><div class="error"></div><br />
<%= f.password_field :password_confirmation, :value => "Password", :class => "clearField curved" %><div class="error"></div><br />
<%= f.text_field :email, :value => "Email Address", :class => "clearField curved" %><div class="error"></div><br />
<div id="login_buttons">
<%= f.submit "Sign in", :id => "login", :value => "Submit", :class => "curved" %>
<%= f.submit "Sign in", :id => "register", :value => "Register", :class => "curved" %>
<%= f.submit "Send Reset Instructions", :id => "pass-reset", :value => "Send Reset Instructions", :class => "curved"%>
Forgot pass?
</div>
<% end %>
</div>
The above only works for the login (because the :url => session_path(resource_name) and not registration_path).
What this page does now, is on pageload it hides every field except the username & password field (i.e. it defaults to the login page). Then when they press the 'Register' button, it fades in the others.
However, when you press submit that doesn't work - because the wrong form handler is managing it.
This is what my regular registration form looks like (which works, btw) at devise\registrations\new.html.erb:
<h2>Sign up</h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<p><%= f.label :username %><br />
<%= f.text_field :username %></p>
<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>
<p><%= f.submit "Sign up" %></p>
<% end %>
<%= render :partial => "devise/shared/links" %>
The applicable part of my routes file looks like this:
devise_for :users, :path_names => { :sign_up => "register",
:sign_in => "login",
:sign_out => "logout" }
devise_scope :user do
get "login", :to => "devise/sessions#new"
get "register", :to => "devise/registrations#new"
get "logout", :to => "devise/sessions#destroy"
So the behavior I want is as follows:
The user goes to login, they see only two form fields (username + password). They press enter it logs them in.
If they press 'Register', without doing a pageload, I would like the right form (with the additional form fields required: first name, last name, etc.) to appear and when they press enter it does the registration. I would also like the URL to change from myapp.com/login to myapp.com/register - without a page load. If they pressed 'Sign In' without filling out the form, it should take them back to the login page (myapp.com/login) with only the two fields (username + pass) showing.
That way when I link directly to myapp.com/register it goes directly to that one page with the correct form fields and it functions properly.
Basically functionality similar to the way github now manages browsing through a repo with no page refreshes (but the URL changes).
Suggestions?
To combine user registration with user login on the same page, I did the following:
1) Copy all the code from views/sessions/new INTO view/registrations/new
2) Modify the submit button id/js namespace:
<%= f.submit 'submit_button', :style => "display: none", :id => "submitSignInForm" %><br>
<a class="button" href="javascript:document.getElementById('submitSignInForm').click();"> Sign in </a>"
3) Override the Devise Session Controller new method with a redirect.
create controllers/sessions_controller.rb and insert the following code. Note the controller class inherits from Registrations, not Sessions!
class SessionsController < Devise::RegistrationsController
def new
redirect_to new_user_registration_path
end
end
*I should note, this worked in rails 2.3.5, but I think it will work in 3.0 the same.