Related
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, ...]>
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?
Here I have 2 models Branch and Subject which have many to many relationship through subjectgroup
The console shows the following result
~/workspace (master) $ rails c
Running via Spring preloader in process 4541
Loading development environment (Rails 4.2.7.1)
irb: warn: can't alias context from irb_context.
2.3.0 :001 > s=Subject.first
Subject Load (0.6ms) SELECT "subjects".* FROM "subjects" ORDER BY "subjects"."id" ASC LIMIT 1
=> #<Subject id: 1, idx_id: nil, fullname: "\tSubject1\t", created_at: "2017-05-06 23:06:32", updated_at: "2017-05-06 23:06:32">
2.3.0 :002 > s.branches.first
Branch Load (0.9ms) SELECT "branches".* FROM "branches" INNER JOIN"subjectgroups" ON "branches"."id" = "subjectgroups"."branch_id" WHERE"subjectgroups"."subject_id" = $1 ORDER BY "branches"."id" ASC LIMIT 1 [["subject_id", 1]]
=> #<Branch id: 1, name: "\Branch1\t", created_at: "2017-05-06 23:06:32", updated_at: "2017-05-06 23:06:32">
2.3.0 :003 > s.branches.find(2)
Branch Load (0.6ms) SELECT "branches".* FROM "branches" INNER JOIN "subjectgroups" ON "branches"."id" = "subjectgroups"."branch_id" WHERE "subjectgroups"."subject_id" = $1 AND "branches"."id" = $2 LIMIT 1 [["subject_id", 1], ["id", 2]]
=> #<Branch id: 2, name: "\tBranch2\t", created_at: "2017-05-06 23:06:32", updated_at: "2017-05-06 23:06:32">
2.3.0 :004 > s.branches.first.name
Branch Load (0.7ms) SELECT "branches".* FROM "branches" INNER JOIN "subjectgroups" ON "branches"."id" = "subjectgroups"."branch_id" WHERE "subjectgroups"."subject_id" = $1 ORDER BY "branches"."id" ASC LIMIT 1 [["subject_id", 1]]
=> "\tBranch1\t"
2.3.0 :005 > s.branches.find(2).name
Branch Load (0.7ms) SELECT "branches".* FROM "branches" INNER JOIN "subjectgroups" ON "branches"."id" = "subjectgroups"."branch_id" WHERE "subjectgroups"."subject_id" = $1 AND "branches"."id" = $2 LIMIT 1 [["subject_id", 1], ["id", 2]]
=> "\tBranch2\t"
2.3.0 :006 > s.branches.each do |branch|
2.3.0 :007 > branch.name
2.3.0 :008?> end
Branch Load (0.5ms) SELECT "branches".* FROM "branches" INNER JOIN "subjectgroups" ON "branches"."id" = "subjectgroups"."branch_id" WHERE "subjectgroups"."subject_id" = $1 [["subject_id", 1]]
=> [#<Branch id: 1, name: "\tBranch1\t", created_at: "2017-05-06 23:06:32", updated_at: "2017-05-06 23:06:32">, #<Branch id: 2, name: "\tBranch2\t", created_at: "2017-05-06 23:06:32", updated_at: "2017-05-06 23:06:32">]
2.3.0 :009 >
What should I do to make the result like
=> "\tBranch1\t" "\tBranch2\t"
you can try following code:
-It will print all branch names
s.branches.each do |branch|
puts branch.name
end
-It will return the names in array
s.branches.map(&:name)
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
See the following output:
1.9.3p194 :001 > player = Player.randomize_for_market
=> #<Player id: nil, name: "Gale Bridges", age: 19, energy: 100, attack: 6, defense: 4, stamina: 5, goal_keeping: 3, power: 4, accuracy: 5, speed: 5, short_pass: 5, ball_controll: 4, long_pass: 6, regain_ball: 5, contract_id: nil, created_at: nil, updated_at: nil>
1.9.3p194 :002 > player.save!
(0.2ms) BEGIN
SQL (20.5ms) INSERT INTO "players" ("accuracy", "age", "attack", "ball_controll", "contract_id", "created_at", "defense", "energy", "goal_keeping", "long_pass", "name", "power", "regain_ball", "short_pass", "speed", "stamina", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17) RETURNING "id" [["accuracy", 5], ["age", 19], ["attack", 6], ["ball_controll", 4], ["contract_id", nil], ["created_at", Fri, 29 Jun 2012 04:02:34 UTC +00:00], ["defense", 4], ["energy", 100], ["goal_keeping", 3], ["long_pass", 6], ["name", "Gale Bridges"], ["power", 4], ["regain_ball", 5], ["short_pass", 5], ["speed", 5], ["stamina", 5], ["updated_at", Fri, 29 Jun 2012 04:02:34 UTC +00:00]]
(16.6ms) COMMIT
=> true
1.9.3p194 :003 > YAML::load(YAML::dump(Player.randomize_for_market)).save!
(0.2ms) BEGIN
(0.2ms) COMMIT
=> true
Why this happens and how can I avoid it?
There is no ((before|after)+(save|create|commit)) on the model. I'm using rails 3.2.
Table "public.players"
Column | Type | Modifiers
--------------+-----------------------------+------------------------------------------------------
id | integer | not null default nextval('players_id_seq'::regclass)
name | character varying(255) | not null
age | integer | not null
energy | integer | not null
attack | integer | not null
defense | integer | not null
stamina | integer | not null
goal_keeping | integer | not null
power | integer | not null
accuracy | integer | not null
speed | integer | not null
short_pass | integer | not null
ball_controll | integer | not null
long_pass | integer | not null
regain_ball | integer | not null
contract_id | integer |
created_at | timestamp without time zone | not null
updated_at | timestamp without time zone | not null
Indexes:
"players_pkey" PRIMARY KEY, btree (id)
Edit: Answering "Why do you expect YAML::load(YAML::dump(Player.randomize_for_market)).save! to do anything?"
Because it serializes a object and recovers it?
example:
1.9.3p194 :006 > p = Player.randomize_for_market
=> #<Player id: nil, name: "Vincenzo Allen", age: 23, energy: 100, attack: 2, defense: 8, stamina: 6, goal_keeping: 3, power: 5, accuracy: 6, speed: 5, short_pass: 6, ball_controll: 5, long_pass: 6, regain_ball: 5, contract_id: nil, created_at: nil, updated_at: nil>
1.9.3p194 :007 > p
=> #<Player id: nil, name: "Vincenzo Allen", age: 23, energy: 100, attack: 2, defense: 8, stamina: 6, goal_keeping: 3, power: 5, accuracy: 6, speed: 5, short_pass: 6, ball_controll: 5, long_pass: 6, regain_ball: 5, contract_id: nil, created_at: nil, updated_at: nil>
1.9.3p194 :008 > YAML::load(YAML::dump(p))
=> #<Player id: nil, name: "Vincenzo Allen", age: 23, energy: 100, attack: 2, defense: 8, stamina: 6, goal_keeping: 3, power: 5, accuracy: 6, speed: 5, short_pass: 6, ball_controll: 5, long_pass: 6, regain_ball: 5, contract_id: nil, created_at: nil, updated_at: nil>
Note that the return of p is the same of the return from YAML::load
This may help to answer your question:
:001 > article = Article.new
#<Article:0x102d16b10> { ... }
:002 > article.persisted?
false
:003 > dumped = YAML::dump(article)
"--- !ruby/object:Article ... "
:004 > loaded = YAML::load(dumped)
#<Article:0x102cf5500> { ... }
:005 > loaded.persisted?
true
Looking into the Rails source code for ActiveRecord::Base#persisted?:
def persisted?
!(new_record? || destroyed?)
end
And for ActiveRecord::Base#new_record?:
def new_record?
#new_record
end
The #new_record instance variable is not saved when you dump the object to Yaml, and therefore it's nil when you load the object from Yaml. So ActiveRecord thinks it's already been persisted to the database and doesn't attempt to save it.
Brandan's answer is very relevant, the object de-serialized from YAML thinks it's already been persisted. Assuming #loaded_obj is the object you loaded from YAML (the object you want to save), try #loaded_obj.dup.save