Add value to column in database via the rails console - ruby-on-rails

I have a table in my database called "users". In this table, I have 4 columns: Firstname, Lastname, Age, Location (all created with the usual: rails generate migration add_firstname_to_users firstname:string).
If I have an existing user with the columns FirstName, Lastname, and Age already populated but Location is empty, how can I add a value to Location for a specific user via the rails console? Been googling all day, cant seem to find an answer.
Thanks!

Open rails console: rails console (in short rails c)
Find specific user: user = User.find 1 # Note here '1' is specific user ID
And then,
user.location = "location value"
user.save! # Force to raise errors if any validation fails
OR
user.update_attribute(:location, "location value")

Related

No error on updating deleted object in rails

Rails executing update on deleted records.
I have a web app on ruby on rails in which I created some users and after that I opened the rails console and assigned U1 to one of my user let say last user then assigned the same User to U2. Then I run U1.destroy which executes successfully
after that I updated the name of user through U2 and it returns me true Although, user was destroyed from database when I checked it. My concern is rails should give me false as there was no object in database against that ID.
If you want to double check that record exists before updating you can use reload
user.reload.update(name: "Some Name")
It will raise ActiveRecord::RecordNotFound if record with such id is absent
UPDATE changes the values of the specified columns in all rows that satisfy the condition.
https://www.postgresql.org/docs/current/sql-update.html
Rails doesn't return false or raise an exception because the UPDATE is still a valid query in the database, even if no rows match the condition. If you connect directly to your PostgreSQL database and run...
UPDATE users
SET name = 'test'
WHERE id = 123
...if 123 is an id that no longer exists, then the database will successfully execute the query and respond with:
UPDATE 0
If it is an id that still exists, the database will respond with:
UPDATE 1
This is similar to how Rails behaves if you use update_all. If you were to run update_all on a record that no longer exists, you'd see something like:
User.where(id: 123).update_all(name: 'test')
=> 0
But if the record exists you'd see:
User.where(id: 123).update_all(name: 'test')
=> 1
No error will be raised.
The purpose of the Rails update and update_all methods is just to attempt to run an UPDATE query in the database. If there is a timing issue and the record no longer exists, that's not something that the database or Rails is designed to give warnings about.

Rails Duplicate key error: How to tell Rails to continue with the ID from the database

I'm currently deploying a Ruby on Rails web application with Postgres. I'm working with Docker, just to say it.
When I deploy my application, I insert some predefined data into the database. When I want to create a new record, I get a duplicate key error.
Full error message:
ERROR: duplicate key value violates unique constraint "modelname_pkey"
DETAIL: Key (id)=(1) already exists
How can I solve this? How can I tell Rails to continue with the primary key from the last record?
You can check insert_all method from Rails 6. If you are in lower versions of Rails use activerecord-import gem.
In case of insert_all
First form the json
new_records = [{id: 1, name: 'steve'},{id: 2, name: 'george'}]
Model.insert_all(new_records)
This will insert records if its not already there and ignore if records are there.
In case of activerecord-import
new_records = [{id: 1, name: 'steve'},{id: 2, name: 'george'}]
Model.import new_records, on_duplicate_key_ignore: true
references:
activerecord-import
rails-6-insert_all
If you don't specify an ID the database will choose one for you.
person = Person.create!( name: "MacReady", thing: false )
If you need to reference a specific ID, reconsider that. Relying on special IDs is too fragile, as you're discovering. Database IDs should be considered unique identifiers with no further special meaning.
For example, instead of remembering that "user ID 1 is the admin user" add an "admin" field.
admin = User.create!( name: "Yarrow Hock", admin: true )
Now you can check if user.admin for any user, have as many admins as you want, and change whether a user is an admin at any time.
I think this can also resolve your problem. Add this in your staging or preprod console (I am using Heroku for this so I added in my heroku rails console):
connection = ActiveRecord::Base.connection
connection.execute("SELECT setval(pg_get_serial_sequence('table_name', 'id'), MAX(id)) FROM table_name;")
Check out this blog for more info and how this is been generated.

Ruby on Rails / ActiveRecord: Updating records with first_or_initialize causes RecordNotUnique

I'm currently getting user data from a SAML assertion and creating users in a local DB based on that info:
mapped_role = map_role user_role
user = User.where(email: auth_attrs.single('Email')).first_or_initialize do |u|
u.firstname = auth_attrs.single('First Name')
u.uid = auth_attrs.single('UID')
u.provider = resp.provider
u.role = mapped_role
end
This works well enough, but when the user's details change (for instance, their role changes), that data doesn't get updated in the DB. What I've tried doing is moving the role assignment out of the do block (on the user object returned by first_or_initialize) and then calling a follow-up user.save, but this results in a pretty red screen informing me that the column 'email' isn't unique. I don't want to be creating a new record here, just updating an existing one. Is there a better pattern to be using here?
Edit: I've tried the various approaches laid out here, but they result in the same SQLite3 error. It seems like I'm missing something there.
Edit2: It looks like this might be due to Devise trying to do something behind the scenes with an email field of its own(?).
I think I would go about it like so
mapped_role = map_role user_role
# find the user or initatiate an new un-persisted user
user = User.find_or_initialize_by(email: auth_attrs.single('Email'))
attributes = {firstname: auth_attrs.single('First Name'),
uid: auth_attrs.single('UID'),
provider: resp.provider,
role: mapped_role}
# attempt to update the above record with the appropriate attributes
# this will set the attributes and fire #save
if user.update(attributes)
# successful
else
# handle validation errors
end
This way there is no need for logical handling of users that are already persisted and new users.

rails can you reference a model within a model?

I seem to have run into a problem with trying to use a model in another model in Rails.
I am pulling a list of users from Active Directory with LDAP in a dropdown. I want to parse the cn that I get from Ldap into a firstname and lastname.
The problem I am running into is that I need to find a record in the users model. The parsing is being done in observations.rb.
Observation.rb:
def parse_employee
#emp_name = '' #initialize
self.employee_raw = self.employee_raw[2...-2] # get rid of the quotes and brackets
#emp_name = self.employee_raw.split(' ') # split first/last names
#emp_first_name = #emp_name[0] #Grab the first name
#emp_last_name = #emp_name[1] # grab the surname
#user = User.where("last_name like ?", #emp_last_name)
self.employee_id = #user.id
end
I've played with this quite a bit and it appears that I can't reference other models from within a model.
To sum up, what I am trying to do is
1. Have the user select the appropriate person from a dropdown that is pulled via LDAP from active directory.
2. Use the first and last names to find the appropriate user in my user table (Right now I'm just trying to get it to work with the last name as that is unique enough)
3. When I find the correct user in the user table, enter that id in the employee_id field in my observations table.

Rails migration cannot find a result and fails

My rails migration is failing because of the following line:
username = User.find(user_id)
if (!username.nil?)
...
I have a user_id of 100 which has no matching user in Users so username is returning as nil (I think) but then my entire migration crashes
I thought that the if (!username.nil?) would overcome this... is there another way to not crash upon no results in find()?
If find cannot find the record with the id you specify then it raises an ActiveRecord::NotFoundError exception.
If you want to return nil when there is no such record you can do:
username = User.where(id: user_id).first
(and note that it is a User instance and not the name of the user)

Resources