In my app i use rails 4.
And i need to fetch as i do now data, but all except one params[:id], now i have such code:
#vip_cars = Car.order(created_at: :desc, is_vip: :desc).limit(100).sample(4)
and i try something like:
#vip_cars = Car.order(created_at: :desc, is_vip: :desc).not(id: params[:id]).limit(100).sample(4)
but it didn't work. What i do wrong? how to fetch data with order, limit, sample and not in rails 4?
You should write as
Car.order(created_at: :desc, is_vip: :desc)
.where.not(id: params[:id])
.limit(100).sample(4)
Read #not
Returns a new relation expressing WHERE + NOT condition according to the conditions in the arguments.
Remember #not always work in conjunction with #where.
Related
I am new to Ruby on Rails and am having trouble with a simple where with a model.
When I try to do Test #1 the results are out of order. New items get pushed to the bottom no matter what.
def index
#user = User.where(:status => false).order(last_name: :desc).all
end
If I enter this into rails console it doesn't work also but if I remove the all it works perfectly in rails console but doesn't work in the UsersController.
What is the proper way to do a where clause with an order? Thanks for your help!
UPDATE:
I have updated the code to the following but the results are still out of order:
def index
#user = User.where(status: false).order('last_name DESC')
end
You should use order('last_name DESC') instead of order(last_name: :desc).
order(last_name: :desc) will produce sql like (That's why your order doesn't work):
ORDER BY '---\\n:last_name: :desc\\n'
order('last_name DESC') will produce sql right:
ORDER BY last_name DESC
Rails 4
def index
#user = User.where(status: false).order('last_name DESC')
end
I am trying to do a simple or statement in a controller
This generates one set of trips that I am interested in displaying and is working fine.
#trips = Trip.where(:userid => #friends)
However, i would like to add another set of trips; trips whose userid == current_user.id
#trips = Trip.where(:userid => current_user.id)
Trying to combine these two i tried...
#trips = Trip.where(:conditions => ['userid= ? OR userid=?', #friends, current_user.id])
Any idea where the bust is? Thanks in advance.
Simply pass an array to get the equivalent of the SQL WHERE ... IN clause.
Trip.where(userid: [#friends, current_user.id])
See the ActiveRecord Rails Guide, 2.3.3 Subset Conditions
Is #friends an array? ActiveRecord will convert your where statement into a SQL IN clause when you generate it with the hash syntax. When you build your OR statement in raw SQL, you need to do the IN manually.
#trips = Trip.where('userid IN ? OR userid = ?', #friends, current_user.id)
Also, your column is called userid ? Typicaly it would be called user_id - is this a typo or do you just have an abnormal database?
I have a model:
class Event < ActiveRecord::Base
default_scope :order => 'date_begin'
end
There is a sort link in a view file:
= sort_link #search, :date_begin
When I'm trying to order date_begin as DESC nothing happens because the SQL query is:
SELECT * FROM events ORDER BY date_begin, date_begin DESC
How to make MetaSearch reorder this column? (I know that there is a "reorder" method in ActiveRecord but I don't know how to apply it to MetaSearch)
You can use unscoped method when you decided to use meta_search:
#search = Event.unscoped.search(params[:search])
I also wanted to use a default sort order, and didn't figure out any other way than to enforce a default order in the controller, not using any ordering scope in the model:
search = {"meta_sort" => "created_at.desc"}.merge(params[:search] || {})
#search = Photo.search(search)
The default sort order is created_at DESC, but it will be overwritten if a new sort order is received in the params. Seems to work for me.
#search = if params[:q] && params[:q][:s]
# Ransack sorting is applied - cancel default sorting
Event.reorder(nil).search(params[:q])
else
# Use default sorting
Event.search(params[:q])
end
Benefits:
1) only cancels :order scope - useful if you have .where(:deleted_at => nil).order(:date_begin) default scope.
2) uses default ordering when Ransack sorting is not applied.
How do I select a single random record for each user, but order the Array by the latest record pr. user.
If Foo uploads a new painting, I would like to select a single random record from foo. This way a user that uploads 10 paintings won't monopolize all the space on the front page, but still get a slot on the top of the page.
This is how I did it with Rails 2.x running on MySQL.
#paintings = Painting.all.reverse
first_paintings = []
#paintings.group_by(&:user_id).each do |user_id, paintings|
first_paintings << paintings[rand(paintings.size-1)]
end
#paintings = (first_paintings + (Painting.all - first_paintings).reverse).paginate(:per_page => 9, :page => params[:page])
The example above generates a lot of SQL query's and is properly badly optimized. How would you pull this off with Rails 3.1 running on PostgreSQL? I have 7000 records..
#paintings = Painting.all.reverse = #paintings = Painting.order("id desc")
If you really want to reverse the order of the the paintings result set I would set up a scope then just use that
Something like
class Painting < ActiveRecord::Base
scope :reversed, order("id desc")
end
Then you can use Painting.reversed anywhere you need it
You have definitely set up a belongs_to association in your Painting model, so I would do:
# painting.rb
default_scope order('id DESC')
# paintings_controller.rb
first_paintings = User.includes(:paintings).collect do |user|
user.paintings.sample
end
#paintings = (first_paintings + Painting.where('id NOT IN (?)', first_paintings)).paginate(:per_page => 9, :page => params[:page])
I think this solution results in the fewest SQL queries, and is very readable. Not tested, but I hope you got the idea.
You could use the dynamic finders:
Painting.order("id desc").find_by_user_id!(user.id)
This is assuming your Paintings table contains a user_id column or some other way to associate users to paintings which it appears you have covered since you're calling user_id in your initial code. This isn't random but using find_all_by_user_id would allow you to call .reverse on the array if you still wanted and find a random painting.
I want to grab the most recent entry from a table. If I was just using sql, you could do
Select top 1 * from table ORDER BY EntryDate DESC
I'd like to know if there is a good active record way of doing this.
I could do something like:
table.find(:order => 'EntryDate DESC').first
But it seems like that would grab the entire result set, and then use ruby to select the first result. I'd like ActiveRecord to create sql that only brings across one result.
You need something like:
Model.first(:order => 'EntryDate DESC')
which is shorthand for
Model.find(:first, :order => 'EntryDate DESC')
Take a look at the documentation for first and find for details.
The Rails documentation seems to be pretty subjective in this instance. Note that .first is the same as find(:first, blah...)
From:http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002263
"Find first - This will return the first record matched by the options used. These options can either be specific conditions or merely an order. If no record can be matched, nil is returned. Use Model.find(:first, *args) or its shortcut Model.first(*args)."
Digging into the ActiveRecord code, at line 1533 of base.rb (as of 9/5/2009), we find:
def find_initial(options)
options.update(:limit => 1)
find_every(options).first
end
This calls find_every which has the following definition:
def find_every(options)
include_associations = merge_includes(scope(:find, :include), options[:include])
if include_associations.any? && references_eager_loaded_tables?(options)
records = find_with_associations(options)
else
records = find_by_sql(construct_finder_sql(options))
if include_associations.any?
preload_associations(records, include_associations)
end
end
records.each { |record| record.readonly! } if options[:readonly]
records
end
Since it's doing a records.each, I'm not sure if the :limit is just limiting how many records it's returning after the query is run, but it sure looks that way (without digging any further on my own). Seems you should probably just use raw SQL if you're worried about the performance hit on this.
Could just use find_by_sql http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002267
table.find_by_sql "Select top 1 * from table ORDER BY EntryDate DESC"