Why can't I delete and rebuild entire search database in Heroku? - ruby-on-rails

On localhost and my Heroku staging app, pg_search is working just fine.
On my Heroku product app, pg_search is still showing search results for my Footnote model (which I no longer want to include) in addition to the Reference model (which I still want to include).
I have...
# /app/models/reference.rb
class Reference < ActiveRecord::Base
has_paper_trail
include PgSearch
multisearchable :against => [:source_text, :citation]
end
I have removed include PgSearch from my /app/models/footnote.rb.
My process starts with manually allocating some workers to the app. (Which I normally do automatically using workless.)
Then I do:
$ heroku run rails console --app testivate
Running `rails console` attached to terminal... up, run.2840
Connecting to database specified by DATABASE_URL
Loading production environment (Rails 3.2.11)
irb(main):001:0> PgSearch::Footnote.delete_all
NameError: uninitialized constant PgSearch::Footnote
irb(main):002:0> PgSearch::Reference.delete_all
irb(main):003:0> PgSearch::Multisearch.rebuild(Reference)
(1.3ms) BEGIN
SQL (56.2ms) DELETE FROM "pg_search_documents" WHERE "pg_search_documents"."searchable_type" = 'Reference'
(1279.8ms) INSERT INTO "pg_search_documents" (searchable_type, searchable_id, content, created_at, updated_at)
SELECT 'Reference' AS searchable_type,
"references".id AS searchable_id,
(
coalesce("references".source_text::text, '') || ' ' || coalesce("references".citation::text, '')
) AS content,
'2013-04-02 01:05:09.330250' AS created_at,
'2013-04-02 01:05:09.330250' AS updated_at
FROM "references"
(33.8ms) COMMIT
=> #<PG::Result:0x00000006c849b0>
irb(main):004:0>
The last step returns its result, #<PG::Result:0x00000006c849b0>, instantly, despite the fact that I've just asked pg_search to index 53 documents of between 3000 and 15,000 words each.
Can I assume the rebuild process is underway? Is there some way of confirming when it's complete so I can scale back the worker processes? (And do I need to allocate worker processes to this anyway?)
BTW, the following approach also takes just seconds, which doesn't seem right:
$ heroku run rake pg_search:multisearch:rebuild[Reference] --app testivate
Running `rake pg_search:multisearch:rebuild[Reference]` attached to terminal... up, run.3303
Connecting to database specified by DATABASE_URL
(1.5ms) BEGIN
SQL (95.4ms) DELETE FROM "pg_search_documents" WHERE "pg_search_documents"."searchable_type" = 'Reference'
(1070.3ms) INSERT INTO "pg_search_documents" (searchable_type, searchable_id, content, created_at, updated_at)
SELECT 'Reference' AS searchable_type,
"references".id AS searchable_id,
(
coalesce("references".source_text::text, '') || ' ' || coalesce("references".citation::text, '')
) AS content,
'2013-04-02 01:10:07.355707' AS created_at,
'2013-04-02 01:10:07.355707' AS updated_at
FROM "references"
(103.3ms) COMMIT
After all these attempts, I still get instances of the Footnote model in my search results. How can I get rid of them?

It's a bit harsh, but heroku run rake db:migrate:redo did the trick.

Related

Activerecord Model.table_exists? does not give correct results

When creating the actual database table in rails console, User.table_exists? does not give me the correct result.
But when I look into ActiveRecord::Base.connection.tables it shows that the table exists. I have to exit rails console and go back in before User.table_exists? give me the correct value. Is there some caching going on? A bug in Rails 5.2.1? Or am I missing something?
Code to reproduce:
in terminal/bash
rails generate model User name:string
rails console
in rails console
User.table_exists? => false
ActiveRecord::Base.connection.tables => []
ActiveRecord::Migration[5.2].create_table :users =>
-- create_table(:users)
(0.1ms) SELECT sqlite_version(*)
(1.5ms) CREATE TABLE "users" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL)
ActiveRecord::Base.connection.tables => ["users"]
User.table_exists? => false
exit
in terminal/bash
rails console
in rails console
User.table_exists? => true
using:
Ruby 2.5.0
Rails 5.2.1
ActiveRecord::ModelSchema::ClassMethods#table_exists? is a wrapper around ActiveRecord::ConnectionAdapters::SchemaCache#data_source_exists?.
As the name implies, this is a cache, probably populated when the Rails app starts. If you modify the database schema the old schema will still be cached (arguably a bug or missing feature). You can reload User's schema cache with User.reload_schema_from_cache or possibly connection.schema_cache.clear_data_source_cache(Users.table_name.
I guess it's a cache thing. I couldn't tell if a bug or not, I don't have much knowledge of rails internals but I gues it's that way by design. It's not even a common use case to create tables from within the console.
You could skip the exit > enter steps calling reload! on the console to reload everything though.

How to remove Sunspot indexed data after removing model indexing?

