After deploying my application I created a new user and noticed that the address bar was reporting number 2 at the end of the url: htt://...herokuapp.com/users/2.
So I checked with rails console in production environment first and then at Heroku. There seemed to be nothing irregular in my production environment (running sqlite3), so I ran heroku run console --sandbox and got the following results:
irb(main):001:0> User.count
(4.9ms) SELECT COUNT(*) FROM "users"
(4.9ms) SELECT COUNT(*) FROM "users"
=> 1
irb(main):002:0> User.first
User Load (2.5ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1
User Load (2.5ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1
=> #<User id: 2, name: "Mark Homburg", email: "mark.homburg#yahoo.com", created_at: "2015-12-20 13:56:04", updated_at: "2015-12-20 13:56:04", password_digest: "...">
irb(main):001:0> User.find(1)
User Load (1.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 1]]
User Load (1.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 1]]
ActiveRecord::RecordNotFound: Couldn't find User with 'id'=1
What is irregular at Heroku is the duplicate SELECT FROM "users" action after running User.count, User.first and User.find(1). As I said there was nothing irregular in the corresponding commands in my production environment:
>> User.find(1)
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
=> #<User id: 1, name: "Rails Tutorial", email: "example#railstutorial.org", created_at: "2015-12-20 10:08:22", updated_at: "2015-12-20 10:08:22", password_digest: "...">
In my opinion this could be explained by the presence of a duplicate users table in the database, as I tried to explain in Duplicate migrations in topic branch.
What is your opinion and what do you suggest I can do?
Related
I am doing a rake task to sync data from rails app to solr
I use:
Job.all to get all the records and process them afterwards.But what if in Job has millions of records. As far as I know the all method will save all records to RAM, which definitely affects performance. Is there any other way to process all records without using all method?
Look at the find_in_batches, this will not load all the records at once.
By default it will load the 1000 rows and also helps to reduce memory consumption.
2.5.1 :013 > User.find_in_batches do |group, batch|
2.5.1 :014 > puts "Processing group ##{batch}"
2.5.1 :015?> end
User Load (7.5ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1000]]
Processing group ##<User:0x00005596f8ef44c8>
User Load (5.9ms) SELECT "users".* FROM "users" WHERE "users"."id" > $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1002], ["LIMIT", 1000]]
Processing group ##<User:0x00005596f908e900>
User Load (5.0ms) SELECT "users".* FROM "users" WHERE "users"."id" > $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 2002], ["LIMIT", 1000]]
Processing group ##<User:0x00007f36a4f1a428>
User Load (6.7ms) SELECT "users".* FROM "users" WHERE "users"."id" > $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 3004], ["LIMIT", 1000]]
Processing group ##<User:0x00007f36a4b82590>
I'm using will_paginate to paginate posts within a group.
A group might have many posts and I don't want to show all posts at once.
For some strange reason I noticed that a lot of posts are deleted from the database when I do #group.posts = paginated_posts as displayed in * groups_controller*.
I'm not doing save on #group, why are the posts deleted?
Tests first
69 it "Pagination – get one group and its posts" do
70 10.times { Fabricate(:post, group: #group, user: #user) }
71 puts "POST COUNT BEFORE #{#group.posts.count}"
72 # byebug
73 get group_path(#group, posts_per_page: 3)
74 puts "POST COUNT AFTER #{#group.posts.count}"
75 expect(response).to have_http_status(200)
76 expect(#group).to be_present
77 end
Output from the test
Groups
GET /group/:group_id?posts_per_page=10&posts_page=2
POST COUNT BEFORE 12
POST COUNT AFTER 3
groups_controller.rb
9 def show
10 paginated_posts = #group.posts.paginate(
11 page: params[:posts_page],
12 per_page: params[:posts_per_page] || 100000,
13 )
14 #group.posts = paginated_posts
15 render json: #group
16 end
The log
(0.3ms) RELEASE SAVEPOINT active_record_1
Started GET "/groups/33?posts_per_page=3" for 127.0.0.1 at 2018-09-18 12:52:13 +0000
Processing by GroupsController#show as HTML
Parameters: {"posts_per_page"=>"3", "id"=>"33"}
User Load (2.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", "78913bd2-4c72-4c73-ba75-421e154c830b"], ["LIMIT", 1]]
Group Load (1.4ms) SELECT "groups".* FROM "groups" WHERE "groups"."id" = $1 LIMIT $2 [["id", 33], ["LIMIT", 1]]
Post Load (2.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."group_id" = $1 LIMIT $2 OFFSET $3 [["group_id", 33], ["LIMIT", 3], ["OFFSET", 0]]
Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."group_id" = $1 [["group_id", 33]]
(0.4ms) SAVEPOINT active_record_1
Comment Load (0.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = $1 [["post_id", 156]]
PostImage Load (0.3ms) SELECT "post_images".* FROM "post_images" WHERE "post_images"."post_id" = $1 [["post_id", 156]]
Post Destroy (0.3ms) DELETE FROM "posts" WHERE "posts"."id" = $1 [["id", 156]]
Comment Load (0.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = $1 [["post_id", 157]]
PostImage Load (0.3ms) SELECT "post_images".* FROM "post_images" WHERE "post_images"."post_id" = $1 [["post_id", 157]]
Post Destroy (0.3ms) DELETE FROM "posts" WHERE "posts"."id" = $1 [["id", 157]]
Comment Load (0.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = $1 [["post_id", 158]]
#group.posts = ... doesn't work the way you think it does. If you have a one-to-many relationship and you assign an array of associated records to the existing group object, the records set and remove the group.id foreign key immediately. No save is required.
So when you do
#group.posts = paginated_posts
The paginated posts are assigned to the association and all other records in the association are removed from the association. Instantly. They're not necessarily deleted, but they no longer belong to #post
You may want to change your #to_json ... perhaps add
attr_accessor :page_of_posts
And then in your controller
#group.page_of_posts = paginated_posts
And ensure page_of_posts is what's rendered in the json. Others may suggest a better way.
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.
Here is my problem:
I'm using Devise's guest_user, that contains a logging_in method to transfer guest_user parameters to the registered user when he logs in. So in my case, the user has_many periods, dependent: :destroy, so here is the logging_in method:
def logging_in
guest_periods = guest_user.periods.all
guest_periods.each do |p|
p.user_id = current_user.id
p.save!
end
current_user.latest_entry = guest_user.latest_entry
current_user.is_in_zone = guest_user.is_in_zone
current_user.save
end
However, when a guest_user logs in, his periods gets destroyed instead of being transfered. Here is the log:
Started GET "/" for ::1 at 2015-05-11 00:18:03 +0300
Processing by WelcomeController#index as HTML
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 24]]
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 23]]
Period Load (0.3ms) SELECT "periods".* FROM "periods" WHERE "periods"."user_id" = $1 [["user_id", 23]]
(0.2ms) BEGIN
CACHE (0.0ms) SELECT "periods".* FROM "periods" WHERE "periods"."user_id" = $1 [["user_id", 23]]
SQL (0.8ms) UPDATE "periods" SET "user_id" = $1, "updated_at" = $2 WHERE "periods"."id" = $3 [["user_id", 24], ["updated_at", "2015-05-10 21:18:03.863162"], ["id", 170]]
(0.9ms) COMMIT
(0.2ms) BEGIN
SQL (2.1ms) UPDATE "users" SET "is_in_zone" = $1, "latest_entry" = $2, "updated_at" = $3 WHERE "users"."id" = $4 [["is_in_zone", "t"], ["latest_entry", "2015-05-04"], ["updated_at", "2015-05-10 21:18:03.875572"], ["id", 24]]
(15.8ms) COMMIT
(0.5ms) BEGIN
SQL (0.3ms) DELETE FROM "periods" WHERE "periods"."id" = $1 [["id", 170]]
SQL (0.7ms) DELETE FROM "users" WHERE "users"."id" = $1 [["id", 23]]
(1.2ms) COMMIT
So we can see that the transfer is done, but then in the end, the periods are destroyed anyway. They should not be, as they are not belonging to the user to be destroyed any more.
Why is it happening?
Even though Period#user_id has changed, guest_user.periods is still loaded in memory and is what gets destroyed when you destroy the guest user. If you guest_user.reload, its associations will clear out and it becomes safe to destroy. You could also guest_user.periods(true) to force reload of just the periods.
Another option is:
guest_user.periods.update_all(user_id: current_user.id)
This executes a single query to perform the update, which will be nice if there are a lot of periods, and also doesn't load the guest_user.periods association, so it will load fresh during the destroy and find the correct empty set.
Hello friends I want to ask them how to make rails console
does not show me the sqlite consult
Loading development environment (Rails 4.0.5)
2.0.0-p481 :001 > last_user=User.last
User Load (0.3ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT 1
=> #<User id: 5, name: "Juan", email: "Lopez", created_at: "2014-06-02 19:50:48", updated_at: "2014-06-02 19:50:48">
I do not want to show this
User Load (0.3ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT 1
In console type:
ActiveRecord::Base.logger = nil