Best practice for structuring a 'large' Rails app
Asked Answered
E

6

17

My question here is seeking best practice, general advice and insight, rather than a solution to a specific problem.

I am in the early stages of planning out a Rails project which I consider fairly large. At its simplest level it offers a cookie-cutter CMS to the target users. So users sign up and choose a subdomain and are given a pretty basic website with CMS.

Therefore the entire app has about 4 different 'sides' to it:

  • A sales website selling the product to end users - www.myapp.com
  • A central admin area where staff can log in and manage accounts etc - www.myapp.com/superadmin
  • The users' own websites - subdomain.myapp.com
  • The users' admin area/CMS - subdomain.myapp.com/admin

So really what I'm looking for is best practice for structuring the app. i.e. should it all be rolled into one huge application or should it be split over 2 (or more) smaller apps?

If deployed as one application, I can see issues surrounding routing as both the sales website and the users' websites will need a root path set, plus I would not want the routes I set for the sales website being accessible through the users' websites. Can anything be done either within Rails or at Apache level (mod rewrites ?) to ensure no mixup of routes?

If split over 2 or more applications, how do you get the applications sharing the same database? Is that even a good idea? Are there any benefits from splitting the application (like isolating problems in one area of the app, rather than bringing everything down)?

I realise this post raises quite a few different questions, but appreciate any advice and insight you can give me.

Epicritic answered 29/11, 2009 at 20:49 Comment(1)
Good question, I'd like to hear people's thoughts on this too. Rails 3 is set to have embeddable apps, so you could put an administrative app inside your base app, but I'm not sure what the best thing to do until then would be.Metallo
R
6

I believe the benefits of isolating your concerns into separate apps outweigh the costs. I would probably start off with just 2 apps (one for the main site and superadmin, one for the client sites and admins), accessing the same database, but you could do 4.

The downside is you don't really have isolation since all your apps are tied to one database. You will eventually run into scaling problems with your database, but starting off simple with one database will get you launched. One strategy for scaling later would be to add a slave db that the client site and main site apps use, while the admin apps use the master db. This along with a TON of caching will get you pretty far.

There is nothing wrong with having multiple rails apps access one db, however you will need a way to share common code across your apps. Your models for the most part. I've done this before by tossing all my models in a plugin that I share as a sub-module in git or as an external in svn. Having separate apps will make each app smaller and easier to maintain.

However, where do you keep your migrations? Where do you test your models? I would opt for the superadmin app. Also, you make a change to a model or the schema, and now you have to check 2-4 apps and make sure they still work!

Better isolation, separate db's and inter-app communication through web APIs (SOA) and you don't have to worry about that. SOA I think is the way to go after a certain point, but SOA might be premature when you first start out.

At any rate, having separate apps sets you up for SOA but you don't have to jump beyond a single db to start.

Randa answered 30/11, 2009 at 6:58 Comment(2)
Thanks for this comprehensive answer. Even though one or two people have disagreed with regard to splitting the app I appreciate the detail in your answer. Once question: If models etc are being kept in a plugin, does that rule out using rails generators to create models and migrations?Epicritic
Generators are not ruled out, but you have the extra step of moving your generated code into your plugin afterwards. Generate, hack on the model, get it working, then move it into your plugin. For migrations you could have one app that you do all your migrations in. Other apps would have to have their schema.rb files updated (rake db:schema:dump), after migrations.Randa
C
5

I would bundle this all into the same app because you won't be duplicating the classes (models, plugins, etc.) across all the apps. Also: running 4 apps means that you'll have 4 processes all consuming memory due to the 4 separate Rails stacks they have loaded.

Compiling it into one application eliminates this issue. For the issue between the sales site and the users site having to have different roots that can be solved, as mentioned earlier, by subdomain_fu. Let me expand with some sample code from an application I have:

map.with_options :conditions => {:subdomain => 'logs'} do |admin|
  admin.resources :channels do |channel|
    channel.resources :logs
  end
  map.root :channels
  map.connect ':id', :controller => "channels", :action => "show"
end

As we see here, the :conditions for the with_options method sets :subdomain to be logs which means that anything coming in to logs.mysite.com will fufill these conditions and therefore be routed this way.

Now further on in this routing file I have everything else wrapped up in a similar block:

map.with_options :conditions => {:subdomain => nil} do |admin|
  # shebang!
end

Everything going to mysite.com will go to these routes.

Lastly, compiling it all into one mega-super-hyper-app will eliminate the database-sharing issues.

Cero answered 30/11, 2009 at 10:45 Comment(4)
Thanks for this. subdomain_fu does indeed look like it solves my primary concern about routes. Can you assign routes to a wildcard subdomain though? like: map.with_options :conditions => {:subdomain => *} do |site|Epicritic
"Lastly, compiling it all into one mega-super-hyper-app will eliminate the database-sharing issues." And create a host of other issues in the process.Forecast
@Forecast Engines weren't a thing back when I posted this answer. Neither was hexagonal / services-style development (or whatever name you want to give it). While the advice is no longer relevant, I still feel it was relevant for the time that it was posted, and so I am choosing (in this instance) to leave my original answer here in all its unedited glory. If people follow the advice here, then it's their bad luck. They should know better than to follow the advice of posts 5+ years old.Cero
That's true. This question looks like a good one to follow.Forecast
U
3

The biggest issue I see with separating into several apps is that you lose flexibility. What happens if, in the future, a previously administrative task (eg. uploading a type of file) becomes a "user task"? You would have to be moving code from one application to the other.

I'd keep everything on single application - and use roles for filtering what each user can see and do. It might be a bit more difficult at the begining, but it pays up in the near future.

Have a look at authorization frameworks, such as declarative_authorization or cancan.

Uphill answered 30/11, 2009 at 8:33 Comment(0)
M
2

Well, since nobody else has spoken up, I'd encourage you to do some reading on Service-Oriented Architecture. The book Enterprise Rails by Dan Chak has some great material on this, and you can read a lot of it through Google Books. Try chapter 13, here. I think it'll put you on the right track.

Metallo answered 30/11, 2009 at 5:24 Comment(0)
E
0

I see the kind of problem you are facing is, trying to build an application which will have various sub domains, so account_manager a plugin can solve your problem.

also if your application is large enough to maintain than splitting them in two or three would be good idea, with restfull resources you can make your applications talk to each other and so.

while if you are thinking of having them under one database, thats quite simple in rails using the establish_connection.

I think you can split the application in three to four different applications where set of clusters will handle each applications request, so the speed will be good. also you can bundle similar kind of functionality in one app to make sure maintaining them is easy.

http://www.railslodge.com/plugins/1113-subdomain-fu

Electron answered 30/11, 2009 at 9:15 Comment(0)
M
0

As far as my research has taken me, most companies at high scale would opt for SOA with multiple databases. Here are links to some information on how Linked In and EBay think about this. And to echo PreciousBodilyFluids, I highly recommend the Enterprise Rails book by Dan Chak.

Minima answered 13/1, 2011 at 17:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.