How to organize default order in pagination? - ajax

I use will_paginate with ajax sort and seen railscasts.com.
http://railscasts.com/episodes/240-search-sort-paginate-with-ajax
My collection for pagination
#cars = Car.joins(:engine).includes(:engine).select('cars.*, engines.*').order(sort_column + " " + sort_direction).paginate(:page => params[:page], :per_page => 5)
But when I went to the index page, I jumped out error.
ActiveRecord::StatementInvalid in Items#index
SQLite3::SQLException: ambiguous column name: name: SELECT "cars"."id" AS t0_r0, "cars"."name" AS t0_r1, "cars"."model_id" AS t0_r2, "cars"."city_id" AS t0_r3, "cars"."created_at" AS t0_r4, "cars"."updated_at" AS t0_r5, "cars"."engine_id" AS t0_r6, "engines"."id" AS t1_r0, "engines"."name" AS t1_r1, "engines"."created_at" AS t1_r2, "engines"."updated_at" AS t1_r3 FROM "cars" INNER JOIN "engines" ON "engines"."id" = "cars"."engine_id" ORDER BY name asc LIMIT 5 OFFSET 0
But when I go to a page already sorted, it works for me.
I think mistake in default Order in SQL.
How to set 'cars.name' instead 'name'?

I found method and set sort default
private
def sort_column
Car.column_names.include?(params[:sort]) ? params[:sort] : "cars.name"
end

Related

order records based on a field value on the order of an array of ids in rails

As part of sorting based on priority_id column label names, I have done the below code:
products = Product.where(id: pr_ids).order("priority_id IN(?)",ordered_priority_ids)
The below error is showing:
ActiveRecord::StatementInvalid (PG::SyntaxError: ERROR: syntax error at or near ")"
LINE 1: ...ducts"."id" IN ($2, $3) ORDER BY priority_id IN(?), 4, 2, 3...
^
):
Please help.
Thanks
def self.order_by_priority_ids(ids)
return self.where(:id => 0) if ids.blank?
values = []
ids.each_with_index do |priority_id, index|
values << "(#{priority_id}, #{index + 1})"
end
return self.joins("JOIN (VALUES #{values.join(",")}) as x (priority_id, ordering) ON #{table_name}.priority_id = x.priority_id").reorder('x.ordering')
end
And then you can use:
Product.where(id: pr_ids).order_by_priority_ids(ordered_priority_ids)

How to construct TSTZRANGE in rom-sql?

I can't find how to write this query in rom-sql. Is it possible to add plain sql to where?
It looks for announcements which do not intersect with requests.
announcements.when and requests.when are tstzrange columns in postgres.
SELECT "announcements".* FROM "announcements" WHERE (
(SELECT COUNT(requests.id)
FROM requests
WHERE requests.id IN (1,2,3) AND
(TSTZRANGE(lower(requests.when) - INTERVAL '1 HOUR', upper(requests.when) + INTERVAL '1 HOUR', '()') &&
TSTZRANGE(lower(announcements.when)), upper(announcements.when), '()') AND
requests.user_id = 42
) = 0
)
Check out the 'Advance Postgres support' section of the docs, http://api.rom-rb.org/rom-sql/ROM/SQL/Postgres/Types looks like there is support TsTzRange range('tstzrange', range_read_type(:tstzrange))
I found a solution to my problem.
Not sure if it's the right way in rom-sql.
I'll accept better answer if any appear.
Until that, here's my solution - Sequel.lit
In my case I defined a method in Announcements relation:
def available(user_id)
request_ids = requests.by_user_id(user_id).confirmed.pluck(:id)
# +- 1 hour around request is not available
# last argument '()' means "do not include boundaries"
request_when = "TSTZRANGE(
lower(requests.when) - INTERVAL '1 HOUR',
upper(requests.when) + INTERVAL '1 HOUR',
'()'
)"
announcement_when = "TSTZRANGE(lower(announcements.when), upper(announcements.when), '()')"
where(Sequel.lit(
"(SELECT COUNT(requests.id)
FROM requests
WHERE requests.id IN (:request_ids) AND
#{request_when} && #{announcement_when} AND
requests.user_id = :user_id) = 0",
user_id: user_id, request_ids: request_ids
))
end

How can I do this update query in ruby with sinatra?

