White label without code duplication? - ruby-on-rails

I have a technical question I'm not sure about.
Right now I have a product / web app (rails application) that I white label to other companies. I host the white label and everything I'm just wondering how to get out of this viscous cycle of having to duplicate all my code.
If I make a change to an API on one I have to do it to the other. I'm not sure how to get around this but I think it is important.
I've thought about building a core API which will route requests to different white labels servers but I'm not sure this is the best option.
Any help offered is greatly appreciated!

It sounds as if you clone your app each time you add a new company, whereas the proper solution would be to have one app that serves somewhat different data depending on the current company.
You can use the Apartment gem if you wish to use different dbs for different companies (sort of, check docs for more details), but you need to make sure your db can handle multiple tables (PostgreSQL can't). Or you can use Acts As Tenant if you wish to scope records to a specific company.
My suggestion is to go with Acts As Tenant, as most dbs are doing well with multiple rows, but not so well with multiple tables.

Related

Rails same app with different databases

I'm building a report app in Rails for a current desktop app. The app is kind of pos/accounting.
So at the moment there are different clients with the desktop app installed at shop or office. Each one has its own mysql database.
I am now planning how to setup the server, most probably heroku.
Given that I will keep the databases for each client separated, I'm trying to understand the best path to follow.
Another thing to consider is that there will be different version of the app, i.e. restaurant, bar, shop etc.. Different versions will use the same database. I'll just need to change some controller and view. Most probably I'll handle this using namespace.
For a client(company) multiple users will have access to the app.
The solution I thought is to create a database table company and add a column company to users table.
Things that could change from a client to another:
call different images from assets such as logo
there might be custom views or even controller if a client requests some customization
use different database
domain possibly, but that's not that important wouldn't a be a big deal to use the same
Then based on user.company show a different logo or any other required image, render a view instead of another, at login connect to the proper database.
I don't know yet how to implement it, right now I'm still evaluating the best approach to follow. But this way maintenance/updates would be easy to manage even if maybe performance will be a bit lower and code harder to understand with possible customizations all together but that's acceptable.
Is this a reasonable solution or should I consider something different? Am I missing something important to consider?

Design application architecture for catalog/orders system

I have to write a system that allows clients to make orders of products. There is an existing application that handles creating catalog (adding, editing products etc.) It is used by producents to maintain data about their products. Now I am wondering how should I add order functionality (I have access to source code of catalog application and catalog database). Order functionality can be shortly describe as:
customer can login make new orders, see old ones
producer can login and see new orders made by clients, archive orders
midleman should see all orders grouped by producer so he can decide whether or not to ship them
I am thinking about few ways:
Create new application with new database, that contains only orders.
products in catalog database and order database will be connected by [producent_id, product_id] pair
in orders application I would connect to catalog database to show information about products
Disadvantages of that approach, that I can think of are
not being able to do statistics queries like "count all orders of items from category that are made of wood" etc.
Advantages
clear seperation from existing application
Add functionality to existing application and use the same database
producer has another option in menu "Orders"
add new functionality for clients and middleman
Disadvantages of that approach, that I can think of are
not being able to for example move orders database/aplication to another server
Advantages
able to run cross orders/catalog queries
I really can't make my mind about this. I can see upsides and downsides for both ways, but can't decide which is better. Do you have any suggestions, maybe third way?
P.S technology will be ruby on rails
Personally I would go for the 'add functionality to existing application'.
I don't suppose you want to sell the Order application separate because it totally depends on how your Catalog/Product app is build.
The development will be easier, not only database access but also the reuse of the existing infrastructure will improve your development speed.
I suppose the only reason you want to move the orders application to another server is because of performance problems. I would say that you should never optimize for a situation your not sure it will ever happen.
It's much harder to do cross database queries which are not supported then to optimize the application when you notice some real, measurable, performance issues.
So in my opinion development speed out wages supposed performance problems.

Multi-tenant rails application: what are the pros and cons of different techniques?

I originally wrote my Ruby on Rails application for one client. Now, I am changing it so that it can be used for different clients. My end-goal is that some user (not me) can click a button and create a new project. Then all the necessary changes (new schema, new tables, handling of code) are generated without anyone needing me to edit a database.yml file or add new schema definitions. I am currently using the SCOPED access. So I have a project model and other associated models have a project_id column.
I have looked at other posts regarding multi-tenant applications in Rails. A lot of people seem to suggest creating a different schema for each new client in Postgres. For me, however, it is not much useful for a new client to have a different schema in terms of data model. Each client will have the same tables, rows, columns, etc.
My vision for each client is that my production database first has a table of different projects/clients. And each one of those tables links to a set of tables that are pretty much the same with different data. In other terms a table of tables. Or in other terms, the first table will map to a different set of data for each client that has the same structure.
Is the way I explained my vision at all similar to the way that Postgres implements different "schemas"? Does it look like nested tables? Or does Postgres have to query all the information in the database anyway? I do not currently use Postgres, but I would be willing to learn if it fits the design. If you know of database software that works with Rails that fits my needs, please do let me know.
Right now, I am using scopes to accomplish multi-tenant applications, but it does not feel scalable or clean. It does however make it very easy for a non-technical user to create a new project provided I give them fillable information. Do you know if it is possible with the multi-schema Postgres defintion to have it work automatically after a user clicks a button? And I would prefer that this be handled by Rails and not by an external script if possible? (please do advise either way)
Most importantly, do you recommend any plugins or that I should adopt a different framework for this task? I have found Rails to be limited in some cases of abstraction as above and this is the first time I have ran into a Rails-scaling issue.
Any advice related to multi-tenant applications or my situation is welcome. Any questions for clarification or additional advice are welcome as well.
Thanks,
--Dave
MSDN has a good introduction to multi-tenant data architecture.
At one end of the spectrum, you have one database per tenant ("shared nothing"). "Shared nothing" makes disaster recovery pretty simple, and has the highest degree of isolation between tenants. But it also has the highest average cost per tenant, and it supports the fewest tenants per server.
At the other end of the spectrum, you store a tenant id number in every row of every shared table ("shared everything"). "Shared everything" makes disaster recovery hard--for a single tenant, you'd have to restore just some rows in every shared table--and it has the lowest degree of isolation. (Badly formed queries can expose private data.) But it has the lowest cost per tenant, and it supports the highest number of tenants per server.
My vision for each client is that my production database first has a
table of different projects/clients. And each one of those tables
links to a set of tables that are pretty much the same with different
data. In other terms a table of tables. Or in other terms, the first
table will map to a different set of data for each client that has the
same structure.
This sounds like you're talking about one schema per tenant. Pay close attention to permissions (SQL GRANT and REVOKE statements. And ALTER DEFAULT PRIVILEGES.)
There are two railscasts on multitenancy that using scopes and subdomains and another to help with handling multiple schemas.
There is also the multitenant gem which could help with your scopes and apartment gem for handling multiple schemas.
Here is also a good presentation on multitenancy-with-rails.
Dont forget about using default scopes, while creating named scops the way you are now works it does feel like it could be done better. I came across this guide by Samuel Kadolph regarding this issue a few months ago and it looks like it could work well for your situation and have the benefit of keeping your application free of some PgSQL only features.
Basically the way he describes setting the application up involves adding the concepts of tennants to your application and then using this to scope the data at query time using the database.

Should I split my Rails app?

I have two tasks both using rails:
To make an inventory app to help employees keep track of inventory
To make a website for the company for customers to visit and gain a bit of knowledge about our product
My plan is to have the inventory app for each branch of the company to have a domain like this:
branch1.example.com
branch2.example.com
branch3.example.com
and for the customer-facing website to simply be www.example.com
My question is, should I make two separate rails apps, one for the inventory app and one for the customer-facing website? Or would it be easier to manage the two as a single combined app? The two apps would not be likely to share much code.
And if I were to split my apps, how would I be able to host both of my apps using a single domain as seen above (with the use of subdomains) with heroku?
Thanks!
Well, there's not really one right answer, but being experience with rails, I would recommend one app.
If you split there will be many times you'll have to copy and paste common code (becomes unmanagable). Plus you'll deal with either a shared database or multiple databases.
Not splitting, you can use a wildcard domain and access the current subdomain via request.subdomain to easily do whatever logic needs to happen per subdomain. Also you will only need to create the Product model once.
In short, all the mentioned requirements sound tightly coupled enough that one app would be easiest.

What is the best strategy to combine IntrAnet and Web-exposed website?

I was wondering if somebody has some insight on this issue.
A little background:
We've been using Rails to migrate from an old dBase and Visual Basic based system
to build internal company IntrAnet that does things like label printing,
invetory control, shipping, etc - basically an ERP
The Dilemma
Right now we need to replace an old customer-facing website that was done in Java, that
would connect to our internal system for our clients to use. We want to be able to pull information like inventory, order placement, account statements from our internal system and expose it to site live. The reason is that we take orders on the website, through fax & phone and sometimes we have walk-ins. So sometimes (very rarely thou) even a short delay in inventory update on our old Java site causes us to put an order on backorder, because we sell the same item to 2 customers within half an hour. It's usually fixed within one day but we want to avoid this in the future.
Actual Question
Does anyone have any suggestion on how to accomplish this in a better
way?
Here are three options that I see:
a) Build a separate Rails app on a web server, that will connect to the same DB that our internal app connects to.
+++ Pluses:Live data - same thing that our internal apps see, i.e. orders are created in real time, inventory is depleted right away
--- Minuses: Potential security risk, duplication of code - i.e. I need to duplicate all the controllers, models, views, etc. that deal with orders.
b) Build a separate Rails app on a web server, that will connect to a different DB from our internal app.
+++ Pluses: Less security exposure.
--- Minuses:Extra effort to sync web DB and internal DB (or using a web service like REST-API), extra code to handle inventory depletion and order # creation, duplication of code - i.e. I need to duplicate all the controllers, models, views, etc. that deal with orders.
c) Expose internal app to the web
+++ Pluses: all the problems from above eliminated. This is much "DRY"er method.
--- Minuses: A lot more security headaches. More complicated login systems - one for web & one for internal users using LDAP.
So any thoughts? Anyone had similar problem to solve? Please keep in mind that our company has limited resources - namely one developer that is dedicated to this. So this has to be one of those "right" and "smart" solutions, not "throw money/people/resources at this" solutions.
Thank you.
I would probably create separate controllers for the public site and use ActiveResource to pull data from you internal application. Take a look at
http://blog.rubybestpractices.com/posts/gregory/rails_modularity_1.html
http://api.rubyonrails.org/classes/ActiveResource/Base.html
Edit - fixed link and added api link
I would go for a. You should be able to create the controllers so that they are re-usable.
Internal users are as likely to duplicate data as external users.
It's likely that a public UI and an internal, for-the-staff, UI will need to be different. The data needs to be consistent so I would put quite a bit of effort into ensuring that there is exactly one, definitive database. So: one database two UIs?
Have a "service" layer that both UIs can use. If this was Java I would be pretty confident of getting the services done quickly. I wonder how easy it is in Ruby/Rails.
The best outcome would be that your existing Customer Java UI can be adapted to use the Rails service layer.
Assuming you trust your programmers to not accidentally expose things in the wrong place, the 'right' solution seems to me to have a single application, but two different sets of controllers and views, one for internal use, and one for public-facing. This will give you djna's idea of one database, two UIs.
As you say having two separate databases is going to involve a lot of duplication, as well as the problem of replication.
It doesn't make sense to me to have two totally separate apps using the same database; the ActiveRecord part of a Rails app is an abstraction of the database in Ruby code, therefore having two abstractions for a single database seems a bit wrong.
You can also then have common business rules in your models, to avoid code duplication across the two versions of the site.
If you don't completely trust your programmers, then Mike's ActiveResource approach is pretty good - it would make it a lot harder to expose things by accident (although ActiveResource is a lot less flexible and feature rich than ActiveRecord)
What version of Rails are you using? Since version 2.3 Rails Engines is included, this allows to share common code (models/views/controllers) in a Rails plugin.
See the Railscast for a short introduction.
I use it too. I have developed three applications for different clients, but with all the shared code in a plugin.

Resources