Django 1.9 models for testing purpose only - django-1.9

How to create test-only models that are actually migrated to test database in Django 1.9 with these two conditions?
migration file is not added to any non-test (application) migration set
relations are created on the remote model (so it can be examined by remote_model._meta.get_field('related_name'))
I've already tried these method:
https://pypi.python.org/pypi/django-fake-model (does not create remote relation)
https://github.com/django/django/pull/4700/commits/c2fef300224402ebb35c3c20243f06fbb67cddda (needs migration file in application's set of migrations)
https://code.djangoproject.com/ticket/7835#comment:20 (does not work with Django 1.9 due to removed module django.db.models.loading)
Thanks a lot for responses!

Related

Converting a single Tenant Application to a multitenant one using Apartment gem

I've built a single tenant rails application with all core features ready to ship. But I now want to make it multi-tenant using the apartment gem. Most tutorials I've found all show how to start from scratch. But I find no pointers on how to convert an existing project to have multi-tenancy built in. From my research I found that all models need a tenant ID added in the migration. How do I add this to all existing models easily? Does installing the gem and running the generator suffice? I'm running a rails 5 API application with close to 30 models and using graphql ruby in an Ubuntu 18.04 environment.
Any ideas on how to do this?
Thanks #lacostenycoder for pointing me in the right direction. Here's what I did.
Short answer: Yes, installing the gem, running the generator and creating your tenant model should suffice. Apartment reads your schema and creates schemas for the tenants.
Long answer, my experience:
I Backed up existing data from my database just in-case.
Installed apartment gem
If you are using any PostgreSQL database extensions like I was (pgcrypto, uuid- ssop)you need to understand that the extensions are not automatically loaded into the newly created schema.(look here for more details) do the following:
Follow instructions the github readme to create a shared_extensions schema
Create your first tenant. If it works, all is well. But...
If that doesn’t work, I mean when you create a tenant you get errors like ActiveRecord::StatementInvalid: PG::UndefinedFunction: ERROR: function gen_random_uuid() does not exist
or ActiveRecord::StatementInvalid: PG::UndefinedFunction: ERROR: function uuid_generate_v4() does not exist (more details here, here and here) like it was my case when creating my first tenant, I discovered that once the extensions are enabled on the public schema, they cannot be installed in the shared schema shared_extensions in this case. So you have to change them from the public schema to the shared_extensions schema. get more details here
If you are using uuid-ossp ALTER EXTENSION "uuid-ossp" SET SCHEMA shared_extensions in your rails dbconsole
If you are using pgcrypto ALTER EXTENSION "pgcrypto" SET SCHEMA shared_extensions in your rails dbconsole
The apartment gem will create all models for your tenant once you have it set up correctly and create your first tenant.
For more information on check out some of these github issues on apartment. Here and here.
Took me a day to figure it out and gather that info. I hope it saves you time and headache!
There doesn't appear to be any reason why you can't add this to an existing Rails app. I have not done this myself, nor does there appear to be any specific tutorials on how to migrate an existing app. Follow the gem setup instructions as shown on the README and also see the wiki for additional configurations and instructions. Use TDD wherever possible and expect to make changes to your application to get everything working correctly. Depending on how complex your existing app is will determine how much work this move will be.
You'll likely want to use lvh.me:3000 instead of localhost:3000 as root domain and port in your browser and perhaps use rails s -b lvh.me when starting your local server.
If you want to safely hack through this branch I recommend that you make a full backup of your local development database before you get started so that you can rollback to your stable current version in the event things go horribly wrong. If you're using Postgres for example there's pg_dump and pg_restore
This approach combined with good TDD should get you where you need to be.

Why do Migrations and Seeds for Mountable Engines need to be explicitly Loaded?

So I have been reading up on Ruby on Rails Engine guide migrations + seeds
and it seems that in order to have seeds run on the Engine they need to be added in the application using it
(Example using the dummy app)
add MyEngine::Engine.load_seed to Engine/test/dummy/db/seeds.rb
My question is why do we need to do this surely they should be isolated from the main application anyway? (they do not relate and are only seeding the Engines database)
NB:
If you are after some more context I have added the devise gem (/engine) to my Engine and the seed data is just creating a user under the context of my Engine for login to its interface
There are two parts of sharing seed data and schema for an engine: the schema migrations and the seed data itself.
As an engine, there are two ways to encapsulate db migrations within the engine but have them run correctly within the Rails app:
Physically copy migration files into Rails db/migrate directory
Patch Rails migration load paths to add engine migration directory:
config.paths["db/migrate"] += config.paths["db/migrate"].expanded
... within an initializer
You can find a good discussion of migrations within engines here: https://blog.pivotal.io/labs/labs/leave-your-migrations-in-your-rails-engines
Sharing seed data is a bit less elegant. DB seed data is loaded from the single db/seeds.rb file, so including custom seed data via engine code requires hooking into the Engine code from the seed file, such as your code above:
MyEngine::Engine.load_seed
There aren't any hacks or simpler ways to do that. You could probably automate prepending/appending that code into db/seeds.rb in your engine install/setup task.