I'm using Rails with Sunspot gem and Websolr for Solr hosting. Let's say I have a Solr indexed ActiveRecord model like this:
class User < ActiveRecord::Base
searchable do
text :name
end
end
Now I want to remove indexing from this model, so I just remove this indexing code (searchable block). Will the indexed data be removed automatically from Solr? I assume not and that I need to remove/reindex in manually. I can reindex everything like this:
Sunspot.index
Sunspot.commit
But reindexing my whole database will be slow. Is there another - faster way to stop indexing 1 model? I don't see any interface in Websolr to look through and delete records from the index and I can't seem to find any information on how to remove models from indexing with Sunspot.
I can reindex everything like this:
No, you can't, if you need to reindex again then open Rails console by typing rails c and then
=> Model.index
# User Load (15.6ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 50]]
# [2018-02-27 18:45:04 +0600] Start Indexing
# D, [2018-02-27T18:45:05.439714 #15296] DEBUG -- : SOLR Request (762.4ms) [ path=update parameters={} ]
And for the removing indexed data then try to the following
curl http://localhost:8982/solr/default/update?commit=true -d '<delete><query>*:*</query></delete>'
Let's describe on the url part
localhost: is the hostname.
8982: port number where your Solr server running if you confusing what is your port number then open rails console and type this puts Sunspot.config.inspect it will show your port number.
/solr/default/update: this is the path where your command execute.
?commit=true -d: That is the instruction.
'<delete><query>*:*</query></delete>': that is the method.
I have found this here but it's not working for me because there are port number and path different, I have edited my own way and it's working perfectly.
I think it will help.

ALTER SEQUENCE on rake db:reset db:migrate not working

I'm developing an information system in Ruby on Rails.
I want to hand out following uids to users:
0: root
1-499: system services (server-side)
500: system admin
501-999: external apps (apps that connect through API)
1000+: human users
I have the following migration set up:
class SetUsersAutoincrementValue < ActiveRecord::Migration
def change
execute("ALTER SEQUENCE users_id_seq RESTART WITH 1000")
end
end
The migration works as expected. However, it doesn't if triggered by rake db:reset db:migrate.
What to do?
Thanks
I suppose rake db:migrate:reset.
Try to restart the ruby server (Puma) may help.
I run the SQL command ALTER TABLE directly on DB to change a table id column from INT to BIGINT.
After updating, when inserting big number I got an error out of range for ActiveModel::Type::Integer with limit 4"
After restart ruby server, everything works well.

Solr cannot reindex due to strange query being produced

I am writing a rails applications that utilize solr for full text search
In development mode, I used the sunpost solr gem which is really handy. I used the sqlite3 database in development and everything went smooth.
Now is the time to move to production server and I installed the solr-tomcat package and moved to my production database which is Mysql. I moved the conf files of solr from my application folder to /usr/share/solr/conf
Suddenly, I cannot reindex, and solr returned this
rake RAILS_ENV=production sunspot:solr:reindex
[# ] [ 50/7312] [ 0.68%] [00:00] [00:41] [ 175.82/s]rake aborted!
Mysql::Error: Unknown column 'barangs.' in 'where clause': SELECT `barangs`.* FROM `barangs` WHERE (`barangs`.`` >= 0) ORDER BY `barangs`.`` ASC LIMIT 50
Intrigued, I tried to reindex with the development database, all is well and can be reindexed. This behavior left me baffled
Any help will be appreciated
I got the problem. It was due to me dropping and restoring tables recklessly and it loses some relationships definitions.
Hence the "missing" column on table 'barangs'.'MISSING' solr can't find the specified column.
For others who are facing the problem, I recommend inspecting the relationship between models first

Marking Rails migrations as migrated

I've ended up with 9 migrations effectively duplicated. (I think this is because I installed/updated Gems and/or pulled in their migrations on both my dev and production machines, but am not entirely sure at this stage.)
I moved out one set of the duplicated 9 from the rails directories on the production server, but now that I want to db:migrate on production in order to run another migration, I'm getting:
$ bundle exec rake db:migrate RAILS_ENV=production
[DEPRECATION WARNING] Nested I18n namespace lookup under "activerecord.attributes.checkout" is no longer supported
== CreatePages: migrating ====================================================
-- create_table(:pages)
rake aborted!
An error has occurred, all later migrations canceled:
Mysql2::Error: Table 'pages' already exists: CREATE TABLE `pages` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, `title` varchar(255), `body` text, `slug` varchar(255), `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB
This is because the migrations have effectively already been run.
I'd rather avoid doing db:migrate:down and db:migrate:up for each one - I think this will mean data in the production database is lost. (A couple of static pages in Spree in this case.)
Is there a way I can tell this installation of Rails to forget all outstanding migrations, effectively marking all outstanding migrations as done?
I solved it like this:
Go to the conflicting migration file.
Erase the content and save it.
Run rake db:migrate
Ctrl+Z the file to the previous state.
This was an special case, because I had copied the DB from another app, and I had conflicting migrations, and stuff.
You can add the timestamps of the migrations to the schema_migrations table. However why is that table missing from the database or missing the rows it needs?
It is likely to be the case that this particular migration has got half way through and failed, thus when you are trying to run it again the first part of the migration will not work as it has been done previously. This is a limitation of MySQL as it can't rollback migration changes that fail part of the way through. Postgres on the other hand can rollback structural changes to the database thus avoiding this issue.
By default rake db:migrate runs all the pending migrations. So, in order to get your migrations right.. for the sake ..comment out those migrations and afterwards revert those back to normal. It will ensure that you are ok in future migrations.
You can also, in a Rails console, use the ActiveRecord::SchemaMigration model to add the timestamps into the schema_migrations table.
ActiveRecord::SchemaMigration.create! version: '20210724133241'

Resources