Two-page sign-up process in rails? - ruby-on-rails-3.1

I'm attempting to create a rails app where a user will sign up, then immediately be directed to fill out a profile with more detailed information.
I'm currently attempting this by having both a users and a profile model, with a has_one/belongs_to relationship between the two models.
I'm having trouble with createing the profile for the user. Tests fail with undefined methodprofiles' for #when testing the creation, and using an automated profile builder calledsample_data.rake`:
namespace :db do
desc "Fill database with sample data"
task :populate => :environment do
Rake::Task['db:reset'].invoke
admin = User.create!(:name => "name name",
:email => "fakename#fake.com",
:password => "password",
:password_confirmation => "password")
admin.toggle!(:admin)
99.times do |n|
name = Faker::Name.name
email = Faker::Internet.email
password = "password"
User.create!(:name => name,
:email => email,
:password => password,
:password_confirmation => password)
end
User.all.each do |user|
User.profiles.create(:city => Faker::Address.city,
:state => Faker::Address.us_state_abbr,
...
)
end
end
end
Also fails on
I'm having trouble with createing the profile for the user. Tests fail with undefined method 'profiles'
profiles_controller.rb is:
class ProfilesController < ApplicationController
before_filter :authenticate, :only => [:create, :edit]
def create
#profile = current_user.profiles.build(params[:profile])
if #profile.save
flash[:success] = "Profile Created!"
redirect_to root_path
else
render 'pages/home'
end
end
def edit
end
end
profile.rb is
class Profile < ActiveRecord::Base
attr_accessible :city, :state, ...
belongs_to :user
validates :city, :presence => true
validates :state, :presence => true
...
end
Can anyone see what I'm doing wrong? Is there a way to merge all the items I need under "users", validate the presence of all the required information, and have the signup process be two pages?
Other suggestions for this?

Why do you do this?
1.times do...end
You dont need that.
The failure comes up because you need to create ONE profile, not profiles, for one certain user.
So try this:
User.all.each do |user|
user.create_profile(:city => "bla", ...)
end
In you controller the same. You have just one profile, using singular will help out.

Related

Add a record in Many to many relation fails

