Post.order method does not work with Sequel and Sinatra - ruby

I am trying to order my posts based on the created date ( newest to oldest ) so i do this :
#posts = Post.order('created_at DESC')
But the posts are not being affected by this. What can the problem be ?

Try something like this
#posts = Post.order(:created_at)
This way you order your data according to the created_at property
and if you want reversed order then
#posts = Post.order(:created_at).reverse

Related

How to order by latest nested model created_at in a query

I've got a question, I don't know if this is possible but suppose these models
class Event < ApplicationRecord
has_many :gifs
end
class Gif < ApplicationRecord
belongs_to :event
end
blank database using rails console you do this
gif_1 = Gif.create
gif_2 = Gif.create
gif_3 = Gif.create
event_1 = Event.new
event_1.gifs = [gif_1, gif_3]
event_1.save
event_2 = Event.new
event_2.gifs = [gif_2]
event_2.save
How would you order events by their last gifs created's created_at attribute.
Here is an example of what I've tried but that doesn't produce the correct result
ordered_events = Event.includes(:gifs).joins(:gifs).order("gifs.created_at DESC")
ordered_events.first.id
=> 2 # I want this to return 1
Now I understand why my attempt probably didn't work. I think it's because it probably only looked at the first Gif to do the ordering.
On top of this I had another thought, and here I have no idea where to begin trying to do this in a query, but what if the Event has 0 Gif, from what I wrote it seems no gifs simply relegates those events to after the ones who do have gifs but this would not work for me.
here's another context in rails console which is more realistic since normally you'd need an event first to store the Gif
event_1 = Event.create
event_2 = Event.create
gif_1 = Gif.create(event_id: event_1.id)
gif_2 = Gif.create(event_id: event_2.id)
event_1 = Event.create
gif_3 = Gif.create(event_id: event_1.id)
Now here what I would like to get back from my query would be something of the sorts of [event_1, event_3, event_2] because since event_3 has no gifs I want to use his created_at to order.
I know how I could do this by hand via some helper function or other but I would really love to be able to this kind of thing in one query directly.
As an example:
Event.joins(:gifs)
.group('events.id')
.order('MAX(gifs.created_at) DESC')
This query takes events, joins them with gifs, groups by event.id (to eliminate event duplicates in case one event has several gifs) and sorts result by latest (maximal) created_at time of event's gifs, in descending order.
Since it uses joins method, which unwraps to INNER JOIN in SQL query, events without gifs won't be returned by this query. To fix it use left_outer_joins:
Event.left_outer_joins(:gifs)
.group('events.id')
.order('MAX(gifs.created_at) DESC')

Rails combine multiple activerecord relations

