Generate a new user programmatically (Auth Logic) - ruby-on-rails

I'm quite new to Ruby on Rails so please bear with me :)
I'm processing an imported .csv file in Rails and I want to programmatically create new users (I'm using the AuthLogic Gem along with Role Requirement), So Far I'm using:
Example Line:
Steve.Jobs#apple.com, Steve, Jobs, 555-APPLE
Code:
def new_user(line)
params = Hash.new
params[:user] = Hash.new
params[:user]["email"] = line[0]
params[:user]["first_name"] = line[1]
params[:user]["last_name"] = line[3]
params[:user]["phone"] = line[4]
user = User.new(params[:user])
user.save
end
The problem being that this doesn't add a new user, it tries to but fails (DB Begin followed by Rollback), I assume because I'm not filling in all the fields, such as login, password etc.
Do I have to explicitly generate values for these fields?

I came across this same problem yesterday. I'm using the oauth addon though so the login/email are not required fields for me, it was failing on the persistence token not being present which I got around by adding
user.reset_persistence_token
just before calling user.save
Hope that helps a bit. Would be nice to find a cleaner way of doing it.

Ok So I've managed to answer my own question, although not in the most ideal of ways:
def new_user(line)
params = Hash.new
params[:user] = Hash.new
params[:user]["email"] = line[0]
params[:user]["first_name"] = line[1]
params[:user]["last_name"] = line[2]
params[:user]["phone"] = line[3]
#generate random password of length 6
password = ActiveSupport::SecureRandom.base64(6)
#generate username by adding first and last name + 3 random characters
username = (line[1] + line[2])
username = username + ActiveSupport::SecureRandom.base64(3)
params[:user]["login"] = username
params[:user]["password"] = password
params[:user]["password_confirmation"] = password
#check to see if user already exists
#existing_user = User.find_by_email(line[0])
if(#existing_user)
#user exists
#do nothing
else
#user is brand new
#new_user = User.new(params[:user])
#new_user.reset_persistence_token
if(#new_user.save)
#new_user = User.find_by_email(line[0])
#user saved successfully
else
#a problem occurred
flash[:errors] = #new_user.errors
end
end
end

Related

Model is Invalid Because Foreign Key Does Not Exist When It's Created

I have a user table and 2 other tables that each have foreign keys to the user table's id field. WhenI create a user, I would like to initialize a record in all three tables, but I'm having trouble doing so. The user record is ultimately created, but not the records in the other two tables. After some debugging, I discovered those models were not saved because they were invalid. The error message said, User must exist. I'm trying to accomplish the initialization inside the create method:
def create
logger.info "inside sessions create"
# how do I save user first, THEN create a record associated with user in 2 tables ?
User.where(:id => auth_hash.uid).first_or_create do |user| # finds the matching record in users table
user.name = auth_hash.info.name
user.id = auth_hash.uid
user.token = auth_hash.credentials.token
user.secret = auth_hash.credentials.secret
#tweetstore = Tweetstore.new() # Record I'd like to save in Table with Foreign KEY
#tweetidstore = Tweetidstore.new() # Another Record I'd like to save in a Table with Foreign KEY
istsvalid = #tweetstore.valid? # returns false
istsidvalid = #tweetidstore.valid?
error = #tweetstore.errors.full_messages #USER MUST EXIST
#tweetstore[:user_id] = auth_hash.uid
#tweetidstore[:user_id] = auth_hash.uid
is_tweetstore_save = #tweetstore.save # false
is_tweet_idstore_save = #tweetidstore.save
end
session[:user_id] = auth_hash.uid
redirect_to '/'
end
How do I restructure my code so that User will exist by the time I initialize the other dependant tables? I tried bypassing the problem by adding the optional parameter to the models (eg belongs_to :user, optional: true) but then I get another error: QLite3::ConstraintException: FOREIGN KEY constraint failed I'm a newbie at Ruby so please ELI5
Consider using transactions when you need to create dependent models. When one of the insert fails, let everything that were inserted to DB before that get rollbacked.
Also you should be using user.id and not auth_hash.uid
ex.
#tweetstore[:user_id] = auth_hash.uid
should be
#tweetstore[:user_id] = user.id
Also
istsvalid = #tweetstore.valid? # returns false its false because it's not yet saved into database.
try this:
def create
...
#user.id = auth_hash.uid <---- do not set this
...
#tweetstore[:user_id] = user.id
#tweetidstore[:user_id] = user.id
...
i ditched the first_or_create method and just included a condition for the existence of the record. i'm not sure when user is saved in the where block i used above, so i explicitly saved it before saving records in my dependent tables.
if !User.exists?(auth_hash.uid)
#user = User.new()
#user.name = auth_hash.info.name
#user.id = auth_hash.uid
#user.token = auth_hash.credentials.token
#user.secret = auth_hash.credentials.secret
is_user_save = #user.save
#tweetstore = Tweetstore.new()
#tweetidstore = Tweetidstore.new()
#tweetstore[:user_id] = auth_hash.uid
#tweetidstore[:user_id] = auth_hash.uid
is_tweetstore_save = #tweetstore.save
is_tweet_idstore_save = #tweetidstore.save
end

Special character not allowed error on website while intregating paytm

I want to integrate paytm using ruby on rails for web only, now the problem is that when I fetched the values of attributes form database like MID, CUST_ID, WEBSITE, CALLBACK_URL, INDUSTRY_TYPE_ID and some others attributes, then one problem is occurring which is below.
Attributes:
paramList["WEBSITE"] = "WEBSTAGING"
Error:
invalid: Special character not allowed
def start_payment
unless #paytm_keys.nil?
paramList = Hash.new
paramList["MID"] = ""
paramList["ORDER_ID"] = "#{Time.now.to_i.to_s}"
paramList["CUST_ID"] = "#{Time.now.to_i.to_s}"
paramList["INDUSTRY_TYPE_ID"] = #paytm_keys.industry_type_id
paramList["CHANNEL_ID"] = #paytm_keys.channel_id
paramList["TXN_AMOUNT"] = #payable_amount
paramList["MOBILE_NO"] = #paytm_keys.mobile_number
paramList["EMAIL"] = #paytm_keys.email
paramList["WEBSITE"] = "WEBSTAGING"
paramList["CALLBACK_URL"] = #paytm_keys.paytm_url
#paramList=paramList
puts #paramList
#checksum_hash = generate_checksum()
respond_to do |format|
format.js
format.html
end
else
redirect_to new_checkout_path, alert: "Right now you don't have to pay."
end
end
It seems there are some special characters in one of the params you're passing in your hash. Have a look at the output of
puts #paramList
It might be helpful if you could post this in your question, but you probably want to obfuscate real credentials by perhaps substituting or removing all valid alphanumeric characters from your puts so you can give us the output of:
puts paramList.to_s.gsub(/\w/, '')
# this should only contain non alphanumeric characters which
# would be safe to post in your question.

Recreate devise users table from excel

I want to have my database tables in excel as a backup so I am able to reseed my database from scratch.
So far everything works OK, except the devise users model.
The code looks like this:
*users.rb*
def self.import(file)
spreadsheet = Roo::Spreadsheet.open(file.path)
header = spreadsheet.sheet(0).row(1) #sheet(0) is the first sheet
(2..spreadsheet.sheet(0).last_row).each do |i|
row = Hash[[header, spreadsheet.sheet(0).row(i)].transpose]
user = find_by(fullname: row["Fullname"]) || new
user.update_fields(row)
end
end
def update_fields(fields)
self.fullname = fields["Fullname"]
self.email = fields["Εmail"]
self.role = fields["Role"]
self.encrypted_password = fields["Enc. Password"]
self.reset_password_token = fields["Password Token"]
self.confirmed_at = fields["Confirm. Date"]
self.confirmation_sent_at = fields["Confirm. SentAt"]
self.confirmation_token = fields["Confirm. Token"]
self.save!
end
When the save is executed I get a rollback error that the Password cannot be blank. I am confused because no password seems to be kept in the database. What it seems to be saved is an encrypted password which I am importing from excel (so it is not blank).
Any ideas?

Rails - Not hitting while loop when creating classes

I have a create method in Rails where I am trying to create multiple objects in a while loop. For some reason it doesn't seem to be hitting the while loop so no objects are being created. The code is below:
def create
#user = User.find(params[:participant][:user_id])
#activity = Activity.find(params[:activity_id])
weeks = #activity.weeks
i = 1
while i <= weeks do
puts "Test"
participant = Participant.new
participant.user_id = #user.id
participant.activity_id = #activity.id
participant.attended = false
participant.paid = false
participant.week = i
participant.save
i = i+1
end
redirect_to user_activities_path(#user, :id => #activity.id)
end
The form I am using to submit is working fine as I can see from the console, and the redirect_to method at the end is working, so it just seems to be missing the loop. If it helps, the value of weeks is 10. Any help would be greatly appreciated.
If multiple Test have been output, try participant.save!, i think the participant save might fail, like some column not valid, so no objects are being created.
Please check if activity record is get fetched. I think your 3rd statement should be as follow.
#activity = Activity.find(params[:participant][:activity_id])

How to set up usernames from email of all users?

I would like to create rake task to set the username of all users' without a username to the part before the '#' in their email address. So if my email is test#email.eu, my username should become test. If it's not available, prepend it by a number (1).
So i have problem witch checking uniqness of username. Code below isn`t working after second loop ex: when i have three emails: test#smt.com, test#smt.pl, test#oo.com username for test#oo.com will be empty.
I have of course uniqness validation for username in User model.
desc "Set username of all users wihout a username"
task set_username_of_all_users: :environment do
users_without_username = User.where(:username => ["", nil])
users_without_username.each do |user|
username = user.email.split('#').first
users = User.where(:username => username)
if users.blank?
user.username = username
user.save
else
users.each_with_index do |u, index|
pre = (index + 1).to_s
u.username = username.insert(0, pre)
u.save
end
end
end
end
Other ideas are in Gist: https://gist.github.com/3067635#comments
You could use a simple while loop for checking the username:
users_without_username = User.where{ :username => nil }
users_without_username.each do |user|
email_part = user.email.split('#').first
user.username = email_part
prefix = 1
while user.invalid?
# add and increment prefix until a valid name is found
user.username = prefix.to_s + email_part
prefix += 1
end
user.save
end
However, it might be a better approach to ask the user to enter a username upon next login.
if i understand your code correct, you are changing the username of existing users in the else branch? that does not look as if it's a good idea.
you should also use a real finder to select your users that don't have a username. otherwise you will load all the users before selecting on them.
i don't know if it "matches your requirements" but you could just put a random number to the username so that you do not have the problem of duplicates.
another thing that you can use is rubys retry mechanism. just let active-record raise an error and retry with a changed username.
begin
do_something # exception raised
rescue
# handles error
retry # restart from beginning
end
In your query User.find_by_username(username), you only expect 1 record to be provided. So you don't need any each. You should add your index in another way.

Resources