I'm trying to sort my users in my controller, and I wanted to sort them by id number. My question is, does rails automatically assign orders an id when they are created, or do I need to add that to the create function in my create action in my controller? For example, can I say this:
def index
#users = User.all.order(:WHAT TO PUT HERE???????)
end
Would I put :id in the space? If I did so, would I need to define id somewhere else or is this something ruby does on the back end?
In most cases Rails would return you records sorted by id. But you should not rely on Rails as sorting is database-specific.
To explicitly add sorting by id you should use:
def index
#users = User.order(:id)
end
Id is automatically added, you don't need to declare it anywhere.
Rails only helps you create the table via migrations. When a migration creates a table it automatically adds the id column as a primary key set to auto increment. So why you create records it's actually the database that adds the id, or as aforementioned, it auto increments it +1 from the last id. Therefore, when you use ActiveRecord to create a record you don't need to specify an id.
Now for your main question: you can pass the name of the column to the order method when you want to sort ascending by that column. You don't need to call all though.
So just do this:
User.order(:id)
That will sort from lower ids to higher. To do the opposite:
User.order("id DESC")
This will give your the most recently created records first by sorting from higher ids to lower.
If you want to sort User by ID
#users = User.order(:id) #ASC default
#users = User.order('id ASC') #ASC explicit
#users = User.order('id DESC') #DESC explicit
...and never forget the User.order('-id') unary minus shortcut...
Related
I'm grabbing a list of users and storing in #users.
Now I need to find properties related to only this list of users I have queried.
if params[:company].present?
#users = User.where(parent_id: params[:company]).or(User.where(id: params[:company]))
##properties = #properties.where(user_id: params[:company])
end
I would basically like to include #users inside #properties.where()
I need to get each property that has a user_id present in my #users array
edit:
I just did the following which gives me the result, however, I'm sure there's a much better way of doing this via activerecord:
ids = []
#users.each do |user|
ids.push(user.id)
end
#properties = #properties.where(user_id: ids)
#properties.where(user_id: #users.ids)
That should work. It'll take the id of user ids and perform a filter using the IN clause.
Perhaps adding your models and their relationships we can think about something better.
So I'm trying to organize one of my views so that the articles of my website are listed by the name of the title. For example some of my articles are named "article pt.1, history pt.2, society pt.1, etc". I do have them sorted correctly using this line of code in the Articles controller
def index
#articles = Article.order(:user_id)
end
It does work using the user id, but if I wanted to add another category and have them in alphabetical order, I would need to update the user id of each article which is not practical as they number a little over 200 in the database. What I would like to is somehow take a partial of the article title and sort each one like I am with the user_id field. This way I can sort each one using the string partial such as "article" from "article pt.1"
Thank you for reading and have a wonderful day!
Why not just sort by the title? Assuming you have a column in your articles table called title:
For alphabetical order
def index
#articles = Article.order(:title)
end
For reverse alphabetical order
def index
#articles = Article.order(title: :desc)
end
If you really want to just sort by a substring of the title. You'll have to add a new column to the articles table (called slug in this example):
rails g migration AddSlugToArticles slug:text
rails db:migrate
Then you'll have to update the slug field of every record
Article.all.each do |article|
new_slug = #your code to generate substring here
article.update(slug: my_string
end
then order by slug:
def index
#articles = Article.order(:slug)
end
First of all, it is not very clear about the output that you want, but based on assumption and the description mentioned in the post, it seems like you want to sort the string field not based on whole value but based on substring.
It is better to use the order to get the strings alphabetically sorted.
#articles = Article.order(:title)
And it will also serve the purpose as it will first match the first alphabet of each string and also handle null values at the same time.
Why write a custom logic if the purpose is fulfilled by an already defined method.
I was able to do it using the sort function instead of order using the :title field on the articles controller.
def index
#articles = Article.sort(:title)
end
I have a User model with a name attribute. In my PagesController, I want to set an instance variable equal to all of the User objects, but I want to order them based on last name. I know I can do:
#sortedusers = User.order(:name => :asc)
to order the users based on their name attribute, but how do I do it based on last name? (i.e. how do I order the Users based on the last word of their name attributes?
Thanks.
Define a virtual attribute last name in your model
def last_name
name.split(' ').last
end
and then
User.order(:last_name => :asc)
I'd suggest storing the users' last name separately. Barring that, you can use sort_by, like so:
items.sort_by! { |a| a.split(' ') } or something along those lines. Note, this most likely cannot be used straight, it's merely intended to point you in the right direction, as most of my answers are.
Upon the creation of a department, users have the option to add the name of a school. On the show page of the school, I want to show all the departments with the school of that name.
My school controller's show action looks like this:
def show
#department = Department.where(:school == 'university of connecticut')
end
This obviously isn't working. What is the correct syntax for this?
Either if these should give you the expected results:
#department = Department.where(school: 'university of connecticut').first
or
#department = Department.where('school = ?', 'university of connecticut').first
where takes either a hash or a SQL statement. Note that in the first example, we're using the shortcut hash method when using a symbol symbol: value, which is equivalent to :symbol => value
Also, keep in mind that where returns an ActiveRecord::Relation object, not an ActiveRecord object. You'll need to add .first or another form of .find if you wish to receive an ActiveRecord object directly.
You're close:
Department.where(school: 'university of connecticut').first
i.e. normal hash syntax.
Below is a relationship between Comments and a user. Each comment has one user so I'm building out a join in the code below.
I was wondering how to build this code to only include specific columns in the join. I don't need all of the user information. Just the first_name. Any suggestions.
Current Code:
#comments = Comment.where(:study_id => #study.id).joins(:user)
You could use something like this:
#comments = Comment.joins(:user)
.select("comments.*, users.first_name")
.where(study_id: #study.id)
Extending Aldo's answer to show a way to retrieve the resulting foreign column value.
#comments = \
Comment\
.joins(:user)
.select("comments.*, users.first_name as users_first_name")
.where(study_id: #study.id)
# Now it's stored on each comment as an attribute, e.g.:
puts #comments.first.read_attribute(:users_first_name)
puts #comments.first.attributes['users_first_name']
# Note that inspecting the comment won't show the foreign data
puts #comments.first.inspect # you won't see user's first name output
You could also declare users_first_name as an attrib on the comment with attr_accessible. I don't think there's any magic way to automatically set it, but you could easily do so yourself in a post-select loop.