I have table blogs and I want to add one to column views when user enter to the blog page .
DB[:blogs].where(:id => params[:id]).update(:views => :views + 1)
but it gave me error when I enter to the blog page in +
undefined method `+' for :views:Symbol
I'm do this :
blog = DB[:blogs].where(:id => params[:id]).first
views = blog[:views] + 1
DB[:blogs].where(:id => params[:id]).update(:views => views)
but this is add 3 or 5 or 1 or 4 not 1 only
(The question has nothing about Sinatra, just Sequel, which is not a part of Sinatra, but rather standalone library.)
You can do this:
DB[:blogs].where(:id => params[:id]).
update(Sequel.expr(:views) => Sequel.expr(:views) + 1)
Or just this:
DB[:blogs].where(:id => params[:id]).
update('views = views + 1')
Rails is mostly syntactic sugar, not a woodoo magic. In your case the most efficient way to perform a task is:
DB[:blogs].update_all("views = views + 1", ["id = ?", params[:id]])
This would generate the query (say id = 1):
UPDATE "blogs" SET views = views + 1 WHERE (id = 1)

1 result set from 3 queries?

I'm at my wits end attempting to make this happen. Currently I have 3 separate queries. For automation purposes I need to get the results of these three queries in one output, I cannot seem to join them properly to get the expected results.
QUERY 1:
SELECT OH.EXTN_HOST_ORDER_REF,
OL.EXTN_HOST_ORDER_LINE_REF,
OL.ORIGINAL_ORDERED_QTY,
OL.EXTN_TENDER_QUANTITY,
OL.EXTN_CUM_PICK_QTY,
OL.SHIPPED_QUANTITY,
OL.EXTN_REFUND_QTY
FROM YFS_ORDER_HEADER OH,
YFS_ORDER_LINE OL
WHERE OH.ORDER_HEADER_KEY = OL.ORDER_HEADER_KEY
AND OH.DOCUMENT_TYPE = '0001'
AND OH.EXTN_HOST_ORDER_REF = 'xxxxxxxxxxx'
ORDER BY PL.EXTN_HOST_ORDER_LINE_REF ASC;
QUERY 2:
SELECT RS.STATUS_QUANTITY AS RETURNED_QTY
FROM YFS_ORDER_HEADER OH,
YFS_ORDER_LINE OL,
YFS_ORDER_RELEASE_STATUS RS
WHERE OH.ORDER_HEADER_KEY = OL.ORDER_HEADER_KEY
AND OL.ORDER_LINE_KEY = RS.ORDER_LINE_KEY
AND RS.STATUS = '3700.02'
AND OH.EXTN_HOST_ORDER_REF = 'xxxxxxxxxxx';
QUERY 3
SELECT RS.STATUS_QUANTITY AS CANCELLED_QTY
FROM YFS_ORDER_HEADER OH,
YFS_ORDER_LINE OL,
YFS_ORDER_RELEASE_STATUS RS
WHERE OH.ORDER_HEADER_KEY = OL.ORDER_HEADER_KEY
AND OL.ORDER_LINE_KEY = RS.ORDER_LINE_KEY
AND RS.STATUS = '9000'
AND OH.EXTN_HOST_ORDER_REF = 'xxxxxxxxxxx';
The query should show NULL values where no data exists from query 2 & 3.
Thanks in advance for your help and advice!
If you are allowed to show both returned and cancelled quantities, the following simple edit should work. Hope this helps.
SELECT oh.extn_host_order_ref,
ol.extn_host_order_line_ref,
ol.original_ordered_qty,
ol.extn_tender_quantity,
ol.extn_cum_pick_qty,
ol.shipped_quantity,
ol.extn_refund_qty,
DECODE (rs.status, '3700.02', rs.status_quantity) AS returned_qty,
DECODE (rs.status, '9000', rs.status_quantity) AS cancelled_qty
FROM yfs_order_header oh
INNER JOIN yfs_order_line ol
ON oh.order_header_key = ol.order_header_key
LEFT OUTER JOIN yfs_order_release_status rs
ON ol.order_line_key = rs.order_line_key
WHERE oh.document_type = '0001' AND oh.extn_host_order_ref = 'xxxxxxxxxxx'
ORDER BY pl.extn_host_order_line_ref ASC;

"PGError: no connection to the server" while trying to create or save

Ruby 1.9.1 + ActiveRecord 2.3.5 + Postgres 8.3.7
Here is a rough sketch of my code. Ignore any obvious syntax details left out. The model below inherits from ActiveRecord::Base connected to a Postgres 8.3.7 database via ActiveRecord 2.3.5.
class TableA
has_many :tableB
end
class TableB
belongs_to :tableA
has_many :tableC
end
class TableC
belongs_to :tableB
has_many :tableD
end
class TableD
belongs_to :tableC
has_many :tableE
end
class TableE
belongs_to :tableD
end
# Note that tableA has fids that are referenced in tableE but is not part of this model
#
# Later in the script, in the same global scope, I want to add entries to these tables if
# I cannot find what I need. Bear in mind that this part betrays much Ruby noobiness.
toAdd.each do |widget|
add_tableA = TableA.find_by_sql().first # assumes I will get one back based on earlier sanity checks
add_tableB = TableB.find_by_sql().first
if (add_tableB == nil)
new_tableB = TableB.new( # value assignments )
new_tableB.save
add_tableB = TableB.find_by_sql().first
end
add_tableC = TableC.find_by_sql().first
if (add_tableC == nil)
new_tableC = TableC.new( # value assignments )
new_tableC.save
add_tableC = TableC.find_by_sql().first
end
add_tableD = TableD.find_by_sql().first
if (add_tableD == nil)
new_tableD = TableD.new( # value assignments )
new_tableD.save
add_tableD = TableD.find_by_sql().first
end
# I step into TableA again because items in TableE are linked to items in TableA, but they are
# distinct from the "high level" item I grabbed from TableA earlier.
add_tableA = TableA.find_by_sql().first
if (add_tableA == nil)
new_tableA = TableA.new( # value assignments )
new_tableA.save
add_tableA = TableA.find_by_sql().first
end
# Now that I have a TableA id to put into TableE, just create TableE row because I know this
# does not exist yet.
new_tableE = TableE.new( # value assignments ) # again, this is assumed to be new based on earlier checks
new_tableE.save
end
What always happens is I get the following stack trace:
/...gems/activerecord-2.3.5/lib/active_record/connection_adapters/abstract_adapter.rb:219:in `rescue in log': PGError: no connection to the server (ActiveRecord::StatementInvalid)
: ROLLBACK
from .../gems/1.9.1/gems/activerecord-2.3.5/lib/active_record/connection_adapters/abstract_adapter.rb:202:in `log'
from .../gems/1.9.1/gems/activerecord-2.3.5/lib/active_record/connection_adapters/postgresql_adapter.rb:550:in `execute'
from .../gems/1.9.1/gems/activerecord-2.3.5/lib/active_record/connection_adapters/postgresql_adapter.rb:576:in `rollback_db_transaction'
from .../gems/1.9.1/gems/activerecord-2.3.5/lib/active_record/connection_adapters/abstract/database_statements.rb:143:in `rescue in transaction'
from .../gems/1.9.1/gems/activerecord-2.3.5/lib/active_record/connection_adapters/abstract/database_statements.rb:125:in `transaction'
from .../gems/1.9.1/gems/activerecord-2.3.5/lib/active_record/transactions.rb:182:in `transaction'
from .../gems/1.9.1/gems/activerecord-2.3.5/lib/active_record/transactions.rb:200:in `block in save_with_transactions!'
from .../gems/1.9.1/gems/activerecord-2.3.5/lib/active_record/transactions.rb:208:in `rollback_active_record_state!'
from .../gems/activerecord-2.3.5/lib/active_record/transactions.rb:200:in `save_with_transactions!'
.... regardless if I'm calling save, save!, or doing a create instead of new and save.
strace reveals that I can only get one BEGIN..INSERT..COMMIT transaction to work for each run of this. Any subsequent attempts to INSERT within a transaction either in the same run of the loop or the next one ends with the connection being dropped before a COMMIT is sent. Clearly, I'm doing something wrong here with how I'm stepping into the ActiveRecord model.
I see the following strace only just before the first successful INSERT statement is set up. Is there something in ActiveRecord that allows me to preserve this as I step through tables, or am I simply Doing It Wrong?
rt_sigaction(SIGPIPE, {0x1, [], SA_RESTORER|SA_RESTART, 0x3876c0eb10}, {0x4b2ff0, [], SA_RESTORER|SA_RESTART, 0x3876c0eb10}, 8) = 0
sendto(3, "Q\0\0\2e SELECT attr.attna"..., 614, 0, NULL, 0) = 614
rt_sigaction(SIGPIPE, {0x4b2ff0, [], SA_RESTORER|SA_RESTART, 0x3876c0eb10}, {0x1, [], SA_RESTORER|SA_RESTART, 0x3876c0eb10}, 8) = 0
poll([{fd=3, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=3, revents=POLLIN}])
recvfrom(3, "T\0\0\0:\0\2attname\0\0\0\4\341\0\2\0\0\0\23\0#\377\377\377\377\0"..., 16384, 0, NULL, NULL) = 541
Any help here is greatly appreciated.
Thanks everyone. I apologize for taking anyone's time in trying to fix this. This instance of postgres depends upon a second process to run to handle pushing trigger events out to other processes. That process was not running, so the database server booted after the first committed INSERT. It's a custom in-house kind of thing.

Resources