Multiple apps, one database heroku rails - ruby-on-rails

A friend and I have an idea to create multiple apps via heroku using Postgres.
Is there away we can tie in all the databases into one singular database by either pushing each one individually or just having them all indexed?

Yes use heroku config in the app with the provisioned database to get the connection string. Then use heroku config:set PG_URL=3829w:8eh8fe78hfd#ffeiwfafdsa.amazonaws.com/8fdHUfdsa to set the database in the other app. Now both apps will use the same database. They won't overwrite each other, but they will write to the same DB.

You can create multiple schemas, which will namespace the tables per-schema and avoid any name conflicts between each app's models.
https://devcenter.heroku.com/articles/heroku-postgresql#multiple-schemas
The most common use case for using multiple schemas in a database is building a software-as-a-service application wherein each customer has their own schema.
The flipside (as the link points out) is that multiple schemas can significantly reduce performance. You're also sharing connection limits, cache and disk space between apps. This might not be a problem depending on your usage, but just be aware of it.
Further reading:
CREATE SCHEMA docs: http://www.postgresql.org/docs/9.3/static/sql-createschema.html
Set schema_search_path in database.yml in each app to your individual schemas: http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html

Related

How can I set up 2 rails apps which share users?

I want to run 2 ruby on rails apps which share users, creating one app to do it all is not an option unfortunately. So I want to have single sign on, and user data shared across them. I'm unsure as to what the best solution to this would be.
Should I run them both off the same database?
Have 2 databases with both apps using the users table in one database only?
Some other solution?
You would have to have a dedicated development rails environment to manage migrations. And have the two "apps" pointing at this database. The downside is just generating models and relationships twice for those two apps is a manual task.
A cleaner solution is to have one rails environment with migrations, models and relationships. But build an API endpoint into this environment that those two apps can call in order to use the shared database.

How to manage migrations when multiple apps share the same database in Ruby?

I have a Rails app and a Sinatra app, sharing the same database. The Sinatra app uses ActiveRecord.
Can I run migrations from within each app, as if they were in the same app? Will this cause any problems?
The schema.rb file in the Rails app tracks the current migration via
ActiveRecord::Schema.define(:version => 20121108154656) do
but, how does the Sinatra app know the current version the database?
Rails 3.2.2, Ruby 1.9.3.
The version column in the schema_migrations table equate to the time stamp on the front of the ruby migration file example: 20130322151805_create_customers.rb So if two ore more applications are contributing to the schema_migrations table roll backs will not be possible if rails can't find the down() method (because it will not find a migration file contained in another app ie db/migrate/...)
I have a current situation that is exactly this and I have opted to have a master ActiveRecord app that manages migration and data conversions as our database evolves. Keep in mind that part of the deal is to keep models up to date as well. This has been time consuming so we are considering breaking apart the DB in to business domains and providing APIs (JSON) to query support data for another application. This way each application manages it domain and is responsible for exposing data via API.
regards.
If you connect both applications to the same database you should be able to run migrations on it but I strongly suggest you use another option since you will almost surely hit a wall at one time or another:
split the database in two if possible with each application responsible for its own database /migrations.
have one application considered the "master" database and use another database for the data specific to the second application but make it connects to both database (each application still only apply migrations to one database)
If you need to share data between multiple applications another option is to implement a REST service in one and use it on the other, you can have a look at the grape gem for a simple way of doing so.
Edit: I realize I forgot to speak about the activerecord migration, there is no longer any "version" of the schema, what activerecord does is that it read all your migration filename, extract their identifier (the starting part) and check if they have already been applied so in theory you can run migrations from two applications on the same database provided they don't interfere.
But if both migrations act on the same tables you will almost certainly run into big troubles at one point.
I disagree with Schmurfy, even if his presented options are valid, its a bit of an overkill to share data through REST (granted, its pretty easy to implement with ruby / rails).
If your case is simple you could just use one database from both apps, and since you use AR in both of them you have no problems with versioning, AR takes care of that.
Also i dont know what happens if you run db:migrate from both apps simultaniously if you use a inferior dbms like mysql which does not allow DDL in a transaction, certainly nothing good..
Also it would bother me to look which app needs what column and not have the migrations in one place. You could use a shared repository to manage the migrations from both apps.
Rails migrations store current database version in schema_migrations table in the database. So both of your apps will be able to check the current version.
The version numbers are timestamps, so there shouldn't be any problem with duplicate values, as it'll be almost impossible to generate two migrations at the exact same millisecond. So you should be fine here.
The only problem I see is that when you rollback a migration in one app, it'll set the db to the previous known version and I'm not sure if it will pick the previous one from the db (which could be from the other app), or the number from the previous migration file. You may want to test that scenario to make sure.
I decided to put all migrations in the Rails app because:
Since there is only one database
Rails manages migrations
This has worked well.
This simplifies the system because all migrations are stored in one place. And, the Sinatra app doesn't need to know about them anyway.

