I want to try to make a simple real-time chat Rails web app, but I thought I would need some kind of let's call it "event listener" to be able to keep track of sent messages so the receiver user's feed get updated with the new message. Also, for the Typing... notice box.
I hope I explained myself.
I guess I could do it in a very troglodyte way to achieve this like follows:
main.js:
while(true) {
$.get('/user-you-are-talking-to/are-there-new-messages', function(data) {
if (data['are_there_new_messages'] === true) {
$('#conversation').append(data['new_message']);
}
});
}
conversation_controller.rb:
# routed by /user-you-are-talking-to/are-there-new-messages'
def new_messages?
unless #new_messages.blank?
#json = []
#json[:are_there_new_messages] = #new_messages.count > 0
#json[:new_message]= #new_messages.shift
render json: #json
end
end
But well aside than the fact that I didn't test that code, a while loop and constant requests to the server seem like a really really bad idea, obviously.
I would like to know if Rails has a built-in feature like this, but as far as I know it doesn't, unlike frameworks I've worked with like Laravel. If there's not a built-in tool for this, how can I do this app?
Real time apps are usually done with websockets.
https://github.com/eventmachine/eventmachine
https://github.com/igrigorik/em-websocket
Or if on a hosted service you can use a publish/subscribe service such as Pusher or PubNub.
Otherwise, you would do polling which is what you have in your example.
Rails 5 will come with Action Cable:
Action Cable seamlessly integrates websockets with the rest of your Rails application. It allows for real-time features to be written in Ruby in the same style and form as the rest of your Rails application, while still being performant and scalable. It's a full-stack offering that provides both a client-side JavaScript framework and a server-side Ruby framework. You have access to your full domain model written with ActiveRecord or your ORM of choice.
But while you're waiting for it, you can use a number of existing solutions, some of which #dinomix listed.
Another option is Faye (never used, but heard good things).
Related
We are planning to make a "large" website for I'd say 5000 up to many more users. We think of putting in lots of real time functionality, where data changes instantly propagate to all connected clients. New frameworks like Meteor and DerbyJS look really promising for this kind of stuff.
Now, I wonder if it is possible to do typical backend stuff like sending (bulk) emails, cleaning up the database, generating pdfs, etc. with those new frameworks. And in a way that is productive and doesn't suck. I also wonder how difficult it is to create complex forms with them. I got used to the convenient Rails view helpers and Ruby gems to handle those kind of things.
Meteor and DerbyJS are both quite new, so I do expect lots of functionality will be added in the near future. However, I also wonder if it might be a good idea to combine those frameworks with a "traditional" Rails app, that serves up certain complex pages which do not need realtime updates. And/or with a Rails or Sinatra app that provides an API to do the heavy backend processing. Those Rails apps could then access the same databases then the Meteor/DerbyJS app. Anyone thinks this is a good idea? Or rather not? Why?
It would be nice if anyone with sufficient experience with those new "single page app realtime" frameworks could comment on this. Where are they heading towards? Will they be able to handle "complete" web apps with authentication and backend processing? Will it be as productive/convenient to program with them as with Rails? Well, I guess no one can know that for sure yet ;-) Well, any thoughts, guesses and ideas are welcome!
For things like sending bulk emails and generating PDFs, Derby let's you simply use normal Node.js modules. npm now has over 10,000 packages, so there are packages for most things you might want to do on the server. Derby doesn't control your server, and it works on top of any normal Express server. You should probably stick with Node.js code as much as possible and not use Rails along with Derby. That is not to say that you can't send messages to a separate Rails app, but since you already have to have a Node.js app running to host Derby, you might as well use it for stuff like this.
To communicate with such server-side code, you can use Derby's model events. We are still exploring how this kind of code works and we don't have a lot of examples, but it is something that we will have a clear story around. We are building an app ourselves that communicates with an email server, so we should have some real experience with this pretty soon.
You can also just use a normal AJAX request or send a message over Socket.IO manually if you don't want to use the Derby model to do this kind of communication. You are free to make your own server-side only routes with Express along with your Derby app routes. We think it is nice to have this kind of flexibility in case there are any use cases that we didn't properly anticipate with the framework.
As far as creating forms goes, Derby has a very powerful templating system, and I am working on making it a lot better still. We are working on a new UI components feature that will make it possible to build libraries of self-contained UI widgets that can simply be dropped into a Derby app while still playing nicely with automatic view-model bindings and data syncing. Once this feature is completed, I think form component libraries will be written rather quickly.
We do expect to include all of the features needed for a normal app, much like Rails does. It won't look like Rails or work like Rails, but it will be similarly feature complete eventually.
For backend tasks (such as sending emails, cleaning up the database, generating pdfs) it's better to use resque or sidekiq
Now, I wonder if it is possible to do typical backend stuff like
sending (bulk) emails, cleaning up the database, generating pdfs, etc.
with those new frameworks. And in a way that is productive and doesn't
suck. I also wonder how difficult it is to create complex forms with
them. I got used to the convenient Rails view helpers and Ruby gems to
handle those kind of things.
Also, my question is not only about background jobs, but also about stuff one can might do during a request, like generating a pdf, or simply rendering complex views with rails helpers or code from gems. –
You're mixing metaphors here - a single page app is just a site where the content is loaded without doing a full page reload, be that a front end in pure js or you could use normal html and pjax.
The kind of things you are describing would be done in a background task regardless of the fornt-end framework you used. But +1 for sidekiq if you're using ruby.
As for notifying all the other users of things that have changed, you can look into using http://pusher.com or http://pubnub.com if you don't want to maintain a websocket server.
I'm a newbie to writing service-oriented applications, so this might be a trivial question for some.
My current setup is something like this:
1 - A base rails app. Also contains the routes and some application logic.
2 - A few services. I have extracted these from my base rails app. They are mostly resources that were DB extensive or used a no-sql solution.
So, what I have ended up doing is something like this
in my rails app, I have a places controller which responds to all the basic CRUD operations on places. Internally it does a HTTP call to the places service.
def show
req = Typhoeus::Request.new('http://127.0.0.1:7439/places/#{params[:id]}.json')
#places = req.response.body
end
The problem is, if I make more than 1 service call, then how to make sure that I have the response for all before rendering the views ? Also, even with 1 service call, how does the Rails rendering process work ? So for example, if the service takes a long time to respond, does the page gets rendered or does it wait infinitely for the response ?
I cannot answer your question specifically about Typhoeus as I've never used it, but I will try to answer more generally about this problem in SOA and hopefully it will be helpful.
The common thread is that the UI should be composed from many services and tolerant to the possibility that some of those services may be down or unresponsive.
You have a few options:
1) Drop down and do the composition from the browser. Use something like Backbone and make Ajax requests to each of the services. You can make many of these requests asynchronously and render each part of the page when they return - if one doesn't return, don't render that part - or have Backbone render some sort of placeholder in that region.
2) If you want to build up a model object in your controller (as in your example), you have to somehow handle timeouts and again - use a placeholder model for whatever service is being unresponsive. The nice thing about this is that, depending on the service, you can decide how critical is to have the data and how much time you're willing to wait before you consider it a timeout and move on.
Take, for example, the Amazon product page. It's very important to get the details about the product from its service - if you don't get that, it's probably worth throwing an error to the browser. But if the "Customers Who Purchased This Product Also Purchased..." service is not responding, it's OK to just stop waiting for it and render the page without it.
Again - I don't know Typhoeus so I'm not sure how to manage this using it, but hopefully this helps. Good luck!
I am a rails developer working on a cakephp site. The more work they send me, the more php code I write and thus the more dependence on php we introduce. What I want is to stop writing new features in php and start writing them in rails. Our resources are limited and the existing php site is huge so a full port from cake to rails is not possible.
Is there some way to write new features in a rails app while maintaining and allowing access to all the functionality of the old php (and vice-versa)?
It seems I would need a route aware app to traffic requests to either php or rails, but then we run into the issue of, for example, existing user functionality written in php not being available to the rails app and vice-versa.
What about something to translate ruby into php? That way I could start writing my model stuff in ruby/rails rather than php.
I feel like my question is muddled by the fact I do not know how to ask the questions I want to answer, so hopefully this is understood.
As always, thanks in advance!
One approach that you may find useful is to leverage the power of your web-server to properly re-write and delegate requests to two different systems. If you can design your new Rails application to use the same database records as the old one, with models mapping to the old tables directly, and ensuring that sessions established by one are valid in the other, you have a lot of latitude in how you go about doing this.
Apache has a very full-featured URL rewriting and proxying system that can be configured to direct "legacy" parts of your site to an existing set of PHP scripts while directing all other traffic to the new Rails application. You will need to be careful to ensure the design of both applications are nearly identical or it may seem strange to users.
Another approach that helps ensure a consistent appearance is to strip out a lot of the theme from your PHP application. By creating very bare-bones pages that only expose the required functionality on each page, Rails can fetch these by passing through any relevant session authentication information and re-frame them in the right layout.
This way you can preserve existing functionality and have it embedded inside your new application. You can use something as simple as open-uri or the curb gem to handle this HTTP-level delegation.
You would end up with controllers that look like this:
class PaymentController < ApplicationController
def index
#content = fetch_legacy_url('/payments/index.php'))
end
end
The fetch_legacy_url method would create an HTTP fetch request that includes the required headers, cookies, and so forth, and return the response body. Your view then ends up looking something like this:
<%= #content =>
From there you can shunt parts of the PHP layout over to the Rails app piece by piece. For instance, ripping out large chunks of static HTML and putting them in the Rails template would reduce the amount of actual PHP code you have to port.
It's a bit messy to maintain two applications in parallel, but as you point out the alternative is to keep accumulating technical debt and making the inevitable re-write that much more significant an undertaking.
The first step would be to experiment and see if you can create a Rails environment that uses your existing data, or at least the data relevant to the new functionality you intend to build out.
Can anyone suggest me the approach of implementing the live chat functionality in my ruby on rails application? Is there any plugin exists to implement this functionality?
Thanks
Yes, Juggernaut. Unfortunately it requires flash, but it works pretty well otherwise. You might also want to look at the WebSockets standard, as there is flash emulation for it in browsers that don't support it yet.
A very simple (possibly not very efficient) implementation would involve using AJAX to send new messages and receive conversation updates. The conversation could be a database backed object shared amongst the users involved. Each user's page would then poll for updates to that object.
I'm looking at Rails development as a backend to a Flex application and am trying to figure out the communication layer between the Rails app and the Flash Player. All of the things I am finding suggest using SOAP web services to communicate.
However, Flash supports AMF which is nice and fast (and native). Is there any way of communicating over AMF from a Rails app, whilst supporting all the "nice" things about AMF (automatic type conversion, data push etc).
There is WebORB or RubyAMF which you can use to respond in AMF from Rails, the approaches are a bit different for each one so it depends on your needs. RubyAMF is discussed in the closing chapters of the Flexible Rails eBook which is a good resource on using Rails with Flex.
I'm in the middle of writing a rails/flex application and we're moving to using a JSON communication within the REST framework. Simple HTTP requests from the Flex side handling JSON responses seemed like the best way to decouple the client and server. XML is just as easy.
For what it's worth, we're using the PureMVC framework on the flex side as well, keeping the responses in a client-side model.
You wouldn't use SOAP web services but rather 'native' REST web services, which are native in Rails. The book quoted by DEFusion above is actually about that: how to use a FLEX client as the front-end of a Rails application using REST (meaning XML).
The AMF protocol has primarily been built by Adobe as a binary protocol to allow FLEX front-ends to talk to CodeFusion and of course Java server applications. It's not free, apart from using Adobe's BlazeDS for which you actually won't have much support. And then of course, you'll have to choose a plugin capable of talking to BlazeDS using the AMF protocol (again, see DEfusion's posts) and rely on it.
You'd be surprised how well direct Flex to Rails via REST works, plus you don't have to rely on third-parties. I'd recommend you try it.
Hope this helps
Go with RubyAMF if you want an MVC style interaction with contollers that can respond to/generate AMF.
Use WebOrb for any other style, including direct access to model objects.
I've built apps using all three methods (WebOrb, RubyAMF, REST)...
WebOrb for Rails is pretty much dead, it hasn't been updated in quite sometime. That said I was able to create a bit of Flex/Ruby magic that makes Flex access to Rails' model objects transparent... if you're interested I'll dig it up and send it to you.
RubyAMF is nice, but not as Flexible (ha!) as WebOrb.
REST returning JSON is a snap, and if I have to build another one of these (I hope not) that's what I'll continue to use.
YMMV.
There's a Rails plugin called WebORB for Ruby on Rails which uses remoting with AMF.
You can use WebORB or RubyAMF, or just plain XML - Rails is pretty smart when it comes to XML, with a few gotchas here and there.
We use XML to speak between our Rails apps and our Flex web application, almost exclusively. It's pretty simple.
For retrieving data from your Rails app, just create an HTTPService with result_type of e4x, and call your url. In your rails controller, do something like:
def people
render :xml => Person.all.to_xml
end
Sometimes, Rails will add the tag to the end. If this happens, change your controller to:
def people
render :xml => Person.all.to_xml.target!
end
If you want to send data to your Rails app, it's just as easy..
<mx:HTTPService id="theservice" url="http://localhost:3000/svc/add_person" method="POST">
<mx:request>
<person>
<first>Firstname</first>
<last>Lastname</last>
</person>
</request>
</HTTPService>
and in your controller:
def add_person
p=Person.create(params[:person])
render :xml => {:result => "Success"}.to_xml.target!
end
Kevin