Ruby on Rails - Multiple applications with same model and db - ruby-on-rails

I'm developing an enterprise web applications with rails.
I'm trying to figure out the best way of using the same models and database between 2-3 rails applications.
My project consists of different applications such as user app, customer app and admin app.
All of these 3 will use the same database and almost the same models.
I want to create 3 different rails app and deploy them to different servers.
What might be the best way of sharing the models?

Build one app that contains your models and database. Make all of the controllers return json (or xml). Make no views for this app. Then, create your other apps as so that they make http calls to the first app. This allows you to share the models/database/capabilities of the original app to as many other apps as necessary down the line. And future apps can even use their own or supplemental data stores if necessary, as they are only using the original app as a service.

One of the solutions is to write custom library or gem and put all common code in here.

In your database.yml file for your various projects, just have them point to the same database. Then use the same class names in your various projects.

You can build 4 rails apps. The datastoreapp contains the data model and controllers returns json (no views). The userapp, custapp, adminapp could do api calls to the datastoreapp for consolidated data.

Related

Do Rails5 API mode app and non API mode app share codes each other?

I'm goint to create a RESTfull service app is made of Rails5 with API mode.
I also need an admin app that provides web views for managing users and contents.
These two apps will share codes each other.
I know a way of creating the API mode app.
$ rails new apiapp --api
How do I create the other project?
The way I would implement this kind of functionality is like so:
RAIL API for your model, database, validation and relationships logic.
Client side MVC for Admin app with RESTful calls. For this I would use Backbone Marionette.
this is the cleanest, least code repetition implementation I can think of, which follows industry standards.
this is as per the software mantra 'consume your own dog food' - if you create an api, use its interface to do your stuff. this way you test and improve it as you go.
If you want RAILS only on both ends, you would be better off implementing your ADMIN and your API as one app, for least code repetition. Create an API controller name space for all your exterior calls, and code normal rails for your admin views and stuff. this way your database and model validation and relationship logic is shared, but controllers and route namespaces are not.
Toodles.
You build the other project as a normal rails project. The thing to understand about Rails 5 api mode is that you cannot have normal html stuff as part of it. The entire rendering pipeline (assets and such) is missing. Rails 5 api mode is fast because big parts of the environment are just plain gone.
What you want to do is have 2 projects:
admin
api
And figure out a way to share your model logic across them.
If you use devise for authentication this is particularly tricky since devise adds things into your user model that you cannot have in an api project. Here's how I got around it:
If Rails.application.class.parent_name == "admin"
# devise crap goes here
end
How exactly you easily share a directory of models across 2 git repos? I have no good answer. I have a rake task which sync's things manually by copying them from the canonical source to the destination but that's a hack.

Rails 4 - Multiple apps using centralized database

Suppose we have this scenario:
www.main.com - Main interface where admin (foo, bar, etc..) can store products, based on their own e-commerce
www.foo.com - Sample store that sells items from the "foo" store
www.bar.com - Sample store that sells items from the "bar" store
The problem is finding a way to centralize the database structure and models.
I prefer to keep every single store in separated apps (so I exclude rails engines).
For instance, if a user buys something in the "foo" store, I need to interact with the main db and update it.
How can I do this?
Rails works much better with a "one database, one app" model. There are lots of ways how you can share models across apps (gems, engines, git submodules, etc), but none of those ways is great. You end up introducing lots of overhead in your development, deployment, and testing process. You also invite lots of hidden dependencies between code, as Rails doesn't give you easy way to keep clean abstraction (for example, you wrote a helper for store Foo, and then your coworker used that helper in store Bar, and then every time you change Foo, Bar breaks).
I recommend a centralized API approach instead:
api.foobarmain.com - a app/service that provides RESTful API for all the functionality of all stores.
This app has all the db models, and it exposes them as resources in the API for other apps to interact with.
This app can have an admin UI for all the stores, if you need it. Alternatively, admin UI may be another client of an API.
www.foo.com - a full stack app that interacts with API at api.foobarmail.com
There is no shared database connection to API, everything that you need to interact has to be exposed via API.
There will be no shared code between www.foo.com and www.bar.com. Code reuse happens only by virtue of using the same API app/service.
From the perspective of www.foo.com, the model layer (in MVC) is powered by API, not by database.
You can still have its own database on www.foo.com if you need to store data specific to www.foo.com only.
www.bar.com - another full stack app that interacts with API
so on ...
Another way is using multiple schema if you are using Postgresql. I have a similar issue with a new project that I about to start.
You can use gem 'apartment' to deal with different schemas. The queries will be a bit complicated but with different schemas you will end up with one database and you can create different namespaces to respond accordingly.
You can set up so app select the correct schema based on the Domain or Subdomain.
Here is the link: https://github.com/influitive/apartment

Large Rails suite architecture: combine three apps into one container app