access an existing database that is created and used by another application

I have a rails app that should access some other databases for reading only. These Databases are created and used by other applications and I only need the to read.
Its not a problem to connect to these databases but I dont want to create a model for each table in these databases manually because there are some hundred tables. Is there a best practice for accessing a foreign database with rails?
Yes we can access foriegn databases in Rails application
Checkout this link
http://www.paultastic.com/showpage/Grabbing-Data-From-Foreign-Database-Using-Rails

RoR/AR: advice on managing different RDBMS permissions across Rails environments

Is there a recommended practice for managing multiple testing and production database users under one Rails app? I've a Rails app with four different database users associated with it:
owner, the DB user who owns the app schemaPermissions: Just about everything. (This is the maintenance/migration account.)
app, the DB account that powers the web applicationPermissions: Read on most tables and views, write on some temporary caching tables.
writer, the DB account that feedsPermissions: Write on a few tables.
auditor, the DB account that logs DB write activityPermissions: Owns a few triggers and functions.
Right now my migration files contain GRANT/REVOKE logic for these specific, named users. However, in the "development" environment all it is often convenient for these users to all be the very same account. Additionally, the hardcoded names of these users may conflict with already-existing DB user names in the final production environment.
It sounds like you're going to need to manage 2 different database connections for each of the classes of users you've got (app/writer). This is often managed by mixing in helpers to set these up to different classes of Models that need to use them.
There's no reason you can't configure this in your development environments, but you'll get the most bang for the buck by using a Staging environment that exactly resembles your Production environment for issues like this, where you can do a final shakedown of behavior before something is pushed live.

Any thoughts on Multi-tenant versus Multi-database apps in Rails

Our app currently spawns a new database for each client. We're starting to wonder whether we should consider refactoring this to a multi-tenant system.
What benefits / trade-offs should we be considering? What are the best practices for implementing a multi-tenant app in Rails?
I've been researching the same thing and just found this presentation to offer an interesting solution: Using Postgre's schemas (a bit like namespaces) to separate data at the DB level while keeping all tenants in the same DB and staying (mostly) transparent to rails.
Writing Multi-Tenant Applications in Rails - Guy Naor
Multi-tenant systems will introduce a whole range of issues for you. My quick thoughts are below
All SQL must be examined and
refactored to include a ClientId
value.
All Indexes must be examined to
determine if the ClientId needs to be
included
An error in a SQL statement by a
developer/sysadmin in production will
affect all of your customers.
A database corruption/problem will
affect all of your customers
You have some data privacy issues
whereby poor code/implementation could
allow customerA to see data belonging
to CustomerB
A customer using your system in a
heavy/agressive manner may affect
other customers perception of performance
Tailoring static data to an individual customers preference becomes more complex.
I'm sure there are a number of other issues but these were my initial thoughts.
It really depends upon what you're doing.
We are making a MIS program for the print industry that tracks inventory, employees, customers, equipment, and does some serious calculations to estimate costs of performing jobs based on a lot of input variables.
We are anticipating very large databases for each customer, and we currently have 170 tables. Adding another column to almost every table just to store the client_id hurts my brain.
We are currently in the beta stage of our program, and here are some things that we have encountered:
Migrations: A Rails assumption is that you will only have 1 database. You can adapt it for multiple databases, and migrations is one of them. You need a custom rake task to apply migrations to all existing databases. Be prepared to do a lot of trouble shooting because a migration may succeed on one DB, but fail on another.
Spawning Databases: How do you create a new db? From a SQL file, copying an existing db, or running all migrations? How do you keep you schema consistent between your table creation system, and your live databases?
Connecting to the appropriate database: We use a cookie to store a unique value that maps to the correct DB. We use a before filter in an Authorized controller that inheirits from ActionController that gets the db from that unique value and uses the establish_connection method on a Subclass of ActiveRecord::Base. This allows us to have some models pull from a common db and others from the client's specific db.
If you have specific questions about any of these, I can help.
I don't have any experience with this personally, but during the lightning talks at the 2009 Ruby Hoedown, Andrew Coleman presented a plugin he designed and uses for multi-tenant databases in rails w/ subdomains. You can check out the lightning talk slides and here's the acts_as_restricted_subdomain repository.
Why would you? Do you have heavy aggregation between users or are you spawning too many DBs? Have you considered using SQLite files per tenant instead of shared DB servers (since multitenant apps often are low-profile and don't need that much concurrency)?

Resources