I want to union multiple active record relation
For example,
apple_companies = Company.where("name like ?","%apple%")
banana_companies = Company.where("name like ?","%banana%")
I want to combine these two relation.
not merge, merge is
apple_companies.merge(banana_companies)
=> Company.where("name like ? and name like ?", "%apple%","%banana%")
I want to
Company.where("name like ? or name like ?", "%apple%","%banana%")
afterward,
I will code
companies = Company.none
company_name_list.each do |name|
like = "%"+name+"%"
companies += Company.where("name like ?",like)
end
but code which I wrote make companies to array.....
So I cannot order and page to companies... :(
thank you
apple_companies = Company.where("name like ?","%apple%")
banana_companies = Company.where("name like ?","%banana%")
apples = apple_companies.where_values.reduce(:and)
bananas = banana_companies.where_values.reduce(:and)
Company.where(apples.or(bananas))
See ActiveRecord Arel OR condition for more examples.
The best result for this that I've come across is to grab and merge the ids of the two queries and then search for them like this:
apple_companies = Company.where("name like ?","%apple%").pluck(:id)
banana_companies = Company.where("name like ?","%banana%").pluck(:id)
ids = apple_companies + banana_companies.uniq
Company.where(id: ids)
It's four lines that seems like it should be doable in one but it works.
In this case you can use any of the other answers. However in more general cases, I strongly recommend using any_of gem. With this gem you can do:
apple_companies = Company.where("name like ?","%apple%")
banana_companies = Company.where("name like ?","%banana%")
Company.where.any_of(apple_companies, banana_companies)
There already is a pull request to add this functionality to future rails releases.
Please try using
Company.where('name LIKE ? OR name LIKE ?','%apple%', '%banana%')
OR
Company.where('name IN (?)', ['%apple%', '%banana%'])
According to your code:
names = []
company_name_list.each do |name|
names << "%"+name+"%"
end
Then you can do:
companies = Company.where('name LIKE ANY(Array[?])', names)
Late answer, but Arel will solve it.
Company.where(Company.arel_table[:name].matches_any(["%apple%", "%banana%"]))
Use
Company.where(name: IN ('%apple%','%banana%'))

Rails 3 Query: How to get most viewed products/articles/whatever?

I always wondered how to query and get results that doesn't fit in a model. Similar how it's done using LINQ and projecting into anonymous objects.
So here's the simple schema:
# Product.rb
class Product < ActiveRecord::Base
has_many :product_views
# attributes: id, name, description, created_at, updated_at
end
# ProductView.rb
class ProductView < ActiveRecord::Base
belongs_to :product
# attributes: id, product_id, request_ip, created_at, updated_at
end
Basically I need to get a list of Products (preferably just id and name) along with the count of views it had. Obviously ordered by view count desc.
This is the SQL I want to get:
select
p.id,
p.name,
count(pv.product_id) as views
from
product_views pv
inner join
products p on pv.product_id = p.id
group by
pv.product_id
order by
count(product_id) desc
I tried the following and similar, but I'm getting ProductView objects, and I would like to get just an array or whatever.
ProductView.includes(:product)
.group('product_id')
.select("products.id, products.name, count(product_id)")
This kind of thing are trivial using plain SQL or LINQ, but I find myself stucked with this kind of queries in Rails. Maybe I'm not thinking in the famous 'rails way', maybe I'm missing something obvious.
So how do you do this kind of queries in Rails 3, and specifically this one? Any suggestions to improve the way I'm doing this are welcome.
Thank you
You can use Arel to do what you're looking for:
products = Product.arel_table
product_views = ProductView.arel_table
# expanded for readability:
sql = products.join(product_views)
.on(product_views[:product_id].eq(product[:id]))
.group(product_views[:product_id])
.order('views DESC')
.project(products[:id],
products[:name],
product_views[:id].count.as('views'))
products_with_views = Product.connection.select_all(sql.to_sql) # or select_rows to just get the values
Yes, it is long, but Arel is a very smart way to deal with creating complex queries that can be reused regardless of the database type.
Within a class method in the Product class:
Product.includes(:product_views).all.map { |p| [p.id, p.name, p.product_views.size] }
Then sort it however you want.
I don't know if there's a way to do it using your models. I would probably resort to:
Product.connection.select_rows(sql)
Which will give you an array of arrays. You can use select_all if you'd rather have an array of hashes.
Try this:
#product = Product.find(#product_id)
#product_views = #product.product_views.count
(Source - http://ar.rubyonrails.org/classes/ActiveRecord/Calculations/ClassMethods.html#M000292)
Hope this helps!

Query a date range with DMZ DataMapper and CodeIgniter

I cannot find the solution in the docs for this simple problem.
I want to fetched a set of objects from the database in a specific date range.
I'm using DMZ Datamapper in the CodeIgniter environment.
$items = new Entity();
$items->where('date_created', 'date1 < x < date2');
$items->get();
Maybe one needs to use the $items->where_in_func(...) method?
Answer is simple:
$items->where('date_created >', '2011-02-26 14:00:13');
$items->where('date_created <', '2011-02-26 16:00:13');

ActiveRecord: Find through multiple instances

Say I have the following in my controller:
#category1
#category2
and I want to find all stores associated with those two categories...
#stores = #category1.stores + #category2.stores
this does work, but unfortunately returns an unaltered Array, rather than a AR::Base Array, and as such, I can't do things like pagination, scope, etc...
It seems to me like there's a built-in way of finding through multiple instance association... isn't there?
##stores = #category1.stores + #category2.stores
#if you want to call API methods you can just add conditions with the category id
#stores = Store.find(:all, :conditions => ['category_id=?', a || b])
With ActiveRecord, whenever you're finding a set of unique model objects, calling find on that model is usually your best bet.
Then all you need to do is constrain the join table with the categories you care about.
#stores = Store.all(:joins => :categories,
:conditions => ['category_stores.category_id in (?)', [#category1.id, #category2.id]])

Resources