I'm going crazy. My each-loop in rails always runs twice for each collection item. I have no clue why.
locations = Location.all
locations.each do |loc|
# delay to not overload le webservice
sleep 1.0
if [... some webservice call - runs fine ... ]
# score calculation - V0.1
score = [... some formula to calculate a score ...]
score_total = score + loc.score_total
score_count = loc.score_count + 1
# update the current record which fresh values from the webservice
loc.update(:temp1 => temp[0],
:temp2 => temp[1],
:temp3 => temp[2],
:temp4 => temp[3],
:temp5 => temp[4],
:condition1 => condition[0],
:condition2 => condition[1],
:condition3 => condition[2],
:condition4 => condition[3],
:condition5 => condition[4],
:score_yesterday => loc.score_now,
:score_now => score,
:score_total => score_total,
:score_count => score_count)
end
end
count jumps in 2-times steps
some variables I want to update within each iteration are always behind
LOG:
Started GET "/loc" for 127.0.0.1 at 2014-02-01 13:37:22 +0100
Processing by WhitelabelsController#loc as HTML
[1m[36mWhitelabelWsd Load (0.6ms)[0m [1mSELECT "whitelabel_wsds".* FROM "whitelabel_wsds"[0m
[1m[35m (0.3ms)[0m BEGIN
[1m[36mSQL (4.4ms)[0m [1mUPDATE "whitelabel_wsds" SET "temp1" = $1, "temp2" = $2, "temp3" = $3, "temp4" = $4, "temp5" = $5, "condition1" = $6, "condition2" = $7, "condition3" = $8, "condition4" = $9, "condition5" = $10, "score_now" = $11, "score_total" = $12, "score_count" = $13, "updated_at" = $14 WHERE "whitelabel_wsds"."id" = 2[0m [["temp1", 17], ["temp2", 15], ["temp3", 13], ["temp4", 14], ["temp5", 13], ["condition1", "Patchy rain nearby"], ["condition2", "Cloudy "], ["condition3", "Sunny"], ["condition4", "Light rain shower"], ["condition5", "Sunny"], ["score_now", 306], ["score_total", 10934], ["score_count", 48], ["updated_at", Sat, 01 Feb 2014 12:37:23 UTC +00:00]]
[1m[35m (264.2ms)[0m COMMIT
[1m[36m (0.2ms)[0m [1mBEGIN[0m
[1m[35mSQL (0.8ms)[0m UPDATE "whitelabel_wsds" SET "temp1" = $1, "temp2" = $2, "temp3" = $3, "temp4" = $4, "temp5" = $5, "condition1" = $6, "condition2" = $7, "condition3" = $8, "condition4" = $9, "condition5" = $10, "score_now" = $11, "score_total" = $12, "score_count" = $13, "updated_at" = $14 WHERE "whitelabel_wsds"."id" = 3 [["temp1", 16], ["temp2", 11], ["temp3", 16], ["temp4", 13], ["temp5", 17], ["condition1", "Cloudy "], ["condition2", "Sunny"], ["condition3", "Cloudy "], ["condition4", "Sunny"], ["condition5", "Partly Cloudy "], ["score_now", 391], ["score_total", 22791], ["score_count", 51], ["updated_at", Sat, 01 Feb 2014 12:37:25 UTC +00:00]]
[1m[36m (1.3ms)[0m [1mCOMMIT[0m
[1m[35m (0.1ms)[0m BEGIN
[1m[36mSQL (1.4ms)[0m [1mUPDATE "whitelabel_wsds" SET "temp1" = $1, "temp2" = $2, "temp3" = $3, "temp4" = $4, "temp5" = $5, "condition1" = $6, "condition2" = $7, "score_now" = $8, "score_total" = $9, "score_count" = $10, "updated_at" = $11 WHERE "whitelabel_wsds"."id" = 1[0m [["temp1", 21], ["temp2", 22], ["temp3", 21], ["temp4", 22], ["temp5", 23], ["condition1", "Partly Cloudy "], ["condition2", "Partly Cloudy "], ["score_now", 961], ["score_total", 93375], ["score_count", 61], ["updated_at", Sat, 01 Feb 2014 12:37:26 UTC +00:00]]
[1m[35m (0.5ms)[0m COMMIT
Rendered whitelabels/loc.html.erb within layouts/whitelabel (0.1ms)
Completed 200 OK in 4318ms (Views: 6.6ms | ActiveRecord: 277.8ms)
Started GET "/loc" for 127.0.0.1 at 2014-02-01 13:37:26 +0100
Processing by WhitelabelsController#loc as HTML
[1m[36mWhitelabelWsd Load (0.7ms)[0m [1mSELECT "whitelabel_wsds".* FROM "whitelabel_wsds"[0m
[1m[35m (0.2ms)[0m BEGIN
[1m[36mSQL (0.7ms)[0m [1mUPDATE "whitelabel_wsds" SET "score_yesterday" = $1, "score_total" = $2, "score_count" = $3, "updated_at" = $4 WHERE "whitelabel_wsds"."id" = 2[0m [["score_yesterday", 306], ["score_total", 11240], ["score_count", 49], ["updated_at", Sat, 01 Feb 2014 12:37:27 UTC +00:00]]
[1m[35m (0.6ms)[0m COMMIT
[1m[36m (0.2ms)[0m [1mBEGIN[0m
[1m[35mSQL (0.6ms)[0m UPDATE "whitelabel_wsds" SET "score_yesterday" = $1, "score_total" = $2, "score_count" = $3, "updated_at" = $4 WHERE "whitelabel_wsds"."id" = 3 [["score_yesterday", 391], ["score_total", 23182], ["score_count", 52], ["updated_at", Sat, 01 Feb 2014 12:37:29 UTC +00:00]]
[1m[36m (0.5ms)[0m [1mCOMMIT[0m
[1m[35m (0.2ms)[0m BEGIN
[1m[36mSQL (0.5ms)[0m [1mUPDATE "whitelabel_wsds" SET "score_yesterday" = $1, "score_total" = $2, "score_count" = $3, "updated_at" = $4 WHERE "whitelabel_wsds"."id" = 1[0m [["score_yesterday", 961], ["score_total", 94336], ["score_count", 62], ["updated_at", Sat, 01 Feb 2014 12:37:30 UTC +00:00]]
[1m[35m (0.5ms)[0m COMMIT
Rendered whitelabels/loc.html.erb within layouts/whitelabel (0.1ms)
Completed 200 OK in 3598ms (Views: 4.7ms | ActiveRecord: 4.5ms)
Was going to write comment, but it will be clearer here:
I'd imagine there to be 3 potential causes of your problem:
Perhaps update is saving the data incorrectly / before & after the webservice call
Your webservice may be taking too long
Perhaps something else is messing-up?
update_attributes
Having looked over the .update & .update_attributes methods, it looks like you could replace .update with .update_attributes
Although the difference escapes me, we use update_attributes all the time - it does exactly what you need here:
loc.update_attributes(
:temp1 => temp[0],
:temp2 => temp[1],
:temp3 => temp[2],
:temp4 => temp[3],
:temp5 => temp[4],
:condition1 => condition[0],
:condition2 => condition[1],
:condition3 => condition[2],
:condition4 => condition[3],
:condition5 => condition[4],
:score_yesterday => loc.score_now,
:score_now => score,
:score_total => score_total,
:score_count => score_count
)
Webservice
Another issue may be that your webservice call is taking too long
Any external dependencies obviously carry added latency, which you may need to factor into your process
Currently, you don't have any logic to determine whether the call was successful or not. This could explain your app's increasing the count without the other items (it doesn't have access to the new data):
locations.each do |loc|
if [... some webservice call - runs fine ... ]
# score calculation - V0.1
score = [... some formula to calculate a score ...]
score_total = score + loc.score_total
# update the current record which fresh values from the webservice
loc.update_attributes(:temp1 => temp[0],
:temp2 => temp[1],
:temp3 => temp[2],
:temp4 => temp[3],
:temp5 => temp[4],
:condition1 => condition[0],
:condition2 => condition[1],
:condition3 => condition[2],
:condition4 => condition[3],
:condition5 => condition[4],
:score_yesterday => loc.score_now,
:score_now => score,
:score_total => score_total
)
loc.increment!(:score_count)
end
end
.increment! method ;)
Logs
Lots of these types of error can be explained with the logs
The logs will detail exactly which calls are being made & when; allowing us to see what's happening
I have solved it while implementing two different functions:
def check_weather(location_station)
[... webservice call ... ]
end
locations.each do |loc|
sleep 1.0
check_weather(loc.location_station)
loc.update(...)
end
Related
Here's a fun ActiveStorage issue which has been causing me to scratch my head in confusion for a couple of days; ActiveStorage seems to not be playing well with either fixture_file_upload & Rack::Test::UploadedFile as both methods are throwing the following error when saving a file to a model attachment using ActiveStorage:
Loading development environment (Rails 6.0.3.4)
irb(main):001:0> Attachment.create({file: Rack::Test::UploadedFile.new("#{Rails.root}/test/fixtures/files/tracer1.jpg", 'tracer1.jpg')})
D, [2021-01-22T16:20:03.695894 #498] DEBUG -- : (0.3ms) BEGIN
D, [2021-01-22T16:20:03.730325 #498] DEBUG -- : Attachment Create (0.8ms) INSERT INTO "attachments" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2021-01-22 16:20:03.726078"], ["updated_at", "2021-01-22 16:20:03.726078"]]
D, [2021-01-22T16:20:03.735233 #498] DEBUG -- : ActiveStorage::Attachment Load (0.4ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = $1 AND "active_storage_attachments"."record_type" = $2 AND "active_storage_attachments"."name" = $3 LIMIT $4 [["record_id", 1], ["record_type", "Attachment"], ["name", "file"], ["LIMIT", 1]]
D, [2021-01-22T16:20:03.736695 #498] DEBUG -- : ActiveStorage::Blob Create (0.3ms) INSERT INTO "active_storage_blobs" ("key", "filename", "content_type", "metadata", "byte_size", "checksum", "created_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["key", "uk44hg6aeqgkijnoti7625kmymn5"], ["filename", "tracer1.jpg"], ["content_type", "image/jpeg"], ["metadata", "{\"identified\":true}"], ["byte_size", 71843], ["checksum", "fleS+FPvNcLEHaUysUgaGQ=="], ["created_at", "2021-01-22 16:20:03.735850"]]
D, [2021-01-22T16:20:03.737593 #498] DEBUG -- : ActiveStorage::Attachment Create (0.4ms) INSERT INTO "active_storage_attachments" ("name", "record_type", "record_id", "blob_id", "created_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["name", "file"], ["record_type", "Attachment"], ["record_id", 1], ["blob_id", 4], ["created_at", "2021-01-22 16:20:03.736870"]]
D, [2021-01-22T16:20:03.739022 #498] DEBUG -- : Attachment Update (0.3ms) UPDATE "attachments" SET "updated_at" = $1 WHERE "attachments"."id" = $2 [["updated_at", "2021-01-22 16:20:03.737884"], ["id", 1]]
D, [2021-01-22T16:20:03.740233 #498] DEBUG -- : (1.1ms) COMMIT
I, [2021-01-22T16:20:03.740753 #498] INFO -- : Disk Storage (0.0ms) Deleted file from key: uk44hg6aeqgkijnoti7625kmymn5
I, [2021-01-22T16:20:03.740868 #498] INFO -- : Disk Storage (0.5ms) Uploaded file to key: uk44hg6aeqgkijnoti7625kmymn5 (checksum: fleS+FPvNcLEHaUysUgaGQ==)
Traceback (most recent call last):
1: from (irb):1
ActiveStorage::IntegrityError (ActiveStorage::IntegrityError)
This issue, however, isn't seen when using the following method of attaching a file.
irb(main):001:0> attachment = Attachment.new
=> #<Attachment id: nil, created_at: nil, updated_at: nil, parent_type: nil, parent_id: nil, frame: "{}", user_id: nil>
irb(main):002:0> attachment.file.attach(io: File.open(Rails.root + 'test/fixtures/files/tracer1.jpg'), filename: 'tracer1.jpg', content_type: 'image/jpg')
=> #<ActiveStorage::Attached::Changes::CreateOne:0x0000563b16d6bdc8 #name="file", #record=#<Attachment id: nil, created_at: nil, updated_at: nil, parent_type: nil, parent_id: nil, frame: "{}", user_id: nil>, #attachable={:io=>#<File:/app/test/fixtures/files/tracer1.jpg>, :filename=>"tracer1.jpg", :content_type=>"image/jpg"}>
irb(main):003:0> attachment.save
D, [2021-01-22T16:21:55.564371 #516] DEBUG -- : (0.2ms) BEGIN
D, [2021-01-22T16:21:55.610210 #516] DEBUG -- : Attachment Create (0.5ms) INSERT INTO "attachments" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2021-01-22 16:21:55.605710"], ["updated_at", "2021-01-22 16:21:55.605710"]]
D, [2021-01-22T16:21:55.615088 #516] DEBUG -- : ActiveStorage::Attachment Load (0.4ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = $1 AND "active_storage_attachments"."record_type" = $2 AND "active_storage_attachments"."name" = $3 LIMIT $4 [["record_id", 2], ["record_type", "Attachment"], ["name", "file"], ["LIMIT", 1]]
D, [2021-01-22T16:21:55.617341 #516] DEBUG -- : ActiveStorage::Blob Create (0.6ms) INSERT INTO "active_storage_blobs" ("key", "filename", "content_type", "metadata", "byte_size", "checksum", "created_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["key", "hjmhqkujbe2uxk6f9jfgmq5j4nn7"], ["filename", "tracer1.jpg"], ["content_type", "image/jpeg"], ["metadata", "{\"identified\":true}"], ["byte_size", 71843], ["checksum", "fleS+FPvNcLEHaUysUgaGQ=="], ["created_at", "2021-01-22 16:21:55.615787"]]
D, [2021-01-22T16:21:55.618972 #516] DEBUG -- : ActiveStorage::Attachment Create (0.7ms) INSERT INTO "active_storage_attachments" ("name", "record_type", "record_id", "blob_id", "created_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["name", "file"], ["record_type", "Attachment"], ["record_id", 2], ["blob_id", 5], ["created_at", "2021-01-22 16:21:55.617781"]]
D, [2021-01-22T16:21:55.621752 #516] DEBUG -- : Attachment Update (0.5ms) UPDATE "attachments" SET "updated_at" = $1 WHERE "attachments"."id" = $2 [["updated_at", "2021-01-22 16:21:55.619356"], ["id", 2]]
D, [2021-01-22T16:21:55.627906 #516] DEBUG -- : (6.0ms) COMMIT
I, [2021-01-22T16:21:55.628651 #516] INFO -- : Disk Storage (0.4ms) Uploaded file to key: hjmhqkujbe2uxk6f9jfgmq5j4nn7 (checksum: fleS+FPvNcLEHaUysUgaGQ==)
I, [2021-01-22T16:21:55.632122 #516] INFO -- : Enqueued ActiveStorage::AnalyzeJob (Job ID: 5e869e72-e190-4a73-8938-14db177822a0) to Async(active_storage_analysis) with arguments: #<GlobalID:0x0000563b18c40938 #uri=#<URI::GID gid://cosplay/ActiveStorage::Blob/5>>
=> true
irb(main):004:0> D, [2021-01-22T16:21:55.691199 #516] DEBUG -- : ActiveStorage::Blob Load (0.3ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = $1 LIMIT $2 [["id", 5], ["LIMIT", 1]]
I, [2021-01-22T16:21:55.691873 #516] INFO -- : Performing ActiveStorage::AnalyzeJob (Job ID: 5e869e72-e190-4a73-8938-14db177822a0) from Async(active_storage_analysis) enqueued at 2021-01-22T16:21:55Z with arguments: #<GlobalID:0x0000563b1947abf8 #uri=#<URI::GID gid://cosplay/ActiveStorage::Blob/5>>
I, [2021-01-22T16:21:55.797208 #516] INFO -- : Disk Storage (0.1ms) Downloaded file from key: hjmhqkujbe2uxk6f9jfgmq5j4nn7
D, [2021-01-22T16:21:55.845133 #516] DEBUG -- : (0.4ms) BEGIN
D, [2021-01-22T16:21:55.845853 #516] DEBUG -- : ActiveStorage::Blob Update (0.5ms) UPDATE "active_storage_blobs" SET "metadata" = $1 WHERE "active_storage_blobs"."id" = $2 [["metadata", "{\"identified\":true,\"width\":575,\"height\":862,\"analyzed\":true}"], ["id", 5]]
D, [2021-01-22T16:21:55.847209 #516] DEBUG -- : (0.9ms) COMMIT
I, [2021-01-22T16:21:55.847513 #516] INFO -- : Performed ActiveStorage::AnalyzeJob (Job ID: 5e869e72-e190-4a73-8938-14db177822a0) from Async(active_storage_analysis) in 155.55ms
Here's the model used in the above 2 examples.
class Attachment < ApplicationRecord
has_one_attached :file, dependent: :destroy
end
I really appreciate any help or insight anyone out there has on this issue; I essentially have a very large test suite which uses fixture_file_upload & Rack::Test::UploadedFile pretty much everywhere as they are very useful, however, as you can see they are not working anymore in combination with ActiveStorage.
Here are my Gemfile & Gemfile.lock if it helps debug what's going on; I've also included a minitest test file on that gist which has 2 failing and 1 succeeding test. I am happy to provide any additional details if it helps debug the issue.
Additional details which could be helpful:
Docker version 20.10.2, build 2291f61
docker-compose version 1.25.5, build unknown
I have the same problem, I know it's not the best solution, but it may work for you:
FactoryBot.define do
factory :user do
full_name { FFaker::NameBR.name }
email { FFaker::Internet.unique.email }
trait :with_avatar_image do
after(:build) do |user|
user.avatar_image.attach(io: File.open('public/examples/my_image.jpg'), filename: 'my_image.jpg')
end
end
end
end
So create this way:
let!(:user) { create(:user, :with_avatar_image) }
In my case, with params like this works:
Attachment.create(file: Rack::Test::UploadedFile.new(Rails.root.join('test', 'fixtures', 'files', 'test.jpg'), 'image/jpg'))
For tests, you may try this:
# Step 1, test_helper.rb
FactoryBot::SyntaxRunner.class_eval do
# If you want to use `fixture_file_upload` with Rails 6.0
include ActionDispatch::TestProcess
# You may need this to use `fixture_file_upload` with Rails 6.1
include ActiveSupport::Testing::FileFixtures
end
# Step 2, attachments.rb
factory :attachment do
name { 'name' }
# As a must have attribute
file {
fixture_file_upload(
Rails.root.join('test', 'fixtures', 'files', 'test.jpg'), 'image/jpg')
}
# As an optional attribute
trait :with_file do
file {
fixture_file_upload(
Rails.root.join('test', 'fixtures', 'files', 'test.jpg'), 'image/jpg')
}
end
end
# You could replace `fixture_file_upload` with `Rack::Test::UploadedFile.new`
# Step 3, now you can use:
# As a must have attribute
attachment1 = create(:attachment)
attributes1 = attributes_for(:attachment)
# As an optional attribute
attachment2 = create(:attachment, :with_file)
attributes2 = attributes_for(:attachment, :with_file)
I have an instance of a model which I'm playing with in my console. The instance is called mz.
irb(main):002:0> mz.updated_at
=> Fri, 24 Apr 2020 14:01:38 UTC +00:00
irb(main):003:0> mz.created_at
=> Fri, 24 Apr 2020 14:01:38 UTC +00:00
irb(main):004:0> mz.created_at == mz.updated_at
=> false
Why is this the case?
It looks to me like it should return true.
(I am trying to solve this problem for a non abstract coding problem, but best to describe it this way I think.)
Update #1...
irb(main):003:0> m.updated_at.to_i
=> 1587741257
irb(main):004:0> m.created_at.to_i
=> 1587741257
irb(main):005:0> m.updated_at == m.created_at
=> false
Confused? I still am.
Update #2 re #DennisvandeHoef
irb(main):002:0> m.updated_at.to_i
=> 1587741257
irb(main):003:0> m.created_at.to_i
=> 1587741257
irb(main):004:0> m.updated_at = m.created_at
=> Fri, 24 Apr 2020 15:14:17 UTC +00:00
irb(main):005:0> m.save(touch: false)
(0.2ms) BEGIN
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 14], ["LIMIT", 1]]
Tlk Load (0.4ms) SELECT "tlks".* FROM "tlks" WHERE "tlks"."id" = $1 LIMIT $2 [["id", 48], ["LIMIT", 1]]
Spkr Load (0.4ms) SELECT "spkrs".* FROM "spkrs" WHERE "spkrs"."id" = $1 LIMIT $2 [["id", 65], ["LIMIT", 1]]
ActionText::RichText Load (0.5ms) SELECT "action_text_rich_texts".* FROM "action_text_rich_texts" WHERE "action_text_rich_texts"."record_id" = $1 AND "action_text_rich_texts"."record_type" = $2 AND "action_text_rich_texts"."name" = $3 LIMIT $4 [["record_id", 74], ["record_type", "Msg"], ["name", "safe_content"], ["LIMIT", 1]]
Msg Update (0.6ms) UPDATE "msgs" SET "updated_at" = $1 WHERE "msgs"."id" = $2 [["updated_at", "2020-04-24 15:14:17.833380"], ["id", 74]]
(6.4ms) COMMIT
=> true
irb(main):006:0> m.updated_at == m.created_at
=> true
Interesting that it works, but I have no idea why it would be different! Any thoughts?
I'm building a GraphQL API with Ruby on Rails and the graphql gem. Now I have some n:m relations, like Projects have many Users and Users have many Projects. My models are like:
# /app/models/project.rb
has_many :project_assignments
has_many :project_managers, through: :project_assignments, source: :user
# /app/models/project_assignment.rb
belongs_to :project
belongs_to :user
# /app/models/user.rb
has_many :project_assignments
has_many :projects, through: :project_assignments
Now I want to query all projects and their corresponding project managers with a query like this:
query {
projects {
edges {
node {
id
projectManagers {
edges {
node {
id
}
}
}
}
}
}
}
And my resolvers are basically like Project.all and each Project calls project.projectManagers, which results in hundreds of queries:
Project Load (3.3ms) SELECT "projects".* FROM "projects"
User Load (1.5ms) SELECT "users".* FROM "users" INNER JOIN "project_assignments" ON "users"."id" = "project_assignments"."user_id" WHERE "project_assignments"."project_id" = $1 [["project_id", 2]]
User Load (0.7ms) SELECT "users".* FROM "users" INNER JOIN "project_assignments" ON "users"."id" = "project_assignments"."user_id" WHERE "project_assignments"."project_id" = $1 [["project_id", 3]]
User Load (1.1ms) SELECT "users".* FROM "users" INNER JOIN "project_assignments" ON "users"."id" = "project_assignments"."user_id" WHERE "project_assignments"."project_id" = $1 [["project_id", 4]]
User Load (1.0ms) SELECT "users".* FROM "users" INNER JOIN "project_assignments" ON "users"."id" = "project_assignments"."user_id" WHERE "project_assignments"."project_id" = $1 [["project_id", 5]]
User Load (0.8ms) SELECT "users".* FROM "users" INNER JOIN "project_assignments" ON "users"."id" = "project_assignments"."user_id" WHERE "project_assignments"."project_id" = $1 [["project_id", 6]]
...
I've added the bullet gem, but there is no warning about a missing eager loading. In fact, If I use Project.all.includes(:project_managers), I get the query that I want (SELECT "project_assignments".* FROM "project_assignments" WHERE "project_assignments"."project_id" IN ($1, $2, $3, $4, $5, $6, $7, $8, ...)), but the User queries fires anyhow:
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" IN ($1, $2, $3) [["id", 3], ["id", 2], ["id", 1]]
User Load (0.8ms) SELECT "users".* FROM "users" INNER JOIN "project_assignments" ON "users"."id" = "project_assignments"."user_id" WHERE "project_assignments"."project_id" = $1 [["project_id", 2]]
User Load (0.9ms) SELECT "users".* FROM "users" INNER JOIN "project_assignments" ON "users"."id" = "project_assignments"."user_id" WHERE "project_assignments"."project_id" = $1 [["project_id", 3]]
User Load (0.8ms) SELECT "users".* FROM "users" INNER JOIN "project_assignments" ON "users"."id" = "project_assignments"."user_id" WHERE "project_assignments"."project_id" = $1 [["project_id", 4]]
User Load (0.7ms) SELECT "users".* FROM "users" INNER JOIN "project_assignments" ON "users"."id" = "project_assignments"."user_id" WHERE "project_assignments"."project_id" = $1 [["project_id", 5]]
User Load (0.7ms) SELECT "users".* FROM "users" INNER JOIN "project_assignments" ON "users"."id" = "project_assignments"."user_id" WHERE "project_assignments"."project_id" = $1 [["project_id", 6]]
...
Is there anything that I can do the preload the users?
I tried eager_load also, but the result is basically the same (tried another example with an normal has_many association (no :through):
SQL (1.3ms) SELECT "projects"."id" AS t0_r0, "projects"."title" AS t0_r1, "projects"."number" AS t0_r2, "projects"."description" AS t0_r3, "projects"."deadline" AS t0_r4, "projects"."archived" AS t0_r5, "projects"."customer_id" AS t0_r6, "projects"."rate_type" AS t0_r7, "projects"."daily_rate" AS t0_r8, "projects"."service_rates" AS t0_r9, "projects"."budget_type" AS t0_r10, "projects"."budget_rate" AS t0_r11, "projects"."created_at" AS t0_r12, "projects"."updated_at" AS t0_r13, "projects"."status" AS t0_r14, "projects"."slug" AS t0_r15, "project_labels"."id" AS t1_r0, "project_labels"."title" AS t1_r1, "project_labels"."description" AS t1_r2, "project_labels"."color" AS t1_r3, "project_labels"."project_id" AS t1_r4, "project_labels"."created_at" AS t1_r5, "project_labels"."updated_at" AS t1_r6 FROM "projects" LEFT OUTER JOIN "project_labels" ON "project_labels"."project_id" = "projects"."id" WHERE "projects"."id" IN ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) [["id", 1], ["id", 2], ["id", 3], ["id", 4], ["id", 5], ["id", 6], ["id", 7], ["id", 8], ["id", 9], ["id", 10]]
ProjectLabel Load (0.3ms) SELECT "project_labels".* FROM "project_labels" WHERE "project_labels"."project_id" = $1 [["project_id", 10]]
ProjectLabel Load (0.5ms) SELECT "project_labels".* FROM "project_labels" WHERE "project_labels"."project_id" = $1 [["project_id", 2]]
ProjectLabel Load (0.7ms) SELECT "project_labels".* FROM "project_labels" WHERE "project_labels"."project_id" = $1 [["project_id", 5]]
ProjectLabel Load (0.5ms) SELECT "project_labels".* FROM "project_labels" WHERE "project_labels"."project_id" = $1 [["project_id", 8]]
ProjectLabel Load (0.5ms) SELECT "project_labels".* FROM "project_labels" WHERE "project_labels"."project_id" = $1 [["project_id", 6]]
ProjectLabel Load (0.6ms) SELECT "project_labels".* FROM "project_labels" WHERE "project_labels"."project_id" = $1 [["project_id", 4]]
ProjectLabel Load (0.4ms) SELECT "project_labels".* FROM "project_labels" WHERE "project_labels"."project_id" = $1 [["project_id", 1]]
ProjectLabel Load (0.3ms) SELECT "project_labels".* FROM "project_labels" WHERE "project_labels"."project_id" = $1 [["project_id", 3]]
ProjectLabel Load (0.3ms) SELECT "project_labels".* FROM "project_labels" WHERE "project_labels"."project_id" = $1 [["project_id", 9]]
ProjectLabel Load (0.5ms) SELECT "project_labels".* FROM "project_labels" WHERE "project_labels"."project_id" = $1 [["project_id", 7]]
You can do all sorts of things with has_many including includes which should help with N+1 queries
has_many :project_assignments, -> { includes(:projects) }
Project.all.includes(:project_managers)
# Project.includes(:project_managers) # shorthand of above
... would include project_managers automatically in the SQL depending on the query.
To also include project_assignment.user, then just merge them:
Project.includes(:project_managers, project_assignments: :user)
# probably below is equivalent of above (but not sure)
# just because `project_managers` association is also going "through" :project_assignments
Project.includes(project_assignments: :user)
See "Loading nested relationships" here in the docs
I am using the actsastaggableon gem. For some reason, the system is saving the tag "Python" as "python (lowercase)". Since i am validating that users can only enter certain tags, the system saving the tag as "python" is causing some problems. Below are my server logs. The first line is a puts statement of the tag_list after all the validations have run (it passes). Then after that the server is doing something strange and turning "Python" to "python". This may have something to do with caching as I used to have a tag called "python" but I no longer do. How do I fix this without seriously changing my cache settings?
["IOS | IPhone | IPad", "App and Web development", "PHP", "Rails", "Python"]
ActsAsTaggableOn::Tag Load (0.8ms) SELECT "tags".* FROM "tags" WHERE (lower(name) = 'ios | iphone | ipad' OR lower(name) = 'app and web development' OR lower(name) = 'php' OR lower(name) = 'rails' OR lower(name) = 'python')
ActsAsTaggableOn::Tag Load (0.8ms) SELECT "tags".* FROM "tags" WHERE (lower(name) = 'ios | iphone | ipad' OR lower(name) = 'app and web development' OR lower(name) = 'php' OR lower(name) = 'rails' OR lower(name) = 'python')
CACHE (0.0ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND (taggings.context = 'tags' AND taggings.tagger_id IS NULL) [["taggable_id", 16], ["taggable_type", "Profile"]]
CACHE (0.0ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND (taggings.context = 'tags' AND taggings.tagger_id IS NULL) [["taggable_id", 16], ["taggable_type", "Profile"]]
ActsAsTaggableOn::Tagging Exists (0.6ms) SELECT 1 AS one FROM "taggings" WHERE ("taggings"."tag_id" = 1 AND "taggings"."taggable_type" = 'Profile' AND "taggings"."taggable_id" = 16 AND "taggings"."context" = 'tags' AND "taggings"."tagger_id" IS NULL AND "taggings"."tagger_type" IS NULL) LIMIT 1
ActsAsTaggableOn::Tagging Exists (0.6ms) SELECT 1 AS one FROM "taggings" WHERE ("taggings"."tag_id" = 1 AND "taggings"."taggable_type" = 'Profile' AND "taggings"."taggable_id" = 16 AND "taggings"."context" = 'tags' AND "taggings"."tagger_id" IS NULL AND "taggings"."tagger_type" IS NULL) LIMIT 1
SQL (3.8ms) INSERT INTO "taggings" ("context", "created_at", "tag_id", "taggable_id", "taggable_type") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["context", "tags"], ["created_at", Tue, 25 Mar 2014 16:05:41 EDT -04:00], ["tag_id", 1], ["taggable_id", 16], ["taggable_type", "Profile"]]
SQL (3.8ms) INSERT INTO "taggings" ("context", "created_at", "tag_id", "taggable_id", "taggable_type") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["context", "tags"], ["created_at", Tue, 25 Mar 2014 16:05:41 EDT -04:00], ["tag_id", 1], ["taggable_id", 16], ["taggable_type", "Profile"]]
Have you set this somewhere:
ActsAsTaggableOn.force_lowercase = true
If so that is forcing lowercase
If you don't have that set, another possible problem can be if you are using mysql for db that can be found here:
https://github.com/mbleigh/acts-as-taggable-on/issues/259
class EditTagTableToBeCaseSensitive < ActiveRecord::Migration
def up
#sql = "ALTER TABLE `tags` CHANGE `name` `name` VARCHAR(255) BINARY DEFAULT NULL;"
execute #sql
end
def down
#sql = "ALTER TABLE `tags` CHANGE `name` `name` VARCHAR(255) DEFAULT NULL;"
execute #sql
end
end
I'm using:
ranking = Ranking.create()
ranking.send("#{month}=", rank)
ranking.save!
I'd like to append whatever value is in the #{month} column, not replace it. For example, if I am performing:
month = 'january'
ranking.send("#{month}=", 500)
ranking.save!
And then again later on:
month = 'january'
ranking.send("#{month}=", 250)
ranking.save!
The value for the column january for that particular ranking should be 750.
Is this possible with the current ActiveRecord API?
You could do this with increment! method
month = 'january'
ranking.increment!(month, 250)
updated:
to proof comments question (e.g. month = 'jan'):
irb(main):011:0> p.increment!(month, 70)
(0.0ms) begin transaction
SQL (0.0ms) UPDATE "products" SET "jan" = ?, "updated_at" = ? WHERE "product
"."id" = 1 [["jan", 171], ["updated_at", Sun, 06 Oct 2013 04:23:54 UTC +00:00]
(0.0ms) commit transaction
=> true
irb(main):012:0> p
=> #<Product id: 1, name: nil, description: nil, jan: 171, created_at: "2013-10-
06 04:22:50", updated_at: "2013-10-06 04:23:54">
and another case
irb(main):013:0> p.increment!("#{month}", 70)
(0.0ms) begin transaction
SQL (0.0ms) UPDATE "products" SET "jan" = ?, "updated_at" = ? WHERE "products
"."id" = 1 [["jan", 241], ["updated_at", Sun, 06 Oct 2013 04:24:10 UTC +00:00]]
(0.0ms) commit transaction
=> true
irb(main):014:0> p
=> #<Product id: 1, name: nil, description: nil, jan: 241, created_at: "2013-10-
06 04:22:50", updated_at: "2013-10-06 04:24:10">