After RAILS_ENV=development rails c
rails console development
etc...
My console cant return any values for my queries. And of course , i have data.
I am using vagrant and port_fowarding.
[20] pry(main)> User.first
Empresa::Empresa Load (1.1ms) SELECT "empresas".* FROM "empresas" WHERE "empresas"."id" = $1 LIMIT 1 [["id", nil]]
User Load (1.1ms) SELECT "usuarios".* FROM "usuarios" INNER JOIN "pessoas" ON "pessoas"."id" = "usuarios"."pessoa_id" AND "pessoas"."empresa_id" IS NULL WHERE (pessoas.empresa_id = NULL) ORDER BY "usuarios"."id" ASC LIMIT 1
=> nil
No matter what, always returning Nil.
Related
From some time I have noticed that I can't see properly database query params with special gems.
(Rails 5,Ruby 2.5.1, Postgresql 10)
Example: rack-mini-profiler, rails_panel:
SELECT "items"."id" FROM "items" WHERE "item"."category_id" IN ($1,$2,$3) LIMIT $4;
Early it was:
SELECT "items"."id" FROM "items" WHERE "item"."category_id" IN (11,12,13) LIMIT 20;
Controller action:
Item.select(:id).where(category_id: #ids).limit(per_page)
#let be #ids = [11,12,13], per_page = 20
The output of clear log in terminal:
Item Load (2.6ms) SELECT "items"."id" FROM "items" WHERE "item"."category_id" IN ($1,$2,$3) LIMIT $4
[["category_id", 11], ["category_id", 12],["category_id", 13], ["LIMIT", 20]]
I tried to rollback many steps of changes, but nothing changed.
What can i do to get back normal output for debug?
What's the best way to handle a large result set with Rails and Postgres? I didn't have a problem until today, but now I'm trying to return a 124,000 record object of #network_hosts, which has effectively DoS'd my development server.
My activerecord orm isn't the prettiest, but I'm pretty sure cleaning it up isn't going to help in relation to performance.
#network_hosts = []
#host_count = 0
#company.locations.each do |l|
if l.grace_enabled == nil || l.grace_enabled == false
l.network_hosts.each do |h|
#host_count += 1
#network_hosts.push(h)
#network_hosts.sort! { |x,y| x.ip_address <=> y.ip_address }
#network_hosts = #network_hosts.first(5)
end
end
end
In the end, I need to be able to return #network_hosts to the controller for processing into the view.
Is this something that Sidekiq would be able to help with, or is it going to be just as long? If Sidekiq is the path to take, how do I handle not having the #network_hosts object upon page load since the job is running asyncronously?
I believe you want to (1) get rid of all that looping (you've got a lot of queries going on) and (2) do your sorting with your AR query instead of in the array.
Perhaps something like:
NetworkHost.
where(location: Location.where.not(grace_enabed: true).where(company: #company)).
order(ip_address: :asc).
tap do |network_hosts|
#network_hosts = network_hosts.limit(5)
#host_count = network_hosts.count
end
Something like that ought to do it in a single DB query.
I had to make some assumptions about how your associations are set up and that you're looking for locations where grace_enabled isn't true (nil or false).
I haven't tested this, so it may well be buggy. But, I think the direction is correct.
Something to remember, Rails won't execute any SQL queries until the result of the query is actually needed. (I'll be using User instead of NetworkHost so I can show you the console output as I go)
#users = User.where(first_name: 'Random');nil # No query run
=> nil
#users # query is now run because the results are needed (they are being output to the IRB window)
# User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."first_name" = $1 LIMIT $2 [["first_name", "Random"], ["LIMIT", 11]]
# => #<ActiveRecord::Relation [...]>
#users = User.where(first_name: 'Random') # query will be run because the results are needed for the output into the IRB window
# User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."first_name" = $1 LIMIT $2 [["first_name", "Random"], ["LIMIT", 11]]
# => #<ActiveRecord::Relation [...]>
Why is this important? It allows you to store the query you want to run in the instance variable and not execute it until you get to a view where you can use some of the nice methods of ActiveRecord::Batches. In particular, if you have some view (or export function, etc.) where you are iterating the #network_hosts, you can use find_each.
# Controller
#users = User.where(first_name: 'Random') # No query run
# view
#users.find_each(batch_size: 1) do |user|
puts "User's ID is #{user.id}"
end
# User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."first_name" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["first_name", "Random"], ["LIMIT", 1]]
# User's ID is 1
# User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."first_name" = $1 AND ("users"."id" > 1) ORDER BY "users"."id" ASC LIMIT $2 [["first_name", "Random"], ["LIMIT", 1]]
# User's ID is 2
# User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."first_name" = $1 AND ("users"."id" > 2) ORDER BY "users"."id" ASC LIMIT $2 [["first_name", "Random"], ["LIMIT", 1]]
# => nil
Your query is not executed until the view, where it will now load only 1,000 records (configurable) into memory at a time. Once it reaches the end of those 1,000 records, it will automatically run another query to fetch the next 1,000 records. So your memory is much more sane, at the cost of extra database queries (which are usually pretty quick)
This is a followup to an earlier thread: Ruby on Rails query not working properly.
As noted, I have several listings. In particular, a listing has_many :spaces, through: :designations and has_many :amenities, through: :offerings.
I define filters to restrict the listings that get shown.
The two main ones are:
# filter by amenities
if params[:search][:amenity_ids].present? && params[:search][:amenity_ids].reject(&:blank?).size > 0
#listings = #listings.joins(:amenities).where(amenities: { id: params[:search][:amenity_ids].reject(&:blank?) }).group('listings.id').having('count(*) >= ?', params[:search][:amenity_ids].reject(&:blank?).size)
end
# filter by space type
if params[:search][:space_ids].present? && params[:search][:space_ids].reject(&:blank?).size > 0
#listings = #listings.joins(:spaces).where('space_id IN (?)', params[:search][:space_ids].reject(&:blank?)).uniq
end
(Note that these reflect the solution indicated in the earlier thread.)
The first filter says: get all of the listings that have ALL of the selected amenities.
The second filter says: get all of the listings that match ANY of the selected space types.
But one issue remains. If I filter for space types 1 and 2 and amenities 1 and 2, I get listing A (which has space types 1 and 2 and amenity 2).
But I should presumably get [] since no listing has both amenities 1 and 2.
What is going on with these queries? Should they not be independent, but chainable?
Here is the output (I disabled the other filters for clarity):
Started GET "/listings/search?utf8=%E2%9C%93&search%5Baddress%5D=London%2C+United+Kingdom&search%5Bprice_min%5D=0&search%5Bprice_max%5D=1000.0&search%5Bprice_lower%5D=0&search%5Bprice_upper%5D=1000&search%5Bsize_min%5D=0&search%5Bsize_max%5D=1000&search%5Bsize_lower%5D=0&search%5Bsize_upper%5D=1000&search%5Bspace_ids%5D%5B%5D=1&search%5Bspace_ids%5D%5B%5D=2&search%5Bspace_ids%5D%5B%5D=&search%5Bamenity_ids%5D%5B%5D=1&search%5Bamenity_ids%5D%5B%5D=2&search%5Bamenity_ids%5D%5B%5D=&search%5Bsort_by%5D=Distance&commit=Apply+Filters" for ::1 at 2015-10-31 14:25:58 +0000
ActiveRecord::SchemaMigration Load (0.4ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by ListingsController#search as HTML
Parameters: {"utf8"=>"✓", "search"=>{"address"=>"London, United Kingdom", "price_min"=>"0", "price_max"=>"1000.0", "price_lower"=>"0", "price_upper"=>"1000", "size_min"=>"0", "size_max"=>"1000", "size_lower"=>"0", "size_upper"=>"1000", "space_ids"=>["1", "2", ""], "amenity_ids"=>["1", "2", ""], "sort_by"=>"Distance"}, "commit"=>"Apply Filters"}
(1.5ms) SELECT MAX("listings"."price") FROM "listings"
(0.6ms) SELECT MAX("listings"."size") FROM "listings"
Listing Load (4.4ms) SELECT DISTINCT "listings".* FROM "listings" INNER JOIN "offerings" ON "offerings"."listing_id" = "listings"."id" INNER JOIN "amenities" ON "amenities"."id" = "offerings"."amenity_id" INNER JOIN "designations" ON "designations"."listing_id" = "listings"."id" INNER JOIN "spaces" ON "spaces"."id" = "designations"."space_id" WHERE "amenities"."id" IN (1, 2) AND (space_id IN ('1','2')) GROUP BY listings.id HAVING count(*) >= 2 LIMIT 24 OFFSET 0
Image Load (0.5ms) SELECT "images".* FROM "images" WHERE "images"."listing_id" = $1 ORDER BY "images"."id" ASC LIMIT 1 [["listing_id", 1]]
Space Load (0.6ms) SELECT "spaces".* FROM "spaces" INNER JOIN "designations" ON "spaces"."id" = "designations"."space_id" WHERE "designations"."listing_id" = $1 [["listing_id", 1]]
Rendered listings/_map_infowindow.html.erb (56.1ms)
Rendered listings/_price_slider.html.erb (0.7ms)
Rendered listings/_size_slider.html.erb (0.6ms)
Space Load (0.4ms) SELECT "spaces".* FROM "spaces"
Amenity Load (0.4ms) SELECT "amenities".* FROM "amenities"
Rendered scripts/_checkbox_toggle.html.erb (0.5ms)
Rendered listings/_search_filters.html.erb (75.5ms)
(0.4ms) SELECT "spaces"."name" FROM "spaces" INNER JOIN "designations" ON "spaces"."id" = "designations"."space_id" WHERE "designations"."listing_id" = $1 [["listing_id", 1]]
CACHE (0.0ms) SELECT "images".* FROM "images" WHERE "images"."listing_id" = $1 ORDER BY "images"."id" ASC LIMIT 1 [["listing_id", 1]]
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 3]]
Avatar Load (0.7ms) SELECT "avatars".* FROM "avatars" WHERE "avatars"."user_id" = $1 ORDER BY "avatars"."id" ASC LIMIT 1 [["user_id", 3]]
Rendered listings/_listing_grid.html.erb (80.8ms)
(3.1ms) SELECT DISTINCT COUNT(DISTINCT "listings"."id") AS count_id, listings.id AS listings_id FROM "listings" INNER JOIN "offerings" ON "offerings"."listing_id" = "listings"."id" INNER JOIN "amenities" ON "amenities"."id" = "offerings"."amenity_id" INNER JOIN "designations" ON "designations"."listing_id" = "listings"."id" INNER JOIN "spaces" ON "spaces"."id" = "designations"."space_id" WHERE "amenities"."id" IN (1, 2) AND (space_id IN ('1','2')) GROUP BY listings.id HAVING count(*) >= 2
Rendered scripts/_map.html.erb (2.9ms)
Rendered scripts/_shuffle.html.erb (0.3ms)
Rendered listings/search.html.erb within layouts/application (178.7ms)
Rendered layouts/_head.html.erb (475.7ms)
Rendered scripts/_address_autocomplete.html.erb (0.3ms)
Rendered listings/_search_address.html.erb (13.7ms)
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 3]]
(0.5ms) SELECT DISTINCT "conversations"."id" FROM "conversations" WHERE (sender_id = 3 OR recipient_id = 3)
(0.5ms) SELECT DISTINCT "messages"."conversation_id" FROM "messages" WHERE ("messages"."user_id" != $1) AND "messages"."read" = $2 [["user_id", 3], ["read", "false"]]
CACHE (0.0ms) SELECT "avatars".* FROM "avatars" WHERE "avatars"."user_id" = $1 ORDER BY "avatars"."id" ASC LIMIT 1 [["user_id", 3]]
Rendered layouts/_navbar.html.erb (32.5ms)
Rendered scripts/_fade_error.html.erb (0.4ms)
Rendered scripts/_transparent_navbar.html.erb (0.3ms)
Completed 200 OK in 1045ms (Views: 688.6ms | ActiveRecord: 30.6ms)
I have also tried adding raise 'test' in order to do some testing in the better_errors live shell. I discovered:
>> #listings
=> #<ActiveRecord::Relation []>
>> #listings = #listings.joins(:spaces).where('space_id IN (?)', params[:search][:space_ids].reject(&:blank?)).uniq
=> #<ActiveRecord::Relation [#<Listing id: 1, title: "Test 1", address: "New Inn Passage, London WC2A 2AE, UK", latitude: 51.5139664, longitude: -0.1167323, size: 1000, min_lease: 1, price: #<BigDecimal:7f89ec245c98,'0.1E4',9(18)>, description: "Test 1", user_id: 3, state: "public", created_at: "2015-10-30 17:37:04", updated_at: "2015-10-30 17:37:04">]>
>>
Why is this happening and how can I fix it?
Any help would be greatly appreciated.
The issue is with how you are determining that all of the amenities have been matched.
When you are only joining the amenities then the count of the rows (prior to grouping) for a listing is the number of matched amenities, so the having clause does what you want.
When you join the spaces table too, then the number of rows (again prior to grouping) for a listing is the number of matches amenities times the number of matched rows. In your example there are 2 spaces and 1 amenity, so the count is 2 and your having clause is satisfied.
If instead of filtering on count(*) you filtered on count(distinct amenities.id) then you should be counting the number of amenity rows that were joined, which should produce the desired result.
I may have figured out the issue. I did the following in the console to test:
Set #listings = Listing.all.
Set #listings = #listings.joins(:amenities).where(amenities: { id: ['1', '2'].reject(&:blank?) }).group('listings.id').having('count(*) >= ?', ['1', '2'].reject(&:blank?).size).
This produces: => #<ActiveRecord::Relation []>, as desired.
I then checked to see what would happen if I were to do: #listings.joins(:spaces).
This produces: => #<ActiveRecord::Relation [#<Listing id: 1, title: "Test 1", address: "New Inn Passage, London WC2A 2AE, UK", latitude: 51.5139664, longitude: -0.1167323, size: 1000, min_lease: 1, price: #<BigDecimal:7ffcb02ce890,'0.1E4',9(18)>, description: "Test 1", user_id: 3, state: "public", created_at: "2015-10-30 17:37:04", updated_at: "2015-10-30 17:37:04">]>, even though #listings was initially [].
So the problem has to do with the joins(:spaces) in the second filter.
In order to make sure that #listings remains [] in the event that that is the result of the first filter, I added the extra condition && #listings.present? to the second filter, yielding:
if params[:search][:space_ids].present? && params[:search][:space_ids].reject(&:blank?).size > 0 && #listings.present?
That extra condition prevents the second filter from being executed and returning results that should not be returned.
This feels like an ugly hack, and I would welcome better solutions, but it seems to work.
I have deployed my Rails application on Heroku. However, I cannot save DB edits via Heroku console.
If I want to update a model via the console I take the following steps -
rails console
#doc = Document.find_by_title('Test’)
#doc.status = 1
#doc.save*
However, in Heroku model saves do not work
heroku run rails c
#doc = Document.find_by_title('Test’)
#doc.status = 1
#doc.save
Console output is as follows
(1.9ms) BEGIN
(1.9ms) BEGIN
Commontator::Thread Load (1.7ms) SELECT "commontator_threads".* FROM "commontator_threads" WHERE "commontator_threads"."commontable_id" = $1 AND "commontator_threads"."commontable_type" = $2 LIMIT 1 [["commontable_id", 40], ["commontable_type", "Document"]]
Commontator::Thread Load (1.7ms) SELECT "commontator_threads".* FROM "commontator_threads" WHERE "commontator_threads"."commontable_id" = $1 AND "commontator_threads"."commontable_type" = $2 LIMIT 1 [["commontable_id", 40], ["commontable_type", "Document"]]
Approval Load (1.8ms) SELECT "approvals".* FROM "approvals" WHERE "approvals"."document_id" = $1 [["document_id", 40]]
Approval Load (1.8ms) SELECT "approvals".* FROM "approvals" WHERE "approvals"."document_id" = $1 [["document_id", 40]]
Review Load (1.8ms) SELECT "reviews".* FROM "reviews" WHERE "reviews"."document_id" = $1 [["document_id", 40]]
Review Load (1.8ms) SELECT "reviews".* FROM "reviews" WHERE "reviews"."document_id" = $1 [["document_id", 40]]
(2.1ms) ROLLBACK
(2.1ms) ROLLBACK
This is the same for any attribute I try to update.
Any ideas?
I think I figured it out. It was being affected by validations, if you want to save and skip validation, then
#document.update_columns(status: 1)
or
#document.attribute['status'] = 1
#document.save
Both will skip validation.
You can also try this.
heroku run rails c
doc = Document.find_by_title("Test")
doc.status = 1
doc.save(validate: false)
I'm trying to set user's (admin) password from Rails console:
bundle exec rails console
> Spree::User.first.email
=> "admin#mysite.com"
> Spree::User.first.encrypted_password
Spree::User Load (1.1ms) SELECT "spree_users".* FROM "spree_users" LIMIT 1
=> "4ec556............................................."
> Spree::User.first.password='spree123'
Spree::User Load (1.0ms) SELECT "spree_users".* FROM "spree_users" LIMIT 1
=> "spree123"
> Spree::User.first.password_confirmation='spree123'
Spree::User Load (1.0ms) SELECT "spree_users".* FROM "spree_users" LIMIT 1
=> "spree123"
> Spree::User.first.save!
Spree::User Load (1.0ms) SELECT "spree_users".* FROM "spree_users" LIMIT 1
(0.3ms) BEGIN
(1.3ms) SELECT COUNT(DISTINCT "spree_users"."id") FROM "spree_users" LEFT OUTER JOIN "spree_roles_users" ON "spree_roles_users"."user_id" = "spree_users"."id" LEFT OUTER JOIN "spree_roles" ON "spree_roles"."id" = "spree_roles_users"."role_id" WHERE "spree_roles"."name" = 'admin'
(0.3ms) COMMIT
=> true
> Spree::User.first.encrypted_password
Spree::User Load (1.0ms) SELECT "spree_users".* FROM "spree_users" LIMIT 1
=> "1bc15d.............................................."
So far so good. It looks like the new password for the user has been changed and commited to the database. However when I try to log in later with a web client and using the new password, it fails with invalid identity/password message.
I even tried to update password with Spree::User.first.reset_password!('spree123', 'spree123') but sill cann't sign in.
Rails 3.2.12
Spree 1.3.2
Any idea what am I doing wrong ? How to properly set a new password ?
Thanks.
The problem is that every time you're doing Spree::User.first it's reloading the record from the database. This means you are setting the value on one instance of the record, reloading it, and then saving the reloaded model that hasn't actually changed. An easy way around this is to create a local instance variable containing the record and update that instead:
user = Spree::User.first
user.password='spree123'
user.password_confirmation='spree123'
user.save!
Spree::User.first.update_attributes(password: 'password')