Design application architecture for catalog/orders system - ruby-on-rails

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.

Related

Database design for reverse-auction platform

The idea is for a reverse auction platform where users post their auction for certain services and providers bid on it with their offers.
Should I be splitting my tables? For example the auction can be for a new service or to replace an existing service so there are questions that are specific to each selection.
Should I move those columns into a separate table for that option?
Here is a diagram of what I've come up with so far:
Database Diagram image
Am I on the right track here?
What data type should I use for columns where there will be an list of options to choose from in the auction form? For example, cash_back will give the user a range of choices as:
Donate to Charity
Deposit to my account
Credit Voucher
Is the norm to use a string for this column with the respective strings or do I create a new table for the options and use the option_id as a foreign key in this table?
I think it is worth discussing here Rails philosophy and database design generally.
As I often say you can have a database for your application, or you can have an application for your database. In the latter, database design is important. In the former, it usually follows application design.
What this means is that you probably, assuming this is a Rails app, don't want to design your database at all. What you want to do is design your application object model and let Rails design your database. You won't get a great db design that way, but it will be good enough.
The tradeoff is that when you go this way, you often end up with the database as effectively owned by the application and it may not be safe to have other apps add or modify the data in the database. Moreover it may be harder to come up with really good reports, but where you put in most of your time will be better optimized (your main app).
TL;DR: If you want a database for your app and using Rails or Django, then stop thinking about database design, but realize that while this optimizes some pathways today, it makes many other things harder down the road.

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.

Rails web app: do you create a separate database per account opened?

I'm about to finish building a simple subscription based support ticket Web app. I'm setting up authorization. But since this it's going to be my very own Web app that I'm going to deploy I'm wondering about this.
Do you create a separate database per account opened?
Let's say you have this support ticket Web app. You have ONE and ONLY ONE account owner. Account owner can setup agents that can respond to support tickets. Also, there are customer roles that open support tickets.
So as you can see the database will contain users, support tickets and more.
What is the best way to go?
1) Create one database for the whole application? That way every time somebody signs up, everything is added to the same database with the other tickets and users data and everything else or...
2) Everytime someone signs up, create a separate database per account subscription.
I'm thinking that maybe option number 2 would be a best choice for security and data integrity purposes. If so, how have you gone about tackling this issue?
It sounds like what you want is Multitenancy:
Multitenancy refers to a principle in software architecture where a
single instance of the software runs on a server, serving multiple
client organizations (tenants). Multitenancy is contrasted with a
multi-instance architecture where separate software instances (or
hardware systems) are set up for different client organizations. With
a multitenant architecture, a software application is designed to
virtually partition its data and configuration, and each client
organization works with a customized virtual application instance.
- Wikipedia article on Multitenancy
This article while a little dated is the general idea of how I would go about doing it. Simple Rails Multi-Tenancy. It's clean and efficient and saves you from writing code that you don't need to.
You should go for option #1. Number 2 is (almost (there are probably cases where it is good, but I can't find one at the moment)) never an option.
You are right in security purposes (well, in a sense), but it also creates a lot of other problems that you will have to think about.
Having a different database for each user means that for each request (remember, HTTP is state-less) you will have to open up a new connection to the database, do whatever needs to be done and then close the connection again, instead of using the connection pooling that is in Rails. This affects the performance a great deal.
Administration will be a hassle the more databases you have. Also, having multiple databases on a server do require more resources than just a bigger database.
You would have to circumvent the entire connection handling in Rails since there it is usually one database per application. It is easy to change the database for specific models, but it adds additional places where things can go wrong.
Rails do have good functionality for scoping and handling of separating data within the same database, just for that kind of use-case that you are mentioning.

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.

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