fixture_file_upload & Rack::Test::UploadedFile - ActiveStorage::IntegrityError - ruby-on-rails
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)
Related
Strange Rails ActiveRecord Behavior
Can someone please explain why the following queries return diff results? If I run a simple "last" query I get an object back. >> j = Job.last (1.6ms) SELECT sqlite_version(*) Job Load (0.7ms) SELECT "jobs".* FROM "jobs" ORDER BY "jobs"."id" DESC LIMIT ? [["LIMIT", 1]] => #<Job id: 12, customer_id: 3, description: nil, shoot_start_date: "2020-11-25 00:00:00", shoot_end_date: "2020-11-26 00:00:00", submission_deadline: "2020-11-27 00:00:00", delivery_deadline: "2020-11-28 00:00:00", created_at: "2020-11-25 21:44:22", updated_at: "2020-12-14 19:30:06", token: "fd2356c1-996b-4f95-b24a-8c92829af1fe", name: "teesting"> And with this object I can get children as follows: >> j.job_entries JobEntry Load (0.7ms) SELECT "job_entries".* FROM "job_entries" WHERE "job_entries"."job_id" = ? LIMIT ? [["job_id", 12], ["LIMIT", 11]] => #<ActiveRecord::Associations::CollectionProxy [#<JobEntry id: 8, entity_id: 12, agency_id: 35, created_at: "2020-12-07 21:27:47", updated_at: "2020-12-07 21:27:47", job_id: 12, job_role_id: 8>, #<JobEntry id: 9, entity_id: 13, agency_id: 35, created_at: "2020-12-14 17:35:30", updated_at: "2020-12-14 17:35:30", job_id: 12, job_role_id: 7>]> HOWEVER, when I run a method on my object which is the following code: def self.getJobAndSubmissions(token) Job.includes(job_entries: :images_attachments).where(:token => token) end I get the very same record with attachments: >> j = Job.getJobAndSubmissions('fd2356c1-996b-4f95-b24a-8c92829af1fe') Job Load (0.9ms) SELECT "jobs".* FROM "jobs" WHERE "jobs"."token" = ? LIMIT ? [["token", "fd2356c1-996b-4f95-b24a-8c92829af1fe"], ["LIMIT", 11]] JobEntry Load (0.2ms) SELECT "job_entries".* FROM "job_entries" WHERE "job_entries"."job_id" = ? [["job_id", 12]] ActiveStorage::Attachment Load (1.0ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? AND "active_storage_attachments"."record_id" IN (?, ?) [["record_type", "JobEntry"], ["name", "images"], ["record_id", 8], ["record_id", 9]] => #<ActiveRecord::Relation [#<Job id: 12, customer_id: 3, description: nil, shoot_start_date: "2020-11-25 00:00:00", shoot_end_date: "2020-11-26 00:00:00", submission_deadline: "2020-11-27 00:00:00", delivery_deadline: "2020-11-28 00:00:00", created_at: "2020-11-25 21:44:22", updated_at: "2020-12-14 19:30:06", token: "fd2356c1-996b- 4f95-b24a-8c92829af1fe", name: "teesting">]> But suddenly, child references no longer work. >> j.job_entries Traceback (most recent call last): 1: from (irb):4 Job Load (0.2ms) SELECT "jobs".* FROM "jobs" WHERE "jobs"."token" = ? LIMIT ? [["token", "fd2356c1-996b-4f95-b24a-8c92829af1fe"], ["LIMIT", 11]] JobEntry Load (0.1ms) SELECT "job_entries".* FROM "job_entries" WHERE "job_entries"."job_id" = ? [["job_id", 12]] ActiveStorage::Attachment Load (0.2ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? AND "active_storage_attachments"."record_id" IN (?, ?) [["record_type", "JobEntry"], ["name", "images"], ["record_id", 8], ["record_id", 9]] NoMethodError (undefined method `job_entries' for #. <Job::ActiveRecord_Relation:0x00005562db1258c0>) Did you mean? entries What the? Please help me understand why this is happening!
Job.last will return an ActiveRecord object. Job.includes(job_entries: :images_attachments).where(:token => token) returns an ActiveRecord::Relation which means you can't call job_entries on it. You can get an object with this code # These do the same thing Job.find_by_token(token) Job.find_by(token: token)
NoMethodError (undefined method `job_entries' for #. <Job::ActiveRecord_Relation:0x00005562db1258c0>) Note the error message is not for Job but for a Job::ActiveRecord_Relation. #last returns a single Job. #where returns a set of Jobs stored in an ActiveRecord::Relation. Job::ActiveRecord_Relation is a relation specific to Job. You can also see this in the returned value... >> j = Job.getJobAndSubmissions('fd2356c1-996b-4f95-b24a-8c92829af1fe') ... => #<ActiveRecord::Relation [#<Job id: 12, ...]>
Why does instance.created_at == instance.updated_at return 'false' when an object has never been updated?
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?
Rails ActiveStorage - has_on_attached/has_many_attached associations is load by default
I got a problem with ActiveStorage, Currently I have has_on_attachedand has_many_attached relation on my Model Every time I call my model it loads the relation as below: ActiveStorage::Attachment Load (4.2ms) 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", 4934], ["record_type", "User"], ["name", "profile_picture"], ["LIMIT", 1]] ActiveStorage::Attachment Exists (0.9ms) SELECT 1 AS one 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", 4934], ["record_type", "User"], ["name", "home_pictures"], ["LIMIT", 1]] How can I disable this behaviour by default ?
You can use Model.with_attached_images.find(:id) to avoid the N+1 https://github.com/rails/rails/tree/master/activestorage#examples I'm not sure if you can disable eager loading the attachments, but the above should help clean up a little bit.
acts_As_taggabe_on changing case of tags - possibly caching issue but not sure
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
Loop in Ruby on Rails running twice
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