Rails have to create a "fake" column in model - ruby-on-rails

In my tabel I have:
rating_score => The current score
ratings => The number of ratings which led to the score
I want to create a "fake" column named rating which is (rating_score/ratings) in model. That I can use in my controller to order after and in my view.
How should I create this in my model?

Notice that you cannot have the SQL query order your results by a virtual attribute.
What you can do is just define the method like this in your model:
def rating
rating_scope / ratings
end
and order your resultset in ruby based on the value:
results.sort_by(&:rating)

Related

how to use sunspot/solr to order by inclusion in an associated field

I am using rails 4 with sunspot which uses solr and I am trying to order a model by the field value of an associated model.
I have a number and the number has_many favorites associated to it (multiple users can favorite the number).
Each favorite stores a user_id.
I want to order the numbers where the user_id of an associated favorite matches the current_user.id.
something like order('number.favorites.user_id', current_user.id)
I have tried to index an array of favorites.user_ids in the number searchable boolean(:favorite_user_ids) { favorites.pluck(:user_id) }
but now I'm trying to think of how to order by inclusion in that indexed array.
For example: "order where the current_user.id matches an id in the number.favorite_user_ids array.
leftJoin strategy:
I also found leftOuterJoin directly in solr https://solr.apache.org/guide/7_2/stream-decorator-reference.html#leftouterjoin
I think if I do a left outer join where I use on current_user.id = favorite.user_id then after I can order by user_id

Count total bookings by category - Rails

My BookingGroup has_many Booking. Booking contains column category where the data can be "adult" or "child_infant" or child_normal.
Now I want to count all total %child% and display it in my index view table
I was'nt sure whether this could be done in one line or I have to use a scope, this is where I stucked.
BookingGroup model
def search_by_category
bookings.visible.map(&:category).inject(:+)
end
Assuming category is a string column, you should be able to count it like that :
bookings.visible.where("category LIKE ?", "child%").count
bookings.visible.where(category: ["child_infant", "child_normal"]).count
We can use LIKE just as in SQL with active record
In your BookingGroup model
def search_by_category
bookings.visible.where('category LIKE ?', '%child%').size
end
But, if you do so for many booking_groups, your code will have N+1 queries issue. You can use eager load in your controller
#booking_groups = BookingGroup.joins(:bookings).select('booking_groups.*', 'count(*) as total_bookings').where('bookings.category LIKE ?', '%child%').group(:id)
Then you can
#booking_groups.first.total_bookings

Filter table on attribute of first result from joined table

I have two tables users and task_lists, users has_many task_lists.
task_lists belongs to users and has an attribute tasks_counter.
users
|id|
task_lists
|id|user_id|tasks_counter|
I would like to find all the users whose first (MIN(id)) tasks_list has a tasks_counter < 5.
How would I achieve this in PostGreSQL? I'm using Rails, if somebody knows a solution using ActiveRecords.
This will set users_ids variable with an Array containing all User id's whose first TaskList has a tasks_counter < 5:
user_ids = TaskList.select("MIN(id) AS id, user_id, tasks_counter")
.group(:user_id) # Get first TaskList for each user
.select { |t| t.tasks_counter < 5 } # Keep users tha meet criteria
.pluck(:user_id) # Return users' id in array
If you would like to get an ActiveRecord_Relation object with User objects you can use the result from the previous query and filter User.
users = User.where(id: user_ids)
Or, everything in one line:
users = User.where(id: TaskList.select("MIN(id) AS id, user_id, tasks_counter")
.group(:user_id)
.select { |t| t.tasks_counter < 5 }
.pluck(:user_id))

Rails - create by date from 2 different models

Let's say I have a table for a model Score, and a table for a model Multiplier. Both of these models have attributes date and value. I want to now create a new object of a different model Total, that corresponds to the date for Score and Multiplier. Here's the idea, though I don't think it's a good solution:
def create
#scores = Score.all
#scores.each do |score|
Total.create(:date => score.date, :value => score.value + Multiplier.find_by_date(score.date).value)
end
end
Essentially, how can I add the values of two fields from separate models to create a third object of a different model, in an elegant way? Thanks in advance!

finding records where belongs_to table's column is not equal

I have a Trainer model that has a has_many relationship with Pokemon. How do I find all Trainers who do not have any Pokemon of a certain type or group of types(type is a column in Pokemon model)?
The code I have tried, but it returns a trainer if any of his Pokemon's types is not in the group (e.g. if a trainer has pokemon of type fire and electric, he will be returned because electric isn't in the array. I don't want him returned because he has a fire pokemon.)
Trainer.joins(:pokemons).where("pokemons.type NOT IN (?)", ["fire","grass","water"])
The same problem occurs when I'm just comparing to one type.
Trainer.joins(:pokemons).where("pokemons.type != ?", "fire")
Again, the example trainer will get returned because he has a pokemon with a type, electric, that is not equal to fire.
I am using Rails 3.2.13 and Ruby 1.9.3.
I don't think there is a way to write this with Rails in one query, but you can do the following:
Trainer.where('trainers.id NOT IN (?)', Pokemon.where(type: ['grass', 'fire', 'water']).pluck(:trainer_id).uniq )
Explained version:
# selects the IDs of Trainer having a Pokemon of type Grass||Fire||Water
trainer_ids = Pokemon.where(type: ['grass', 'fire', 'water']).pluck(:trainer_id)
# returns the trainers
Trainer.where('trainers.id NOT IN (?)', trainer_ids)
In Rails 4, you can do:
Trainer.where.not(id: Pokemons.select(:trainer_id).where("pokemons.type IN (?)", ["fire","grass","water"])
This will grab all the trainers where their id does not show up in the list of trainer_ids on pokemons with fire, grass, or water.
An alternative is doing the query on the SQL layer through ActiveRecord's find_by_sql:
Trainer.find_by_sql [
"SELECT * FROM trainers
WHERE id NOT IN
(SELECT DISTINCT(trainers.id) FROM
trainers JOIN pokemons
ON trainers.id = pokemons.trainer_id
WHERE pokemons.type IN ('grass', 'fire','water'))"
]

Resources