Our Rails suite is comprised of three independent Rails apps:
JSON API (Rails app)
Admin dashboard (Rails app)
Shared data models (Rails engine)
Both the API and Admin dashboard require the shared data models engine in their Gemfiles. All models and custom classes are stored in the engine, and both apps make heavy use of the shared components. The API lives on one Heroku server, and the Admin dashboard lives on another separate Heroku server (two separate Heroku apps). Each use their own respective Postgres databases. All three apps have their own GIT repos.
The API database stores information pertinent to our public users, and the Admin database stores mostly statistical information for admin eyes only.
A caveat of the setup is that the Admin dashboard app has direct access to the API database, and vice-versa. I understand that this is bad practice and may not seem to make sense, but there was a reason for this (mainly because the Admin dashboard needed to access all records of certain API tables, and the use of a custom API to communicate over the wire was not feasible). A similar reason exists for the API-to-Admin database communication.
This setup works for our purposes, nothing is broken, and resources are allocated efficiently. However, productivity is beginning to suffer due to the slow and uncomfortable development process. An example: a change to the API is required. Chances are that the shared models engine needs a change and therefore a feature branch is needed in both repos. After committing and pushing, the Admin dashboard now contains an old version of the models engine (is behind by one patch version). The problem lies in trying to coordinate all three Rails apps, when only one app needs a change. Another problem is migrations. Since the models engine contains two different database connections, I must create the migration once in the models engine then create it again in the appropriate app (API or Admin).
My ideal setup would involve one large Rails container app with separate engines contained within. The separate engines would be: API, Admin, Models. Also, I’m beginning to think that using only one database might make things easier. I would also like to keep the API on its own server instance, and the Admin on a separate server. The reason for this is that the API is public facing (communicates with a public iOS app) and the Admin is used mainly as a CMS and reporting engine.
I am looking for solutions and advice from experience managing similar Rails / Heroku architectures. Specific questions:
Should I attempt to combine the three Rails apps into one container
app and use the engine approach?
Should I attempt to combine the two
databases into one database?
Is it possible to have one Rails
container app, and allocate different servers to different engines?
If I should keep all apps separate, is their an easier and more
productive way to implement new features and fixes on a daily basis?

Best practice for importing a partial database dump into a rails app daily?

The iTunes Enterprise Partner Feed is "a data feed of the complete set of metadata from iTunes and the App Store" and "is available in two different formats - either as the files necessary to build a relational database or as stand-alone flat files that are country and media dependent."
I need to consume the data from this feed (which is essentially exported into flat files) and allow linking of my own Model objects (User, Activity, etc.) to data provided by the feed (App, Developer, etc.) The data is provided as a weekly full export and a daily incremental export.
I have two ideas for ways to implement this:
Create all of the models in my rails app and write my own importer that will insert/update records directly into my app's database daily via cron using models I've created (App, Developer, etc.)
Keep this database entirely separate and open up REST API that my own app will consume
My naive approach with #1 to keep everything in the Rails app is based on the need to be able to observe changes in the data I'm getting from the EPF. For example, if an App's description is updated, I want to be able to create an Activity object via an observer to track that update.
On one hand #2 feels like a better approach because it creates a standalone API into the data that can be consumed from several different apps I create. On the other hand, I'm just not sure how I'd accomplish the data change notifications without using observers directly on my own models. Or, how I would even consume the data in an object oriented way that could still be used with my own models. It feels like a lot of duplicate work to have to query the API for, say, an App's data, create a proper Active Record object for it and then save it just so it can be linked to one of my own models.
Is there a standard way to do this that I'm totally missing? Any pointers?
EDIT: Rails engines sound interesting but it would mean that each app would still need to consume and insert the data separately. That doesn't sound so DRY. It sounds more and more like a REST API is the way to go. I just don't know how to bridge the gap from API to Active Record model.
Rails Engines might be a good fit for this. You can create a Rails Engine gem and add all of your models and rake tasks to consume the data. Then you can include this gem in any app that uses it and also create an API app which includes the gem. You should be able to create observers in your other apps that interact with the gem.
I have quite a few apps that interact with each other and this approach works well for me. I have one central app that includes all the engines that consume data and I run all of my cronjobs from this app. I use the use_db plugin which allows my app to communicate with different databases. Each engine has use_db as a dependency and I keep the database configuration inside the gem. One example:
Engine Gem = transaction_core
This gem consumes transaction data from a source and inserts it into my transaction database.
The gem is included in my central app and I pull the transaction data using a rake task on the cron
I include this gem in several other apps that need to use the transaction data. Since the engine automatically adds the models and database config to the app, there is no additional work required to use the models in the app.
I have not used observers inside an app that includes my engines, but I see no reason why it would not work. With the engine the models work as if they are in your app/models directory. Hope this helps!
Modest Rubyist has a good 4 part tutorial on Rails 3 plugins that includes Engines:
http://www.themodestrubyist.com/2010/03/05/rails-3-plugins---part-2---writing-an-engine/

Combining two Rails applications into one

I have a couple of pre-existing applications which I need to run in "one" app. One is the application I want to use for authentication etc, whilst the other is another app that contains all of the business logic.
Both apps have pre-existing authentication, and both have fairly complex user models.
Is it possible to easily combine these so that if I log into one application and create a user, that same data is available in the other - or something similar?
What is the easiest way of doing this? Can a rails model extend a REST webservice?
You can use the new(ish) Engine feature to embed one app inside another. Your engine lives inside vendor/plugins, can have all of it's own routes and config setup just like a normal rails application but actually share the database. Makes combining applications really easy. We use it with git submodules to make management of complex applications seamless.
I'd use warden (or devise, which is built on it) for the authentication. Warden is rack-based, and can therefore be used in both apps aka single-sign-on.

Resources