Rails Column in Schema but not Showing Up in Console - ruby-on-rails

I recently ran a migration to add a "Rank" column as a float to a model called jokes (it's a reddit-type page on the app). It shows up in my schema, which means to me that the migration was successful, but when I try to use it to order things via the controller or when I look for that column in my rails console I don't see it.
Here's an example of the controller ordering that doesn't work:
#jokes = Joke.where(kids: true, approved: true).order("rank DESC")
And here's the console output which neglects the new "rank" column:
[54] pry(main)> Joke.last
Joke Load (4.7ms) SELECT "jokes".* FROM "jokes" ORDER BY "jokes"."id" DESC LIMIT 1
=> #<Joke:0x007fb52f927e58
id: 16,
title: "Test Joke",
body: "Tested",
kids: false,
mixed: false,
approved: true,
rejected: nil,
user_id: 1,
created_at: Sat, 13 Aug 2016 19:40:14 UTC +00:00,
updated_at: Sat, 13 Aug 2016 19:40:18 UTC +00:00>
Can anyone help me figure out what's going on here?

Related

Rails - How to query multiple arrays of hashes in Active Records

I am working on a Ruby on Rails project and I have several tasks with this structure in a Postgresql database :
id: 8,
name: "Task 1",
due_date: Mon, 25 Jul 2022,
finished: true,
reviewed: false,
note: nil,
tags: [{"id"=>6, "name"=>"tag_1"}, {"id"=>7, "name"=>"tag_2"}],
assigned_to: [{"id"=>7, "username"=>"Julia"}, {"id"=>8, "username"=>"Joe"}],
user_id: 5,
group_id: 4,
created_at: Sat, 06 Aug 2022 01:09:31.135203000 UTC +00:00,
updated_at: Sat, 06 Aug 2022 01:09:31.135203000 UTC +00:00,
pending: false>
And I want to query those tags depending on the the tag id and the assigned_to id.
The column types are:
t.jsonb "tags", default: [], array: true
t.jsonb "assigned_to", default: [], array: true
I checked this source: Query on Postgres JSON array field in Rails
but couldn't figure out how it works, this is what I get:
Task.where("tags::jsonb #> ?", [{"id": 6}, {"id": 7}].to_json)
Task Load (3.8ms) SELECT "tasks".* FROM "tasks" WHERE (tags::jsonb #> '[{"id":6},{"id":7}]')
Task Load (0.9ms) SELECT "tasks".* FROM "tasks" WHERE (tags::jsonb #> '[{"id":6},{"id":7}]') /* loading for inspect */ LIMIT $1 [["LIMIT", 11]]
=> #<Task::ActiveRecord_Relation:0x4290>
Is there a way to query it? Thanks!
You could use JSONB_TO_RECORDSET to extract tasks.tags->'id' and the same way tasks.assigned_to->'id' and have a couple of extra columns you can use for the filtering:
Task
.from('tasks, JSONB_TO_RECORDSET(tasks.tags) AS tags(id int), JSONB_TO_RECORDSET(tasks.tags) AS assigned_to(id int)')
.where('tags.id = ? AND assigned_to.id = ?', 6, 7)
# SELECT "tasks".* FROM JSONB_TO_RECORDSET(tasks.tags) AS tags(id int), JSONB_TO_RECORDSET(tasks.tags) AS assigned_to(id int) WHERE (tags.id = 6 AND assigned_to.id = 7)
Notice the Active Record where won't work using hashes (like where(tags: { id: 6, ... }) as one might intuitively think), so the binding has to be done manually.
Notice this works by using tags and assiged_to as jsonb not jsonb[] as it's in your example. So you might have to remove the array: true argument in your migration.

Rails refuses to add associated record

I have a table with 2 foreign key relationships - to a Timeline and a Phase. When I create a record in my development database it all works 100% as expected, but when I do it in test mode it refuses to add the Timeline - you can see from the INSERT statement that it flatly refuses .. it doesn't even try to add it. When I run the exact same sequence below in development it's fine
I can add/update timeline_id but then it doesn't reference the timeline through the parent phase_timeline object as it should. I repeat that this all works fine in development, but not in test. Its driving me mad. Is it failing a validation possibly.. or could the database be corrupt. Are there some console commands I could run to check out the foreign key relationship further?
[33] pry(main)> t = Timeline.last
Timeline Load (0.3ms) SELECT "timelines".* FROM "timelines" ORDER BY "timelines"."id" DESC LIMIT $1 [["LIMIT", 1]]
=> #<Timeline:0x0055fd716dcfa8 id: 1, title: "England", timelineable_type: "Global", timelineable_id: 1, created_at: Thu, 24 Sep 2020 14:46:28 UTC +00:00, updated_at: Thu, 24 Sep 2020 14:46:28 UTC +00:00>
[34] pry(main)> p = Phase.last
Phase Load (1.3ms) SELECT "phases".* FROM "phases" WHERE "phases"."deleted_at" IS NULL ORDER BY "phases"."id" DESC LIMIT $1 [["LIMIT", 1]]
=> #<Phase:0x0055fd717f8450
id: 1,
name: "First phase",
development_id: 1,
created_at: Thu, 24 Sep 2020 14:46:28 UTC +00:00,
updated_at: Thu, 24 Sep 2020 14:46:28 UTC +00:00,
developer_id: 1,
division_id: 1,
number: 1,
deleted_at: nil,
total_snags: 0,
unresolved_snags: 0,
business: "core">
[35] pry(main)> pt = PhaseTimeline.create(phase: p, timeline: t)
(0.2ms) BEGIN
SQL (0.5ms) **INSERT INTO "phase_timelines" ("phase_id") VALUES ($1) RETURNING "id" [["phase_id", 1]]**
(1.8ms) COMMIT
=> #<PhaseTimeline:0x0055fd719ef9c0 id: 5, phase_id: 1, timeline_id: nil>
After a LOT of head scratching and diving into the bowels .. this problem was caused by having 2 model classes with the same name. The classes were in 2 separate folder but had the same scope and were identical but removing the errant one sorted the problem

weird time_zone EDT vs EST issue with Rails

I have a rails 5 server that is configured to be "Eastern Time (US & Canada)"
The server works great mostly, it stores times in the database in UTC.
For example, if I am in a console and do
Time.zone.now
=> Fri, 27 Oct 2017 15:07:04 EDT -04:00
Which is correct (we have not fall back on time yet)
However if I pull down an active record object:
> s = Schedule.first
Schedule Load (6.2ms) SELECT "schedules".* FROM "schedules" ORDER BY "schedules"."id" ASC LIMIT $1 [["LIMIT", 1]]
=> #<Schedule id: 1, product_id: 1, day: "Monday", start_time: "2000-01-01 22:00:00", end_time: "2000-01-01 23:00:00", size: 25, description: "Grades 3-5", created_at: "2017-08-23 14:16:09", updated_at: "2017-08-23 14:16:09", is_full: false>
2.4.0 :004 > s.start_time
=> Sat, 01 Jan 2000 17:00:00 EST -05:00
As you can see it convert is to Easter Standard time, which is not correct. Is it possible rails is confused or am I doing something wrong?
(using ruby 2.4)
This was user error, the objects date was in EST so Active Record was doing its job, fix was to set it to today and it would be in the right zone.

Why does the .size method not respond with the actual value stored in my counter_cache?

I have a Question model that has_many :answers & # answers_count :integer default(0)
On my Answer model, I have:
belongs_to :question, counter_cache: true
On my Question#Show page though, when showing my Answer#Form partial, I build an instance of an answer to be included in the form like so:
<%= render partial: "answers/form", locals: {answer: #question.answers.build(user: current_user)} %>
Right below that, I display the number of answers currently associated with this question. It should NOT include that unpersisted answer I just built in the form, yet it does.
This is the value of a #question:
[3] pry(#<#<Class:0x007fadab5f4d48>>)> question
=> #<Question:0x007fadab7f3478
id: 51,
title: "Chile loves Mexico A LOT",
body: "5.times do\r\n puts \"*\"\r\nend\r\n\r\nputs \"Chile, Chile, Chile!\"\r\nputs \"Whips Mejico 7 - LOVE\"",
user_id: 1546,
created_at: Mon, 20 Jun 2016 09:05:09 UTC +00:00,
updated_at: Mon, 20 Jun 2016 20:40:23 UTC +00:00,
test_suite: "",
expected_results: "",
language: "ruby",
comments_count: 1,
runnable: false,
answers_count: 0>
When I do various calls, I get different results:
[4] pry(#<#<Class:0x007fadab5f4d48>>)> question.answers.count
CACHE (0.0ms) SELECT COUNT(*) FROM "answers" WHERE "answers"."question_id" = $1 [["question_id", 51]]
=> 0
That gives me the result I want, but it also does a DB-query which I am trying to avoid. The call to size seems to hit the cached value but it gives me the wrong value as you can see below.
[5] pry(#<#<Class:0x007fadab5f4d48>>)> question.answers.size
=> 1
[6] pry(#<#<Class:0x007fadab5f4d48>>)> question.answers_count
=> 0
Shouldn't .size just return what is in answers_count? Why is it not working like I expect? I can always just use answers_count, but I feel like there may be a bigger problem here that I would love to get to the bottom of.

Why doesn't delayed job load my serialized arguments from the DB?

When I schedule my delayed job, I do it in the usual way:
NotificationMailer.delay.notify(self, #current_user)
And if I peek at the object on the Delayed::Job queue (before the worker sees it), I can see my serialized parameter current_user in the handler:
[33] my_project ยป Delayed::Job.first
Delayed::Backend::ActiveRecord::Job Load (0.7ms) SELECT "delayed_jobs".* FROM "delayed_jobs" ORDER BY "delayed_jobs"."id" ASC LIMIT 1
=> #<Delayed::Backend::ActiveRecord::Job:0x0000010d546fb0> {
:id => 764161,
:priority => 0,
:attempts => 0,
:handler => "--- !ruby/object:Delayed::PerformableMailer\nobject: !ruby/class 'SurveyCompletionNotificationMailer'\nmethod_name: :notify\nargs:\n- !ruby/ActiveRecord:MyInstance\n attributes:\n id: 10786\n created_at: 2013-12-19 03:52:21.082910000 Z\n updated_at: 2014-07-23 19:12:27.967755000 Z\n delta: true\n- !ruby/ActiveRecord:User\n attributes:\n id: 30\n first_name: Andrew\n last_name: Anderson\n created_at: 2013-01-16 16:40:20.980147000 Z\n updated_at: 2013-01-16 16:40:20.980147000 Z\n title: Compensation Analyst\n primary_phone_number: '123456789'\n supervisor_id: \n status: modified\n disabled: \n prefix: \n suffix: ''\n department: ''\n general_info: ''\n contact_id: 4428\n emulating: true\n",
:last_error => nil,
:run_at => Wed, 23 Jul 2014 14:12:27 CDT -05:00,
:locked_at => nil,
:failed_at => nil,
:locked_by => nil,
:queue => nil,
:created_at => Wed, 23 Jul 2014 14:12:27 CDT -05:00,
:updated_at => Wed, 23 Jul 2014 14:12:27 CDT -05:00
}
But I find that Delayed Job will ignore the serialized argument data and reload the User record from the database. So if the User record changes between when the job is queued and when it executes, the new data will be used. This is not what I want. Why even bother the serialize the parameters if you're not going to use it? Am I missing something? Any way to get DJ to use the serialized argument data?
This is the behavior of DJ, it just uses the deserialized id to load the ActiveRecord object from DB (here is a related FAQ entry). If you want it to do something different, you would either need to monkeypatch ActiveRecord, or to pass the attributes as additional parameters to the mailer.

Resources