Git - Heroku deploy app that is composed of a couple of git repos - ruby-on-rails

Recently I built an rails app for a local business. They like this app so much that they've gotten a couple of other local businesses interested in having their own version of the app.
Here lies the problem that Im uncertain how to fix. The core business logic behind the app would be the same for these new and future customers(about 80% of the code). Whereas each customer would have their own static pages, as well as their own stylesheets.
Ive thought about multi-tenancy, but these guys are picky enough that it honestly seems easier to build the app function the way they want, as opposed to building around DB stored customer preferences(perhaps I'm wrong here).
I would like configure this application so that I can push changes to the core business logic without overwriting the customer specific portions of the site. Perhaps creating a second repo which only contains the customer specific content.
How do I configure this app/Git repo so that I can personalize the app without creating a bunch of parallel repos?

As Meagar pointed out the solution to this scenario is to encapsulate the core business logic of these applications into a Gem that can be reused later down the road.

Related

Rails application architecture and common setup

So I am starting out on company project that will have several components:
At first...
Job list
Client profile creation and management
User administration and access (login, signup, roles, etc)
later...
Messaging
Schedule
Basic reporting
way later...
Deeper analysis and bi
I'm wondering if it makes sense for each bullet item to be its own rails project, self contained and modular (if that is indeed the case); or if it's just best for it to be in the same app. I could envision a situation where each module could operate so independently of each other that it wouldn't need the rest (except for the user funcionality) and another situation where all modules would be used together.
It seems like to me that many tasks can be handled with a lighter framework like Sinatra (and then situated physically under the rails app). It also seems like it would be a lot of overhead to have several rails apps running on a server. But I am not totally aware of all the pluses and minuses to operating each scenario.
I know this is kind of a general question that is bound to get a lot of "it depends" kind of responses (and rightfully so) I was looking for opinions/examples of how you setup this kind/your kind of project in rails. I am a quasi noob so be gentle.
Thanks in advance!
Generally speaking I would consider a website to be a suitable target for a Rails app. Each part of the app can have its own namespaces within the app, so the app has some structure internally, but they should all be one application. Consider things like sessions, where you want a user to login and use whatever features of the site you want. You want those sessions in one application without a user having to login to different sections.
Saying that, if there is complex or extended functionality that isn't part of the MVC architecture (say talking to an external API, data-mining etc), then you could offset that to a separate project and a include it as a Gem in your application. You would still have one main Rails application that includes those Gems.
You might also want to bundle together a section of your project into a reusable Rails engine that can be loaded into multiple projects. For example, Devise handles user login and management. It is a Rails engine, bundled as a Gem, that you include in your project.
Another example from Meducation (one of my sites). I'm in the process of extracting our email tracking system out into its own Rails engine as I feel its functionality sits alongside Meducation and is not a core part of it. I can then use it in other projects as well.
In your specific example, I think your requirements fit fine in one Rails application.

How to decompose a Rails app into different small apps ecosystem

My team has been developing a bunch of modules in a monolithic Rails app for internal use. The modules are for example leave request, staff info, tasks/todo etc. Each module has its own purpose but somehow is linked to common information such as staff profile and user authentication. Each module has a developer assigned and they commit code to the same Rails app. Currently, it's super hard to maintain the code and scale. Now, I'm doing my research to decompose the app into small distributed apps and make them an ecosystem. Here are the concept I'm looking for:
There should be a master app that maintain the views of other client apps. Better yet, it acts as a platform for other client apps to plug in to it. Staff logs in to this master app to access client app.
Master app should render views of client app using AJAX or other ways (not decided).
Although, I want to decompose the apps, but each app should still be able to query resources/data such as staff profile from other client app in the ecosystem.
Actually, I have not decided about the interaction of each app. Thinking to us RESTful (not decided).
It should support development environment where each developer can develop each app independently. Hence, maintaining their own code in their own git repository. This is probably the main purpose of decomposing the app in the first place.
I'm reading Service-Oriented Design with Ruby on Rails book, but it seems like they focus on decomposing an app into small different services, whereas I want to have small different apps. Just wondering if there's any other ways to do.
Sorry for a long question and asking too much. Just want to know if you have been in the same situation and can guide me to some articles, communities, books so that I can continue more on my research.
Ah the joys of refactoring. It can be a tricky dance trying to structure an application into logical groups so that parts can be decoupled.
I would strongly suggest looking into Engines, with the Engines vs Mountable being very informative. This allows you to build a mini Rails app (aka an Engine) that can be packaged as gem. The custom Engine gems are bundled into a Rails app, providing a complete set of configurable functionality (models, controllers, views, etc).
The usefulness of Service-Oriented Architecture depends a lot on what kind of data you are pushing and pulling around. That being said, Rails is really wired for RESTful, so you get a lot of bang for the buck with that route.

How to extend an existing Ruby on Rails CMS to host multiple sites?

I am trying to build a CMS I can use to host multiple sites. I know I'm going to end up reinventing the wheel a million times with this project, so I'm thinking about extending an existing open source Ruby on Rails CMS to meet my needs.
One of those needs is to be able to run multiple sites, while using only one code-base. That way, when there's an update I want to make, I can update it in one place, and the change is reflected on all of the sites. I think that this will be able to scale by running multiple instances of the application.
I think that I can use the domain/subdomain to determine which data to display. For example, someone goes to subdomain1.mysite.com and the application looks in the database for the content for subdomain1.
The problem I see is with most pre-built CMS solutions, they are only designed to host one site, including the one I want to use. So the database is structured to work with one site. However, I had the idea that I could overcome this by "creating a new database" for each site, then specifying which database to connect to based on the domain/subdomain as I mentioned above.
I'm thinking of hosting this on Heroku, so I'm wondering what my options for this might be. I'm not very familiar with Amazon S3, or Amazon SimpleDB, but I feel like there's some sort of "cloud database" that would make this solution a lot more realistic, than creating a new MySQL database for each site.
What do you think? Am I thinking about this the wrong way? What advice do you have to offer in this area?
I've worked on a Rails app like this, and the way it was done there was named-based virtual hosts, with db entries for each site running. Each record was scoped to a site if necessary (blog posts, etc.) while users would have access to all sites running out of that db. Administrator permissions could be global or scoped to one or more sites.
You're absolutely correct when you say you'll reinvent the wheel a million times during the project. Plugins will likely require hacking on top of the CMS itself.
In my situation, it ended up being a waste of almost a million dollars of company money to build that codebase to run multiple sites while still being able to cater to the whims of each client site. It worked, but was not very maintainable due to the number of site-specific hacks that subsequently entered the codebase. You may be able to make it work if you don't have to worry about catering to specific client sites running on your platform.
In the end, you're going to need a layer of indirection to handle the different sites regardless of methodology. We ended up putting it in the database itself. If you go with the different-db-for-each-site method you mentioned, you'll put that layer in your code instead. I'm not sure which one is the better method.
I hope you're able to pull this off. I failed.
Also, as I learned today, Heroku offers postgres instead of mysql for rails apps.
There's James Stewart's Theme Support Plugin for Rails 2.3, and lucasefe's themes_for_rails gem for Rails 3+.
I just started using the 2.3 version and it's working well so far.

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.

How to reuse a rails app

I developed a rails app for a school alumni site.
Now another school wants me to develop a similar site for them.
I want to reuse the app. Data structure will be same but the actual data will be different. Design layout will be similar but design itself will be different.
One option is that I just copy the app and modify it. But in this case, I need to manage 2 apps as they evolve.
Another option will be to make the app generalized and customizable (Database will be separated though). Views will have a lot of a lot of branches.
I could use on database for multiple apps but I am sure it will require a lot of jobs.
Another option will be to move controllers and models to plugins so that 2 apps share them.
Do you have any experience with such a case? If so, can you share it with me?
Thanks.
Sam
This might be a little unorthodox, but if you're using git, you can create two branches
one for the school alumni site
one for the similar site
The root code will stay in the master branch. Your development flow would then be:
branch off the master
make edits
pull edits into master when satisfied
pull the master changes into the branches.
You can continue to locally modify the branches as needed, but you will need to be careful about introducing conflicting edits between master/branch.
If there is any way to avoid the complexity of forking your code into two separate applications you should do it.
Making the application generalized and customizable as you are suggesting moves your one off consulting project into something closer to a standalone product (which might be more profitable).
You'd be surprised how far you can get with different stylesheets, layouts and judicious use of localisation.
2 apps will share:
Models
Helpers
Controllers
They won't share:
Views
I am not sure about database yet.
I may separate views using skin concept like:
app/views/app1/...
app/views/app2/...
I am still thinking about database.
I'm using git submodules and symlinks. There's a submodule to the shared project in Rails.root/shared. Then there's symlinks from app/models to shared/app/models, and so on.

Resources