views:

92

answers:

5

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.

+1  A: 

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.

dr
My main concern with this is that I need to maintain 2 copies of the same code. Granted we use SCM (mercurial) and I should write proper unit tests, which should simplify maintainance, but its just rails programmer inside me cringes at the thought of nor writing DRY code :-)
Nick Gorbikoff
+1  A: 

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.

djna
Nick Gorbikoff
Your option #3 is to have one web app the internal one, and expose that? No, that's not what I mean. In concept I have three components. 1) a service layer, 2) an internal UI and 3). an external UI. 2 and 3 use 1. Whether the components are a single "Application" comprising three modules, or three separately deployed applications is an implmentation detail, but I suspect that you will at least have separate URIs for internal and external users.
djna
+1  A: 

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%5Fmodularity%5F1.html

http://api.rubyonrails.org/classes/ActiveResource/Base.html

Edit - fixed link and added api link

Mike
Mike, that link is dead. :-(
Nick Gorbikoff
Sorry about that! Fixed it and added a link to the api docs.
Mike
thank will take a look!
Nick Gorbikoff
Just wanted to thank everyone, let know that I ended up going with this solution.Thank you
Nick Gorbikoff
+1  A: 

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)

DanSingerman
+1  A: 

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.

nathanvda
I was thinking actually about using engines, which addresses code reuse, however second part of my question / concern is security. If I setup system with engines - it would have to reside on one server - so if I put it in DMZ for external access - then I have to deal with a headache of managing access to internal systems that are on internal side of the firewall.
Nick Gorbikoff
The code you define in the plugin is shared. However, you can overrule this definition if it is found in the standard Rails folders. So for instance: in the plugin/shared code authentication is through your own user/password database, but in the internal application you overwrite this model with a connection to LDAP. Once the user is authenticated, has its roles, the behaviour for the rest of the application is the same. Likewise: the access to the DMZ is in the shared code, but only your internal application will access the internal database.
nathanvda
And with engines there is no need for both applications to reside om the same server. The shared code resides in the plugin, a folder inside your rails-app (vendor/plugins). Just make sure that your plugin is inside it's own git-repository (i use git submodules for that). That way i make sure that the plugin code is identical along all my applications, and whatever functionality that needs to overrules, i do in the "hosting" rails application. Is that clear? I hope it helps. I am not sure if it covers your needs (or that i understand them correctly).
nathanvda