Convert #<ActiveRecord::AssociationRelation to #<ActiveRecord::Relation - ruby-on-rails

Ok, so I'm getting an error breaking my code when the #products array is #<ActiveRecord::AssociationRelation when it's #<ActiveRecord::Relation everything works fine
if params[:collection_id] && params[:collection_id] != ""
#products = Collection.find_by(id: params[:collection_id]).products.not_hidden
else
#products = Product.for_company(#current_company).not_hidden.where(category_id: #category.subtree.visible.ids)
end
puts("===============")
puts #products.inspect
puts("===============")
First case, which causes the error, returns
#<ActiveRecord::AssociationRelation [#<Product id: 29, bar_code: "", deleted: false, price: 3242.0, discounted_price: 52.0, category_id: 15, tags: "", created_at: "2020-12-14 12:29:04", updated_at: "2020-12-17 14:45:26", final_price: 52.0, status: "visible", sku: "", barcode: "", priority: 100, min_quantity: 1, max_quantity: 100, add_shipping_fees: true, weight: 0.0, inventory: {"jklj"=>{"sku"=>"", "barcode"=>"", "quantity"=>"13"}, "ojio9"=>{"sku"=>"", "barcode"=>"", "quantity"=>"555"}}, add_to_inventory: true, is_translated: true, requires_preparing: false, name: "product englishh", description: "">]>
Second case, which works fine, returns
#<ActiveRecord::Relation [#<Product id: 28, bar_code: "", deleted: false, price: 21312.0, discounted_price: 23.0, category_id: 16, tags: "", created_at: "2020-12-10 12:03:37", updated_at: "2020-12-14 13:45:17", final_price: 23.0, status: "visible", sku: "", barcode: "", priority: 100, min_quantity: 1, max_quantity: 234, add_shipping_fees: true, weight: 0.0, inventory: {"ewqeqwr"=>{"sku"=>"", "barcode"=>"", "quantity"=>"0"}}, add_to_inventory: true, is_translated: true, requires_preparing: false, name: "ewqeqwr", description: "<p>qweqw</p>\r\n">,]>
So you can see that the only difference is that the one breaking is AssociationRelation instead of Relation, how can I convert it to Relation?
The error is the following:
PG::InvalidParameterValue: ERROR: cannot call jsonb_each on a non-object
: SELECT DISTINCT "products"."priority" AS alias_0, "products"."id" AS alias_1, "products"."id" FROM "products" LEFT OUTER JOIN "product_translations" ON "product_translations"."product_id" = "products"."id" INNER JOIN "collection_products" ON "products"."id" = "collection_products"."product_id" WHERE "products"."deleted" = $1 AND "collection_products"."collection_id" = $2 AND "products"."status" IN ($3, $4) AND "products"."status" = $5 AND (add_to_inventory =FALSE OR (add_to_inventory =TRUE AND inventory !='{}' )) AND NOT (ARRAY(select distinct (jsonb_each(inventory)).value->>'quantity' as integer)='{0}') ORDER BY "products"."priority" ASC, "products"."id" ASC LIMIT $6 OFFSET $7 excluded from capture: Not configured to send/capture in environment 'development'
The json_b each run happens here
#products = #products.offset(offset)
.limit(#limit)
.where(status: "visible")
.where("add_to_inventory =? OR (add_to_inventory =? AND inventory !=? )", false, true, "{}")
.where.not("ARRAY(select distinct (jsonb_each(inventory)).value->>'quantity' as integer)='{0}'")

Related

How to use rails ActiveRecord to perform a left join of a Model with a subquery

I am using rails 5. When I perform the following straight SQL query in the rails console, I get the following expected result:
2.3.5 :053 > w = ActiveRecord::Base.connection.exec_query("SELECT * FROM students s LEFT JOIN (SELECT student_id, MAX(urgent) AS has_urgent,MAX(created_at) AS last_contact FROM reports GROUP BY student_id) r ON r.student_id = s.id")
(0.5ms) SELECT * FROM students s LEFT JOIN (SELECT student_id, MAX(urgent) AS has_urgent,MAX(created_at) AS last_contact FROM reports GROUP BY student_id) r ON r.student_id = s.id
=> #<ActiveRecord::Result:0x00000000051e1518 #columns=["id", "name", "cwid", "email", "phone", "company", "role", "advisor", "advisor_email", "mentor", "created_at", "updated_at", "student_id", "has_urgent", "last_contact"], #rows=[[1, "Johnny Smith", "71419940", "jsmith#gmail.com", "8435550001", "foxtrot", "mentor", "John I. Moore, Jr.", "john.moore#citadel.edu", "", "2017-11-13 14:58:50.128114", "2017-11-13 14:58:50.128168", nil, nil, nil], [2, "Shelly", "12345678", "shelly#gmail.com", "8435550002", "bravo", "mentee", "Michael P. Verdicchio", "mv#citadel.edu", "Johnny Smith", "2017-11-13 14:58:50.160195", "2017-11-13 14:58:50.160243", "2", "t", "2017-11-13 14:58:50.210105"], [3, "Max", "87654321", "max#gmail.com", "8435550003", "palmetto", "unassigned", "Mei-Qin Chen", "mei.chen#citadel.edu", "", "2017-11-13 14:58:50.179220", "2017-11-13 14:58:50.179258", nil, nil, nil], [4, "George", "87654325", "george#gmail.com", "8435550004", "palmetto", "mentee", "Deepti Joshi", "djoshi#citadel.edu", "Johnny Smith", "2017-11-13 14:58:50.189733", "2017-11-13 14:58:50.189762", "4", "f", "2017-11-03 14:58:50.260914"]], #hash_rows=nil, #column_types={}>
However, this returns an ActiveRecord::Result type, but I really want is to use the Rails ActiveRecord to do the same query but return an ActiveRecord::Relation instead, I thought like so:
2.3.5 :054 > w = Student.joins("LEFT JOIN (SELECT student_id, MAX(urgent) AS has_urgent,MAX(created_at) AS last_contact FROM reports GROUP BY student_id) r ON r.student_id = students.id")
Student Load (0.5ms) SELECT "students".* FROM "students" LEFT JOIN (SELECT student_id, MAX(urgent) AS has_urgent,MAX(created_at) AS last_contact FROM reports GROUP BY student_id) r ON r.student_id = students.id LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Student id: 1, name: "Johnny Smith", cwid: "71419940", email: "jsmith#gmail.com", phone: "8435550001", company: "foxtrot", role: "mentor", advisor: "John I. Moore, Jr.", advisor_email: "john.moore#citadel.edu", mentor: "", created_at: "2017-11-13 14:58:50", updated_at: "2017-11-13 14:58:50">, #<Student id: 2, name: "Shelly", cwid: "12345678", email: "shelly#gmail.com", phone: "8435550002", company: "bravo", role: "mentee", advisor: "Michael P. Verdicchio", advisor_email: "mv#citadel.edu", mentor: "Johnny Smith", created_at: "2017-11-13 14:58:50", updated_at: "2017-11-13 14:58:50">, #<Student id: 3, name: "Max", cwid: "87654321", email: "max#gmail.com", phone: "8435550003", company: "palmetto", role: "unassigned", advisor: "Mei-Qin Chen", advisor_email: "mei.chen#citadel.edu", mentor: "", created_at: "2017-11-13 14:58:50", updated_at: "2017-11-13 14:58:50">, #<Student id: 4, name: "George", cwid: "87654325", email: "george#gmail.com", phone: "8435550004", company: "palmetto", role: "mentee", advisor: "Deepti Joshi", advisor_email: "djoshi#citadel.edu", mentor: "Johnny Smith", created_at: "2017-11-13 14:58:50", updated_at: "2017-11-13 14:58:50">]>
For this second approach, the Right table columns do not appear in the result, even though the generated SQL looks very similar. I am new to Rails and ActiveRecord, so if someone can help me understand why these two results are different and what I should do to make the second ActiveRecord query work like the straight SQL query I would appreciate it.
If you are using rails 5 then use left_joins or left_outer_joins.
Try this and let me know if it work for you.
Student.left_outer_joins(:reports).select("student.*, MAX(urgent) AS has_urgent,MAX(created_at) AS last_contact").group("student.id").
If you want to go with your first approach then these methods may helpful for you.
result.columns #Get the column names of the result.
result.rows #Get the record values of the result.
result.to_hash #Get an array of hashes representing the result (column => value)
#ActiveRecord::Result also includes Enumerable.

Check if a value created_at not equal to current date exists in an array in Ruby

I have a collection of user.paid_subscriptions in which each subscription has attributes created_at(datetime) and active(boolean).
How can I check if a PaidSubscription exists such that created_at is not equal to a certain date and active is true?
PaidSubscription looks like this:
[
#<PaidSubscription id: 11457,
user_id: 12,
period: 3,
price: 4000,
expires_at: "2016-03-08 09:44:56",
expires_at: "2016-03-08 09:44:56",
created_at: "2015-12-08 09:44:56",
updated_at: "2016-03-08 23:00:09",
active: false,
giver_id: 20573,
partial: false,
remaining_days: 0>,
#<PaidSubscription id: 13948,
user_id: 12,
period: 1,
price: 1500,
expires_at: "2016-04-11 12:07:40",
created_at: "2016-03-11 13:07:40",
updated_at: "2016-04-11 22:00:11",
active: false,
giver_id: nil,
partial: false,
remaining_days: 0>,
#<PaidSubscription id: 11458....
]
Try this,
If it is a query then it should be like this
user.paid_subscriptions.where("created_at < :date or created_at > :date and active = :active",{date: DateTime.civil(yyyy,mm,dd), active: true})
Or
if it is an array you can use it like below.
user.paid_subscriptions.any? {|ps| ps.active && ( ps.created_at.to_date < Date.civil(yyyy, mm, dd) || ps.created_at.to_date > Date.civil(yyyy, mm, dd))}

Rails console setting limit to one on queries

When I run ActiveRecord queries, the Rails Console seems to be appending LIMIT 1 to my queries.
So I have a sheet which has_many slots. When I query Slot.find_by(sheet_id: 96), I get:
Slot Load (2.3ms) SELECT "slots".* FROM "slots" WHERE "slots"."sheet_id" = ? LIMIT 1 [["sheet_id", 96]]
=> #<Slot id: 153, label: "Foo", name: "Foo", email: "", phone: "", comments: "Fighters", sheet_id: 96, created_at: "2015-04-30 14:28:47", updated_at: "2015-04-30 14:28:47">
But when I query Sheet.find(96).slots:
Sheet Load (10.0ms) SELECT "sheets".* FROM "sheets" WHERE "sheets"."id" = ? LIMIT 1 [["id", 96]]
Slot Load (4.6ms) SELECT "slots".* FROM "slots" WHERE "slots"."sheet_id" = ? [["sheet_id", 96]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Slot id: 153, label: "Foo", name: "Foo", email: "", phone: "", comments: "Fighters", sheet_id: 96, created_at: "2015-04-30 14:28:47", updated_at: "2015-04-30 14:28:47">, #<Slot id: 154, label: "Bar", name: "James", email: "", phone: "", comments: "Foobar", sheet_id: 96, created_at: "2015-04-30 14:28:47", updated_at: "2015-04-30 14:28:47">, ... >
You have to do Slot.find_all_by_sheet_id(96)
EDIT The above code should have worked. Although I use Rails 4.1.8. Try following as well:
Slot.where(:sheet_id => 338)
The find_by method returns a single result, always.
If you want to get all of the slots for a particular sheet, there are a few options:
Sheet.find(96).slots or more likely #sheet.slots if you've already found the sheet
Slot.where(sheet_id: 96) would also work
To be clear, this has nothing to do with the Rails console and everything to do with the .find_by method.

Convert ActiveRecord::Relation into a usable array

When I call:
preivous_lessons = #item.where("track_id = ?", lesson.track_id)
I get this active record realtion:
[#<CodeLesson id: 2, name: "Python", permalink: "python", lesson_content: "", instructions: "Print your name to the console.", hints: "", starting_code: "\"\"\"\r\nThis is a comment\r\n\"\"\"\r\n\r\nprint(\"Hello, World\"...", language_id: "12", order: 1, track_id: 2, user_id: 1, created_at: "2014-02-14 16:01:12", updated_at: "2014-02-15 21:14:43", visible: true>, #<CodeLesson id: 8, name: "Test Lesson", permalink: "test-lesson", lesson_content: nil, instructions: nil, hints: nil, starting_code: nil, language_id: "26", order: nil, track_id: 2, user_id: 1, created_at: "2014-02-20 19:23:15", updated_at: "2014-02-20 19:23:15", visible: false>]
How do I convert this into a usable array of models so I can do something like this:
preivous_lessons.each do |i|
highest = i.order if i.order > highest
end
As OP confirmed from my comment, that my hint solved his problem, I am putting it as an answer to the post :
preivous_lessons = #item.where("track_id = ?", lesson.track_id)
highest = preivous_lessons.maximum(:order)
Documentation of maximum :
Calculates the maximum value on a given column. The value is returned with the same data type of the column, or nil if there's no row.
preivous_lessons = #item.where("track_id = ?", lesson.track_id).all

Acts As Taggable On

I'm having problems getting the acts-as-taggable-on gem working properly.
I have a model:
class Resource < ActiveRecord::Base
acts_as_taggable
end
I can add tags to it, and though its tag_list is populated:
$ a = ArchiveResource.new()
$ a.tag_list = ["one", "two", "three"]
$ a.tag_list # ["one", "two", "three"]
However, its tag association is not:
$ a.tags # []
If I check for all the tags, I can see they are being created:
$ ActsAsTaggableOn::Tag.all #<ActsAsTaggableOn::Tag id: 1, name: "one">,
#<ActsAsTaggableOn::Tag id: 2, name: "two">,
#<ActsAsTaggableOn::Tag id: 3, name: "three">
And if I check the model's taggings association I can see they exist there:
$ a.taggings #<ActsAsTaggableOn::Tag id: 1, name: "one">,
#<ActsAsTaggableOn::Tag id: 2, name: "two">,
#<ActsAsTaggableOn::Tag id: 3, name: "three">
Looking more closely at a call to a.tags.all I can see from the query that there is a mismatch:
ActsAsTaggableOn::Tag Load (0.9ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = 1 AND "taggings"."taggable_type" = 'ArchiveResource' AND (taggings.context = ('tags'))
However the taggings_context of the model's Taggings are all set to tag singular, so the query always fails:
<ActsAsTaggableOn::Tagging id: 1, tag_id: 1, taggable_id: 1, taggable_type: "Resource", tagger_id: nil, tagger_type: nil, context: "tag", created_at: "2013-09-10 17:12:20
<ActsAsTaggableOn::Tagging id: 2, tag_id: 1, taggable_id: 1, taggable_type: "Resource", tagger_id: nil, tagger_type: nil, context: "tag", created_at: "2013-09-10 17:12:20
<ActsAsTaggableOn::Tagging id: 3, tag_id: 1, taggable_id: 1, taggable_type: "Resource", tagger_id: nil, tagger_type: nil, context: "tag", created_at: "2013-09-10 17:12:20
If I run through all the Taggables and set context to tags, everything works:
ActsAsTaggableOn::Tagging.all.each{|t|t.context = "tags"; t.save!}
So why is this happening. Is it a bug or am I doing something wrong?
Looks like the default implementation is broken. By explicitly declaring the tags as :tags everything works OK:
acts_as_taggable_on :tags

Resources