I have a many to many connection in Rails applications, it looks like this:
class Workspace
has_and_belongs_to_many :users, dependent: :destroy
end
class User
has_and_belongs_to_many :workspaces
end
class UserWorkspace
belongs_to :user
belongs_to :workspace
end
Schema:
create_table :users_workspaces do |t|
t.integer :user_id
t.integer :workspace_id
t.integer :role, default: 0
t.timestamps null: false
end
Then I want to create a new record like this:
#user.workspaces.create(:workspace_id => #workspace.id, :role => 1)
or this
#user.workspaces << #workspace
and have an error in logs:
(0.0ms) begin transaction
(0.0ms) begin transaction
(0.1ms) rollback transaction
(0.1ms) rollback transaction
Completed 500 Internal Server Error in 207ms (ActiveRecord: 5.5ms)
Completed 500 Internal Server Error in 207ms (ActiveRecord: 5.5ms)
ActiveRecord::UnknownAttributeError (unknown attribute 'workspace_id' for Workspace.):
app/controllers/sessions_controller.rb:10:in `block in sign_up'
app/controllers/sessions_controller.rb:4:in `sign_up'
What am I doing wrong?
PS Controller:
def sign_up
respond_to do |format|
#user = User.new(user_params)
if #user.save
#workspace = Workspace.new(title: "#{#user.name}'s workspace")
#workspace.save
puts "workspace id: #{#workspace.id}"
#user.workspaces.create(:workspace_id => #workspace.id, :role => 1)
puts "workspaces count: #{#user.workspaces.count}"
#user.workspace = #workspace
#user.update_attributes(user_params)
flash.now[:success] = 'Welcome! Please check activation letter in your email box.'
format.js { render 'signup_message' }
else
format.js { render 'render_signup_errors' }
end
end
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation, :name, :workspace_id)
end
There are couple of problems with your code. For example, you are creating workspaces that are already created (#user.workspaces.create), or permitting a :workspace_id that is not used, etc.
Pleas see code below:
def sign_up
respond_to do |format|
#user = User.new(user_params)
if #user.save
#workspace = Workspace.new(title: "#{#user.name}'s workspace")
if #workspace.save
# Like this
UserWorkspace.create(user: #user, workspace: #workspace, role: 1)
# Or, like this
#user.user_workspaces.create!(workspace_id: #workspace.id, role: 1)
end
flash.now[:success] = 'Welcome! Please check activation letter in your email box.'
format.js { render 'signup_message' }
else
format.js { render 'render_signup_errors' }
end
end
end
private
# You don't need :workspace_id since you are not using it anywhere
def user_params
params.require(:user).permit(:email, :password, :password_confirmation, :name)
end

undefined method `activation_digest=' for #<User:0x007fe3810ceba0> Michael Hartl's book

I am working through Michael Hartl's Rails book and I am about halfway through chapter 10-working on account activation.
I had everything working with the mailers but then when I tried to add a new user, I got the following error message: "undefined method `activation_digest=' for #"
I have been trying to follow along in the book the best that I can. I have my users_controller.rb here:
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update]
before_action :correct_user, only: [:edit, :update]
def new
#user = User.new
end
def index
#users = User.paginate(page: params[:page], :per_page => 10)
end
def show
#user = User.find(params[:id])
end
def create
#user = User.new(user_params)
if #user.save
#user.send_activation_email
flash[:info] = "Please check your email to activate your account."
redirect_to root_url
else
render 'new'
end
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
else
render 'edit'
end
end
def edit
#user = User.find(params[:id])
end
#confirms if a user is logged in
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please Log In."
redirect_to login_url
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
end
Here is my Model/user.rb:
class User < ActiveRecord::Base
attr_accessor :remember_token, :activation_token
before_save :downcase_email
before_create :create_activation_digest
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: { minimum: 6 }
# Returns the hash digest of the given string.
def User.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Engine.cost
BCrypt::Password.create(string, cost: cost)
end
#Returns a random token
def User.new_token
SecureRandom.urlsafe_base64
end
#Remembers a user in the database for use in persistent sessions
def remember
self.remember_token = User.new_token
update_attribute(:remember_digest, User.digest(remember_token))
end
#Returns true if the given token matches the digest
def authenticated?(remember_token)
return false if remember_digest.nil?
BCrypt::Password.new(remember_digest).is_password?(remember_token)
end
#forgets a user
def forget
update_attribute(:remember_digest, nil)
end
private
# Converts email to all lower-case.
def downcase_email
self.email = email.downcase
end
# Creates and assigns the activation token and digest.
def create_activation_digest
self.activation_token = User.new_token
self.activation_digest = User.digest(activation_token)
end
end
The routes I have this:
root 'static_pages#home'
get 'sessions/new'
get 'users/new'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :users
resources :account_activations, only: [:edit]
Please let me know if anything more is needed to be seen. I do have my App up on Github under the name sample_app, my username is ravenusmc.
Looking at your project on Github, your User model doesn't have an activation_token or activation_digest column, nor does the model define them as attributes.
Your User model is trying to write to these columns in the User#create_activation_digest function which is most likely causing the issue.
You'll need to write a migration to add those columns to your User model or add them is attributes (ie attr_accessor) if they are not meant to be persisted.

Stack level too deep or unknown attribute: password_confirmation

I'm working on a web app that has users model. You either sign up or try the app and be a 'guest'. I had the sign up functionality working well until I added the guest option. I based on Railscast to do this (http://railscasts.com/episodes/393-guest-user-record) and that's when I ran into troubles
Here is my user model code
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation
has_many :bookings
has_one :account, dependent: :destroy
# before_save :downcase_email, allow_nil: true
before_save :create_remember_token
validates_presence_of :name, :email, :password, :password_confirmation, unless: :guest?
validates_uniqueness_of :email, case_sensitive: false , allow_blank: true
validates :name, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, format: { with: VALID_EMAIL_REGEX }, unless: :guest?
validates :password, length: { minimum: 6 }, unless: :guest?
def downcase_email
{ |user| user.email = email.downcase }
end
# has_secure_password
# override has_secure_password to customize validation until Rails 4.
require 'bcrypt'
attr_reader :password, :password_confirmation
include ActiveModel::SecurePassword::InstanceMethodsOnActivation
##def to_param
## "#{id}.#{name.parameterize}"
##end
def self.new_guest
new { |u| u.guest = true }
end
def name
guest ? "Guest" : name
end
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
end
and here is my User Controller code:
class UsersController < ApplicationController
before_filter :signed_in_user, only: [:edit, :update]
before_filter :correct_user, only: [:edit, :update]
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = params[:user] ? User.new(params[:user]) : User.new_guest
if #user.save
sign_in #user
#user.create_account.accountPlan = "Free"
##flash[:success] = "Welcome to the HighTide!"
redirect_to #user
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
#flash[:success] = "Profile updated"
sign_in #user
redirect_to #user
else
render 'edit'
end
end
private
def correct_user
#user = User.find(params[:id])
redirect_to(root_path) unless current_user?(#user)
end
def admin_user
redirect_to(root_path) unless current_user.admin?
end
end
you may notice some code is commented out. I wasn't able to store in the database a user without an email (and for have a quick and dirty thing working now I comment the callback before_save, I also might add that I use the guidelines of Michael Hartl tut)
What happens is, when I run this code I get a unknown attribute: password_confirmation error, but when I comment out
require 'bcrypt'
attr_reader :password, :password_confirmation
include ActiveModel::SecurePassword::InstanceMethodsOnActivation
and use has_secure_password instead
I get a stack level too deep
I haven't figured out what to do

User specific Redirect after successful login in ruby on rails

Currently I am working on a sms application .I used devise gem for authentication and carrier wave for uploading. My question is after a successful login a user has to redirect to his own page and different users will be having redirecting to different pages.
User model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
# attr_accessible :title, :body
has_many :sms
end
Sm model
class Sm < ActiveRecord::Base
attr_accessible :Messages, :Mobile_no, :Nickname, :Templates
validates_presence_of :Mobile_no
validates_length_of :Mobile_no, :minimum => 10, :maximum => 10, :allow_blank => true
validates :Mobile_no, :numericality => {:only_integer => true}
attr_accessible :sm_id, :name, :image
belongs_to :sm
mount_uploader :image, ImageUploader
validate :image_size_validation, :if => "image?"
def image_size_validation
errors[:image] << "should be less than 1MB" if image.size > 1.megabytes
end
validates :image, allow_blank: true, format: {
with: %r{\.(xls|xlsx|csv|txt)\z}i,
message: 'must be a TXT, CSV, XLS, or XLSX'
}, if: :filename_has_extension?
def filename_has_extension?
!(image.to_s =~ /\.[a-z]{1,4}\z/).nil?
end
belongs_to :user
end
You should define after_sign_in_path_for method in ApplicationController
def after_sign_in_path_for(resource)
# resource is commonly a User class object
if resource.admin?
# redirect somewhere
else
# redirect somewhere else
end
end

Paperclip "Gem" Rails 3.1 undefined method model file name

Using rails 3.1.1, Ruby 1.9.2,
Gems: gem 'haml', gem 'simple_form', gem 'aws-sdk',
gem 'paperclip', :git => "git://github.com/thoughtbot/paperclip.git"
plugin: country_select: git://github.com/rails/country_select.git
Having an issue uploading/displaying images pushed to Amazon S3 through paperclip (GEM)
Error: undefined method `avatar_file_name' for #Player:0x00000102aff228
For the most part I was following the example on the git-hub page for paperclip
https://github.com/thoughtbot/paperclip
Here is what I have in my code:
Migration: 20111224044508_create_players.rb
class CreatePlayers < ActiveRecord::Migration
def change
create_table :players do |t|
t.string :first_name
t.boolean :first_name_public, :default => false
...
t.string :website
t.boolean :website_public, :default => false
t.has_attached_file :avatar
t.timestamps
end
end
end
Model: Player.rb:
class Player < ActiveRecord::Base
attr_accessible :first_name, ... :website
validates_presence_of :username, :email
has_attached_file :avatar,
:styles => { :medium => "300x300>", :thumb => "100x100>" },
:storage => :s3,
:s3_credentials => "#{Rails.root}/config/s3.yml",
:path => ":class/:id/:style/:filename"
{Unrelated validations}
end
S3 file: s3.yml
development:
bucket: voh_development
access_key_id: *********************
secret_access_key: ********************
staging:
bucket: voh_staging
access_key_id: *********************
secret_access_key: ********************
production:
bucket: voh_production
access_key_id: *********************
secret_access_key: ********************
Controller: players_controller.rb
class PlayersController < ApplicationController
def create
#player = Player.create(params[:player])
if #player.save
redirect_to players_path, :notice => "Player Created";
else
render :action => 'new'
end
end
{basic restful}
end
Views:
Edit.html.haml + New.html.haml
= simple_form_for #player do |f|
= f.input :first_name
...
= f.input :website
= f..file_field :avatar
.input_div
= f.button :submit
index.html.haml
...
%td Avatar
%td First Name
...
%td Actions
- #players.each do |player|
%tr
%td
= image_tag #player.avatar.url(:thumb)
%td
= player.first_name
...
%td
= link_to ' Show ', player_path(player.id)
|
= link_to ' Edit ', edit_player_path(player.id)
show.html.haml
= image_tag #user.avatar.url
%br
= #player.first_name
...
Research:
I found a lot to do with the pluging and genration of the migration but it all seems old. Most of them suggest putting in the up down in the migration for the 4 attributes. However it seems that should have been replaced by the one line t.has_attached_file :avatar.
I have a rails 3.0 project and this worked. I am able to upload products and pull them back down. (had to play with the suggested image_tag #icon.avatar.url and turned it into %img{:src => URI.unescape(icon.icon.url)} but that a different question.)
TLDR: Fixed typo in index.html.haml from #player => player, Added :avatar to attr_accessible.
I woke up this morning and had a different error.
instead of: undefined method Avatar_file_name'
I got: undefined method avatar' for nil:NilClass
That error was caused buy a simple type in my code. I used an instance vairable instead of .each variable I should have been using (index.html.haml:9)
Now the app was not erring out but the file was still not uploading.
In the development log I found this. (I did not look here the first time I posted)
WARNING: Can't mass-assign protected attributes: avatar
I then went and added :Avatar to attr_accessible and everything started working.
Not sure if this is supposed to be required or not but I did see that they had updated S3 header to be a proc yesterday.
https://github.com/thoughtbot/paperclip/tree/master/test/storage
I am not going to close this out yet. There will be an edit because I am going to play with the version and quickly report my findings today. Then I will close this out.
Edit:
I tryed switch back to 2.4.5 and I am getting the error that made me switch to pulling master in the first place. When attempting to do a migration with t.has_attached_file :avatar it fails to migrate and gives the following error.
undefined method `has_attached_file' for #ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::TableDefinition:0x00000105053600
I think I will stick with pulling from master.

Resources