Model, after some time, decides it references a different (non-existent) table

This is odd... I have a few models that after some time just start doing SELECT "my_tablemy_belongs_to_table".* sort of thing. (Almost like it is trying to reference a join table, but missing a _ between the table names.)

In other words, things work for hours, days or weeks then suddenly goes from SELECT "my_table".* to SELECT "my_tablemy_belongs_to_table".*

The associated FROM clause also changes to match. Hundreds of exceptions per minute then ensue and all heck breaks loose. ;')

I perhaps am running into a namespace issue or something(?)... how does a model get triggered into changing it's associated table name in runtime? Our temp fix it to just restart the service/app but that's obviously not sustainable. We had to do it several times today.

Thoughts?

ruby 2.5.0p21 (2018-02-18 revision 62472) [x86_64-linux]
rails 5.1.6
pg 1.0.0

Thanks!

Phil

Is there nothing unusual in the log just before it happens the first
time? Also look in the system/server logs to see if anything happened
there.

Colin

This is odd... I have a few models that after some time just start doing SELECT "my_tablemy_belongs_to_table".* sort of thing. (Almost like it is trying to reference a join table, but missing a _ between the table names.)

In other words, things work for hours, days or weeks then suddenly goes from SELECT "my_table".* to SELECT "my_tablemy_belongs_to_table".*

There are a few activerecord settings (table_name, table_name_prefix maybe some others) that could do this. Might these be getting changed by accident (perhaps because your model has a method whose name clashes with an active record method) ?

Fred

This is odd... I have a few models that after some time just start doing SELECT "my_tablemy_belongs_to_table".* sort of thing. (Almost like it is trying to reference a join table, but missing a _ between the table names.)

In other words, things work for hours, days or weeks then suddenly goes from SELECT "my_table".* to SELECT "my_tablemy_belongs_to_table".*

There are a few activerecord settings (table_name, table_name_prefix maybe some others) that could do this. Might these be getting changed by accident (perhaps because your model has a method whose name clashes with an active record method) ?

Fred

The associated FROM clause also changes to match. Hundreds of exceptions per minute then ensue and all heck breaks loose. ;')

I perhaps am running into a namespace issue or something(?)... how does a model get triggered into changing it's associated table name in runtime? Our temp fix it to just restart the service/app but that's obviously not sustainable. We had to do it several times today.

Thoughts?

ruby 2.5.0p21 (2018-02-18 revision 62472) [x86_64-linux]
rails 5.1.6
pg 1.0.0

Thanks!

Phil

Thank you Fred and Colin.

Somehow table_name seems to be getting set to something else... I can simulate how it breaks but I don't know where/why it is breaking in the production code...

UserAccount.table_name = "blah"

=> "blah"

UserAccount.first

Traceback (most recent call last):
        1: from (irb):2
ActiveRecord::StatementInvalid (PG::UndefinedTable: ERROR: relation "blah" does not exist
LINE 1: SELECT "blah".* FROM "blah" ORDER BY "blah"."id" ASC LIMIT ...
                              ^
: SELECT "blah".* FROM "blah" ORDER BY "blah"."id" ASC LIMIT $1)

Something in Rails 5.1.x is appending to 'table_name' in the model during some condition?

I can't easily reproduce. I don't see anywhere in the code where I'm operating on table_name directly.

(still digging, I hope everyone is having a good Saturday, btw :')

Phil

This is odd... I have a few models that after some time just start doing SELECT "my_tablemy_belongs_to_table".* sort of thing. (Almost like it is trying to reference a join table, but missing a _ between the table names.)

In other words, things work for hours, days or weeks then suddenly goes from SELECT "my_table".* to SELECT "my_tablemy_belongs_to_table".*

There are a few activerecord settings (table_name, table_name_prefix maybe some others) that could do this. Might these be getting changed by accident (perhaps because your model has a method whose name clashes with an active record method) ?

Fred

The associated FROM clause also changes to match. Hundreds of exceptions per minute then ensue and all heck breaks loose. ;')

I perhaps am running into a namespace issue or something(?)... how does a model get triggered into changing it's associated table name in runtime? Our temp fix it to just restart the service/app but that's obviously not sustainable. We had to do it several times today.

Thoughts?

ruby 2.5.0p21 (2018-02-18 revision 62472) [x86_64-linux]
rails 5.1.6
pg 1.0.0

Thanks!

Phil

Thank you Fred and Colin.

Somehow table_name seems to be getting set to something else... I can simulate how it breaks but I don't know where/why it is breaking in the production code...

UserAccount.table_name = "blah"

=> "blah"

UserAccount.first

Traceback (most recent call last):
       1: from (irb):2
ActiveRecord::StatementInvalid (PG::UndefinedTable: ERROR: relation "blah" does not exist
LINE 1: SELECT "blah".* FROM "blah" ORDER BY "blah"."id" ASC LIMIT ...
                             ^
: SELECT "blah".* FROM "blah" ORDER BY "blah"."id" ASC LIMIT $1)

Something in Rails 5.1.x is appending to 'table_name' in the model during some condition?

I can't easily reproduce. I don't see anywhere in the code where I'm operating on table_name directly.

(still digging, I hope everyone is having a good Saturday, btw :')

Phil

Ah, I've solved this. We've migrated code that used arrays, to strings. We were still using "<<", though, to concatenate strings. Let me give you some examples to understand the issue....

>> a = MyItem.table_name
=> "my_items"
>> b = a
=> "my_items"
>> c = b
=> "my_items"
>> d = c
=> "my_items"
>> d += ", other_items"
=> "my_items, other_items"
>> d
=> "my_items, other_items"
>> c
=> "my_items"

All good, right? Now, let's use '<<':

>> a = MyItem.table_name
=> "my_items"
>> b = a
=> "my_items"
>> c = b
=> "my_items"
>> d = c
=> "my_items"
>> d << ", other_items"
=> "my_items, other_items" <---- Same result! Looks right.
>> c
=> "my_items, other_items"
>> MyTable.table_name
=> "my_items, other_items" <--- Oh noes, the result was inherited all the way down to the table_name of the model!

Now the MyItem model is borked until the app is restarted.

The malformed 'from' clause was a bit of a red herring and that was easily resolved, btw. (A 'join(', ')' was skipped because the construction of the from-clause was a string not an array any more in our code.)

The '<<' method appears to work the same as the String method ".concat(something)" . It also makes all other variables inherit the same value.

Another possible solution is to use '.dup', for what it is worth:

>> d = c.dup
=> "my_items"
>> d << ", other_items"
=> "my_items, other_items"
>> c
=> "my_items"

I hope this helps somebody if they run into a similar problem! (I don't claim this is a Ruby bug or such, just perhaps not very well documented feature.)

Phil

>> a = MyItem.table_name
=> "my_items"
>> b = a
=> "my_items"
>> c = b
=> "my_items"
>> d = c
=> "my_items"

​var references object.​
at this point, all vars a,b,c,d points to MyItem.table_name

>> d << ", other_items"
=> "my_items, other_items" <---- Same result! Looks right.
>> c
=> "my_items, other_items"
>> MyTable.table_name
=> "my_items, other_items" <--- Oh noes, the result was inherited all
the way down to the table_name of the model!

Now the MyItem model is borked until the app is restarted.

The malformed 'from' clause was a bit of a red herring and that was easily
resolved, btw. (A 'join(', ')' was skipped because the construction of the
from-clause was a string not an array any more in our code.)

The '<<' method appears to work the same as the String method
".concat(something)" . It also makes all other variables inherit the same
value.

it does more, ​just be careful since it flattens.

(from ruby core)
=== Implementation from Array