Exclude Rails ActiveRecord from query - ruby-on-rails

I'm developing an marketplace app where sellers can list items to sell. On the listing show page, I developed a widget called "other items from this seller". I use the below query to pull these items into the view.
Listing.where(:user_id => #listing.user)
This works but it includes the activerecord. Since this is a widget for "other items" I want to exclude the listing whose page the user is currently on. Note that the "user_id" field in the listing model is the sellers user id.
How would I modify this? I tried the below but it gives me an error saying it expects an "=>".
Listing.where(:user_id => #listing.user, :id != #listing.id)

How about simply using array parameter to where:
#listing.user.listings.where(["id != ?", #listing])
OR (better performance)
Listing.where(["user_id = ? AND id != ?", #listing.user_id, #listing.id])

For completeness, if you are using rails 4.x you could use .where.not
Listing.where(user_id: #listing.user_id).where.not(id: #listing.id)

In addition to RAJ's answer, you can chain the two clauses to make one query
Listing.where(:user_id => #listing.user).where("id != ?", #listing.id)

Related

Get Unique records per attribute in Active Record

I have Student model and I would like to get one record per term_id (one of the attributes).
Student.select(:term_id).distinct
works but the result is an array of term_ids, not the objects themselves - which is what I would like to get
Try this:
Student.pluck("DISTINCT id, term_id")
Student.select("DISTINCT term_id, `students`.* ")
Incase if you are using older versions of ruby (< 2.3.8),
Student.find(:all, :select => "DISTINCT(term_id), `students`.*")
or if you want id alone,
Student.find(:all, :select => "DISTINCT(term_id), id")
where students is your table name. You will get array of objects.

Postgres ORDER BY values in IN list using Rails Active Record

I receive a list of UserIds(about 1000 at a time) sorted by 'Income'. I have User records in "my system's database" but the 'Income' column is not there. I want to retrieve the Users from "my system's database"
in the Sorted Order as received in the list. I tried doing the following using Active Record expecting that the records would be retrieved in the same order as in the Sorted List but it does not work.
//PSEUDO CODE
User.all(:conditions => {:id => [SORTED LIST]})
I found an answer to a similar question at the link below, but am not sure how to implement the suggested solution using Active Record.
ORDER BY the IN value list
Is there any other way to do it?
Please guide.
Shardul.
Your linked to answer provides exactly what you need, you just need to code it in Ruby in a flexible manner.
Something like this:
class User
def self.find_as_sorted(ids)
values = []
ids.each_with_index do |id, index|
values << "(#{id}, #{index + 1})"
end
relation = self.joins("JOIN (VALUES #{values.join(",")}) as x (id, ordering) ON #{table_name}.id = x.id")
relation = relation.order('x.ordering')
relation
end
end
In fact you could easily put that in a module and mixin it into any ActiveRecord classes that need it, since it uses table_name and self its not implemented with any specific class names.
MySQL users can do this via the FIELD function but Postgres lacks it. However this questions has work arounds: Simulating MySQL's ORDER BY FIELD() in Postgresql

How to implement mongoid rails simple search

With rails 3.2, mongoid
I don't want full-text search, I just wanna search one field of the model.
E.g
I have a "People" scaffold with just a name field.
And I want to have a search form. For instance, I search "peter", if there's an exact match(case insensitive) of the search term - "peter" in the database, then I want it immediately redirect to peter show page without listing further search results.
However, if there's no exact match, then suggested results(in the database) will be shown.
Please kindly advise.
You need test if the exact match exist in first case and use after a regexp to have some possibilities of result
user = User.where(:name => params[:name])
if user
redirect_to user_url(user)
return
else
#users = User.where(:name => /params[:name]/i)
end

rails 3 group by and sum

I have the following model:
activity_types: id, name
activities: id, id_activity_type, occurrences, date (other fields)
The activities table store how many times an activity occurs by day. But now I want to show to the user how many activities from each type occurred by month.
I got the following solution based on this post which seems ok:
Activity.all(:joins => :activity_types,
:select => "activity_types.id, activity_types.name, SUM(activities.occurrences) as occurrences",
:group => "activity_types.id, activity_types.name",
:order => "activity_types.id")
but this seems a lot of code for the rails standards and rails API says it's deprecated.
I found the following solution which is a lot simple:
Activity.sum(:occurrences).group(:activity_type_id)
Which returns an hash with activity_type_id => occurrences.
What shall I do to get the following hash: activity_type.name => occurrences ?
If the original query worked, then just try rewriting it with Rails 3 syntax:
Activity.joins(:activity_types)
.select("activity_types.id, activity_types.name, SUM(activities.occurrences) as occurrences")
.group("activity_types.id, activity_types.name")
.order("activity_types.id")
Activity.joins(:activity_types).group('activity_types.name').sum(:occurrences)
SELECT SUM(activities.occurrences) AS sum_occurrences, activity_types.name AS activity_types_name FROM activity_types INNER JOIN activity_types ON activity_types.id = activities.activity_types_id GROUP BY activity_types.name
in case you needed an ordered hash based on activity_types.id and assuming activity_types_id is not needed as a part of hash key.
Activity.joins(:activity_types).group('activity_types.name').order(:activity_types_id).sum(:occurrences)
incase [activity_type_id, activity_types.name] needed as a part of key
Activity.joins(:activity_types).group(:activity_types_id, 'activity_types.name').order(:activity_types_id).sum(:occurrences)

How do I find() all records unique in certain fields?

I have a list of 'request' objects, each of which has fairly normal activerecord qualities. The requests table is related to the games table with a join table, 'games_requests,' so that a request has a request.games array.
The question is, is there a way to do a find for the last n unique requests, where uniqueness is defined by the games column and a couple others, but specifically ignores other colums (like the name of the requesting user?)
I saw a syntax like 'find (:all, :limit=>5, :include=>[:games,:stage])' but that was returning duplicates.
Thanks...
EDIT: Thanks to chaos for a great response. You got me really close, but I still need the returns to be valid request objects: the first 5 records that are distinct in the requested rows. I could just use the find as you constructed it and then do a second find for the first row in the table that matches each of the sets returned by the first find.
EDIT:
Games.find(
:all, :limit => 5,
:include => [:games, :requests],
:group => 'games, whatever, whatever_else'
)
...gives an SQL error:
Mysql::Error: Unknown column 'games' in 'group statement': SELECT * FROM `games` GROUP BY games
I made a few changes for what I assumed to be correct for my project; getting a list of requests instead of games, etc:
Request.find(
:all, :order=>"id DESC", :limit=>5,
:include=>[:games], #including requests here generates an sql error
:group=>'games, etc' #mysql error: games isn't an attribute of requests
:conditions=>'etc'
)
I'm thinking I'm going to have to use the :join=> option here.
Games.find(
:all, :limit => 5,
:include => [:games, :requests],
:group => 'games, whatever, whatever_else'
)
Try Rails uniq_by.It also works with association and returns array.
#document = Model.uniq_by(&:field)
More Detail
I think you'll be able to do this using find_by_sql and GROUP BY:
Games.find_by_sql("SELECT * FROM games GROUP BY user_id")

Resources