How to externalize Rails model (api/gem/plugin)

currently I am working on a RoR application (2.3.14 with ActiveRecord) (let's call it A).
Now I started another project B (a remote testing app using capybara, looks something like this: https://github.com/searls/remote-capybara-cucumber-example).
But now I need to have access to the model of application B for test data setup (and possibly test assertions). I therefore would like to use the existing model classes (and some additional libraries like factory_girl if necessary).
I certainly don't want to wrap my project B in a Rails app and copy the model classes. So is there a way to organize A so that B can access the model and create/update/destroy entities?
Are there any keywords for further research (I tried several google searches containing rails model as a gem, as a plugin, externalize rails model etc... but nothing useful turned up (mostly the documentation of ActiveRecord)
Rails 2.x does make it very hard to share the model layer between two applications.
If you don't care about maintaining migrations twice, you can put the models into a gem and then require it in your apps.
Another way is to symlink the db and app/models directories from both applications to a shared folder. This works quite well though you have to be careful because rake tasks and generators now affect both applications.
Rails 3.1 ships with an improved implementation of rails engines. Engines allow you to isolate parts of an rails application and package them up as a gem.
You could try using an alias (symbolic link) to the A's app/models directory in the B project.
On Mac/Linux:
ln -s /volumes/code/project-a/app/models/ /volumes/code/project-b/models

Using ActiveRecord models in a gem - how to handle database config

I have several active record models in a rails app and I would like to extract these models into a gem so that I can easily use them in several web apps. The process seems pretty straight forward, except for passing along the configuration for the models. Do I:
Add the configuration yaml file to the gem, thus assuring the databases will always be the same across all apps - seems rigid, esp for testing and dev, though the databases for production will always be consistent.
Use the ActiveRecord hooks to look for a database.yml file in the config directory with the database defined? If so, which hooks should I use?
This is a stupid idea. If you have a better way to handle this, I'm all ears. I'd prefer not to copy and paste.
You should use the host rails app's database config. Your plugin or gem should contain just the database migrations, and a rake task to run them from the host rails app (e.g. myplugin:db:migrate)
If your models need some other configuration file, you should create a rake task (e.g. myplugin:install) to copy it to your host app's config directory. (This task can call the db:migrate task automatically as well.)
Why do you want to embed the database.yml file inside the gem? Each rails application should use it's own database.yml
I would put all the models into a plugin and include that in each rails application that needs the models.

Ruby on Rails and db:fixtures:load - can it ignore some models?

I have two databases in use in a Ruby on Rails application; one is the database for the application while the second is an independent database over which Rails is not given control.
Problem is when loading fixtures into the dev, it tries to run DELETE statements on the tables in the independent database from the connection to the dev database, which obviously errors out.
I don't want Rails to try to do ANYTHING but read the independent database - I especially don't want it trying to delete tables.
Is there a simple way to tell Rails to ignore the models for the second database when loading fixtures?
UPDATE: To clarify, Rails seems to think the tables from the independent database are part of the development connection, though I have specified the correct connection in the model class using establish_connection. As another note, all model classes work precisely as desired from script/console.
rake db:fixtures:load RAILS_ENV=testing
will do the job for database configured as testing in your database.yml
I think you might also be able to accomplish this by adding all the tables in the independent database to ActiveRecord::SchemaDumper.ignore_tables in environment.rb, like so:
ActiveRecord::SchemaDumper.ignore_tables = ['independent_db_table1', 'independent_db_table2']
Okay...my issue was that I used the script/generate to create the models from the secondary database, which also created fixture, schema, test, and migrations files. I had removed the schema, test, and migrations files, but did not remove the generated fixtures (they were empty files) as I did not think it had created any.
After removing all files (including the models) from the secondary database and re-running the migrations for the dev db, I added back only the model files and the database in databases.yml from the secondary db, which solved the issue.
I still can't explain why Rails' rake tasks were looking in the wrong database and I am a little disappointed with rails' addition of the schema_migrations table in the secondary database, which it obviously does not need.
However, it works now.
Delete the model_name.yml file in your test/fixtures directory and Rails will not try to delete these tables.
Better yet, delete all your *.yml files and stop using fixtures entirely.

Resources