I have a simple model for students but I want to also have unique student code for each student, I know I can use the student_id but I would like student code to be something like 'STU0001', 'STU0002. How can I implement something like this so that whenever I create a student, it will create the student code and add it to the DB? Also how can I search students by their ids in this case?
Asked
Active
Viewed 365 times
0
-
Do `students` and `staff` share the same model? If yes, create a model function that prefixes `STU000` to the unique id and voila – benjessop Aug 15 '20 at 16:16
-
I assume you're wanting to do a custom primary key? Or do you want the student id to be another attribute? Why do you need `STU` as a prefix? If it's just for how it's viewed, you could use the default `id` and just prepend `STU` whenever interacting in the view. If you really want a custom primary key in the database in Rails, you can look up how to do that online. For example, [Using Rails: how can I set my primary key to not be an integer typed column?](https://stackoverflow.com/questions/1200568/using-rails-how-can-i-set-my-primary-key-to-not-be-an-integer-typed-column) – lurker Aug 15 '20 at 16:17
-
How is the student code going to be used? Depending on the use, this sounds like it might be a uniquely bad idea. Or, it might be brilliant. Hard to tell without some additional context. – jvillian Aug 15 '20 at 16:24
2 Answers
4
You can do it using before-create hook in your model, something like follow -
class Student < ActiveRecord::Base
# Callbacks
before_create :set_student_id
def set_student_id
self.student_id = "STU" + "%04d" % self.id
end
end
output -
$> student = Student.create()
$> puts student.student_id
$> STU0001

fidato
- 719
- 5
- 22
2
IMHO if you want id to be prefixed as STU
just for a nice display purpose then I would suggest not to store that way in database.
Let current implementation of auto incrementing id
be untouched.
Just while displaying you can prepend it with STU
.
For handy use you can create method to wrap this logic as
def formatted_id # OR friendly_id or whatever you like
"STU#{'%04d' % self.id}"
end
Reasons for not storing prefixed id:
- You will have to write a setter
- Your column data type will change to string
- Your performance will go down as compared to integer column
- In future if you decide to change the prefix, then you will have to update existing ids. With my solution you can change all (existing and future) ids formatting anytime by just changing formatting in the method.
Searching depends on exactly what is your usecase. If you can explain that then I can guide you better. To search students you can write a handy method like below in model (i assume it will be Student or User)
def self.find_by_formatted_id(formatted_id)
self.find(formatted_id.gsub(/^STU/, ''))
end
def self.find_by_formatted_ids(formatted_ids) # formatted_ids will be an array
self.where(id: formatted_ids.map{ |fid| fid.gsub(/^STU/, '') })
end

Anand Bait
- 331
- 1
- 12
-
Thanks for this, but how can I search for students via their student id? – Mozart Len Aug 15 '20 at 22:24
-
1to search for student by student id you have to make a small method to extract the id from the student id. I agree with Anand, it's not a good idea to store student_id in the database. Besides the reasons he gives, it's not "normalized" to have one field entirely dependent on the other. – Les Nightingill Aug 15 '20 at 23:28
-
@MozartLen I have updated answer with search related snippet. If you could brief about what exactly is your usecase then I can help you better. – Anand Bait Aug 17 '20 at 01:25
-
Thank you for this solution, I want to assign a student_id to students when they are created. I have a "lend" model which will be filled whenever a student lends a book, in the model I have student_id:references. I wish to reference a student with his student_id when creating a lend record. – Mozart Len Aug 17 '20 at 22:11