I am building a ruby on Rails 4 app. The web version is ready and I would like to set up/learn how to build mobile apps.
I know and read in many many articles that the "way to go is to use rails-api and feed json to the various clients".
But I'm not sure it's the best fit: I don't want to use it only because it's popular. I want to understand why (if it is) really necessary.
I'd like if possible to build a "beautiful monolith" as explained here.
DHH (core creator of Rails gem) use in Basecamp this beautiful monolith strategy, an hybrid approach which he states is the number 1 time-saving tactic they use to be able to maintain with few developpers numerous web and mobile apps.
Basically you keep your Rails controller, Rails models and everything in your Rails app and rails app and you use a phonegap container to inject in web views the views. You only change this way the views (with Rails 4.2 variant).
https://signalvnoise.com/posts/3766-hybrid-how-we-took-basecamp-multi-platform-with-a-tiny-team
So with this strategy, let's take an example where we need to the database data. for example if someone loads my mobile app:
- the webview 'homepage' on iphone will load ex: views/phone/projects/show.html.erb:
say I need to display the name of the user in this page, the app will go fetch it on /app/controllers/homepage_controller.rb and this controller will have a method like #users = User.find(id)... (active record)
so IT WILL GO HIT THE standard DATABASE (without needing any api or json)
So when I asked 'I'd really want to know why people sue rails-api/josn to know if I really must use it, or if I can use DHH hybird approach', here what people say
80% of start ups use it => blah...not a reason enough. I'd like to know why I should do it.
you can't do "single page apps" and ajax calls without API/json
Here I checked and it's incorrect: as explained below, you can totally use ajax in a webview can totally do it via whitelisting:
http://www.telerik.com/forums/$-ajax-not-working-on-android-devices :
When you are developing a Cordova powered hybrid app, you do not need to make CORS requests. Regular XHR requests will work without a problem. The reason for this is that a mobile app is executed from a file URI and does not comply to the cross origin policy. Mobile apps have an alternative to this policy which is called domain whitelisting.
Are pure and traditional Ajax Requests possible on native / hybrid mobile apps?:
PhoneGap apps run in webview not in browser, so cross origin is not an issue with PhoneGap apps, you can perform AJAX calls to any URL. The only thing to care of is that there is a white list parameter "access origin" in config used to restrict the access to some specific URLs.
So if I follow DHH hybrid approach to keep my Rails app but change the views on the web/iphone/android views and use my database data WITHOUT any API or json, is it possible?
What does API/json really bring to the table, why would they be really necessary, explaining most large multi clients app use them? Can't each of my various apps (web app, mobile app, tv app) just hit the database without any API/json ?
I might be missing something obvious so please advise.
This question does not really suit stack overflow, as the answers can be very opinion-based and also depend on what YOU really want to achieve. However, I will have a go:
Your first question:
So if I follow DHH hybrid approach to keep my Rails app but change the
views on the web/iphone/android views and use my database data WITHOUT
any API or json, is it possible?
Yes this is possible. Note that it will not be a 'native' app on the mobile device, and many people consider such 'apps' to be inferior (since they are not really apps installed on the device). The big advantage of course is that you don't have to learn how to write a native mobile app (and an API for it to talk to). The other big advantage is that you only have to maintain one code-base (models and controllers) for serving all users. You should really google native apps versus non-native to see the full picture.
Your next question:
What does API/json really bring to the table, why would they be really
necessary, explaining most large multi clients app use them?
Separating the API out from the 'front end' part of your code base allows you to have different teams develop different frontends. So you might have a mobile team that focuses on building a very polished mobile native app. You can also have a backend team focus on the API. So for larger enterprises this makes a lot of sense. The API is also more easily scalable - you can have multiple servers running the API and as more 'frontend users' connect (whether form mobile or web or whatever) you can bring up more copies of your API to serve their needs. The other option you have is to easily open-up your API to 3rd party developers if the need arises. That would be a bit harder with the DHH hybrid approach. Not impossible, but harder.
Your last question:
Can't each of my various apps (web app, mobile app, tv app) just hit
the database without any API/json ?
Yes, of course. This is really the same question as the first. Your different views would be serving different 'frontends' (basically HTML/JS/CSS) for the different clients. But they all hit the same controllers/models and hence database. Just don't forget that all your clients are HTML based. Most mobile/tablet users don't like having to open a browser to use an 'app'. They want the native experience (same goes for tv boxes, consoles etc).
By the way, there are ways to develop mobile apps that share one-code base (see appcelerator.com for example). But that's yet another, and different, approach!
Related
Background
I have a fairly typical Rails application, which uses Devise for authentication management. While building this app, I realized that realtime chat would be a great feature to have. Ideally, of course, this would make use of Websockets, in order to reduce the polling load on the server (as well as making it marginally easier to implement, as you don't have to manage polling).
I realized quickly that Ruby isn't really a great fit for having a large number of concurrent connections open at one time. Phoenix, however, is written in Elixir, so I can make use of the Erlang VM, which is quite good at long connections. It also seems like it could be greatly beneficial if all the chat data was stored separate from the main application database, which should also reduce load in the future.
The Problem
I want to be able to make this separation completely invisible to the user. They visit www.example.com/chat, and it loads all the relevant data in from chat.example.com and starts up the websockets, without requiring them to login to a separate service. I think using an <iframe> is probably the way to go about doing this.
My problem is sharing authentication and data between the two applications. The Rails app needs to be able to create conversations on the Phoenix app in response to certain events. The Phoenix app needs to know what user is currently authenticated into Rails, as well as general data about the user.
An OAuth flow with the Rails app as the ID provider seemed like a good fit at first, but I can't figure out a way for the Phoenix app to automatically be granted access. I also have some concerns about user records existing inside the Phoenix app—it should be aware of all users on the main application, so you can start a chat with a user even if they haven't ever opened chat.
What would be the best way to go about doing this? My intuition says that this is going to involve window.postMessage and some kind of token system, but I wanted to ask what the generally accepted way of doing this was before I accidentally created an insecure mess.
Sharing the session isn't too hard, assuming you are running at least Rails 4.1 and using JSON serialization (default for apps created with >=4.1). A quick google search finds PlugRailsCookieSessionStore, which accomplishes this.
For more information on what it takes to share a session between Rails and another language, Matt Aimonetti has an excellent blog post with detailed information.
Lastly, if you would prefer to stay entirely in Ruby, it's definitely doable. Ryan Stout discusses scalability around persistent connections in the FAQ for Volt, which uses a persistent connection for every user. The article he links is also a great read. Just mentioning it to help you weigh the trade off of building a separate app in another language.
So I am creating both a Rails app and they are getting a mobile app created for their project.
I would prefer to use Heroku and that whole tool chain because I love it. It is simple, has lots of caching add-ons, is cheap/free on the low-end and can scale up easily.
However, they want a mobile client that can also do the same thing the Rails app can do.
It obviously doesn't make sense running two different databases (one on Heroku and the other on Parse - which is what they want to use).
So how do I setup both apps to use the same DB?
Do I just create a public-facing API from the Rails app and have the mobile client ping those endpoints?
Do I use Parse for the mobile stuff, and write the Rails app to use the Parse DB instead? Is Parse a suitable Heroku replacement for serving cached files and scaling up as needed, etc.?
Do I maintain two databases (one at Parse and one on Heroku) and just create a Rake task that syncs the two?
What's the best way to approach this problem, so we keep the entire project as DRY as possible and also future-proof it so when we want to add more mobile clients and perhaps other clients in general, we can easily just add them on to the existing infrastructure?
I see many developers using Rails to deliver their API while taking advantage of Ember or Angular to build the front of the application. It makes it a lot easier to build the mobile app at the same time.
I want to create a web application in which the main application shall be built using a PHP Framework or RoR. However, there are some sections only, that need real time updates (e.g., collaborative editing, real time feeds) etc. Is it possible that if a user is authenticated on the PHP/RoR app, the user session data can be passed on to the meteor app ? Can the 2 applications share the same database? Any insight on how do I go about implementing this ?
While it is possible to do what you've asked you should possibly ask yourself if you can't achieve your goals with one tech stack. Having multiple tech stacks like Meteor and RoR / PHP means anyone that wants to work on your codebase needs to know all of these frameworks. Additionally you might be able to achieve your requirements around collaborative editing and real time feeds using PHP or RoR.
Since you have not posted your requirements it is hard to make concrete recommendations but maybe you should list your requirements use the least complicated tech stack to implement it.
Are you aware that RoR 4 has built in support for streaming: http://tenderlovemaking.com/2012/07/30/is-it-live.html
You might be able to implement your collabaration requirements using a JS library liek Angular or Ember JS which uses Ajax to keep the users screen in sync with what other users are doing.
Also, this blog post on how Trello is implemented might give you some ideas. They have a great web interface for collaboration: http://blog.fogcreek.com/the-trello-tech-stack/
With regards to your questions:
Two applications implemented in two different technologies can share the same database. You will need to choose a database that is supported by both technology stacks that you want to use. After that, point both applications at the same database.
If you authenticate a user in PHP/RoR app, you can then set a cookie for the user. Assuming your Meteor app is served from the same domain, you can then read in this cookie which might contain some kind of identifier for the authenticated users session. Your Meteor app could then check the db to see if this is a valid session for an authenticated user.
I have a Rails app that has 2 "clients" -- an iOS app reads/writes JSON, and Web browsers that read HTML.
Now, if I said "I want different output for different browsers/clients", we could use different ERB files and render based on User-Agent or similar.
In this way Rails was imagined in the Web world -- where I type "cap deploy", and all of my "instances" are upgraded to the latest version (save active session AJAX calls).
As an iOS dev, however, I'm very used to if blocks in code to deal with different data versions & client app versions. It's painful (but required).
I would love to be able to say "I will magically think of the perfect data structure in version 1.0", but we probably all know that's not true -- I'll want to add & deprecate attributes or even models as time goes.
I don't want to mix all of that versioning logic with my normal HTML (which can upgrade gracefully, per above), so I've thought about:
Having a separate controller or just actions for my API calls from iOS
Writing a "forwarder" that treats the HTML/Web version as a layer on top of the API version
Am I trying to solve a Solved Problem? Are there any resources or guiding philosophies I should know about in undertaking this project?
I suggest you create 2 applications, one for the webapp and one for the API.
You could have an external library with all the models, tests and business logic used in those 2 applications.
You can then lock the api to a certain version of the library if needed.
You can create multiple versions of the API without affecting older versions.
You can implement caching at library level if needed and it will automatically affect all applications.
With this model you can also create specific needs, for example, you may want shorter urls for the api than the real webapp, since you don't care about SEO in the API.
What do you think?
Edit :
Here is what I have in mind, library is in the middle.
So, this may be a kind of dumb question, but I checked the Google and got no hits. We want to host multiple Rails apps in a way that makes them look homogeneous. We want all the apps to have the same look and feel, and all the apps to use the same sign-on database.
Theming I think we could accomplish by just putting the site theme into a gem, and requiring that gem from our github repository in each app. However, auth is trickier.
I know that I can achieve this "for free" by just not making the different portions of the site (store, chat forums, etc.) different apps. If they're all, say, Rails Engines, we can basically drop them into the same application with their own namespaced routes, and have a single plugin that does auth.
However, for various reasons we'd like to keep these separate apps, if that's technically possible. The number one reason is scalability; since this will be a hosted site, we want the flexibility to spin up more instances of, say, the store (perhaps to handle a holiday sale rush), without needing to spin up the chat forums. Also, we want to be able to completely isolate the portions of the code that AREN'T intertwined.
Ideally, the databases would be separate too (keeping us from falling back into the rut of "put everything including the kitchen sink in the db"), but I do know that one "cheap" way to do cross-app auth is just to use the same plugin (say, Devise), and just point to the same DB.
So, I'm thinking that maybe the way to do this is to auth via a web service call. Is this prior art -- does anyone have a gem for this that "just works" so that authentication can be shared across all apps? Or am I just entering into a world of pain by trying to build things this way?
Thanks in advance!
You could do a single sign on approach described at:
http://blog.joshsoftware.com/2010/12/16/multiple-applications-with-devise-omniauth-and-single-sign-on/
The single sign on approach with oauth and devise has some drawbacks. The main problem I had was I was unable to extend the timeout time across multiple apps.