Can I fetch the data from the my database in realtime using Rails and ReactJS?
I have just started using React with Rails as this is pretty awesome combination. What I want to know is if there is a way to tell the view to update itself after a component is deleted/ created (so a record is removed/ added to the database)? Something like user after entering the page will subscribe to the database event (?).
What I have now is ComponentContainer with a custom fetch method that gets json from the server. I put it in the componentWillMount and inside a setInterval and run it every single second:
var ComponentsContainer = React.createClass({
componentWillMount() {
this.fetchRecords();
setInterval(this.fetchRecords, 1000);
},
fetchRecords() {
$.getJSON(path_to_results,
(data) => this.setState({components: data});
}, ...render methods etc.
});
Sounds like you might be looking for ActionCable, a Rails 5 thing. It uses sockets to provide server/client communication and will enable the server to send or broadcast messages to clients.
Related
I'm kind of a newb to RoR and I'm working on creating my first web app.
So...My question is, how do I create a user time sheet in RoR?
What I need to do is create a classroom time sheet for students' (Users) reading times at home.
The students (Users) are able to sign up and have a profile created. From there, I would like for them to have access to log in their reading time(s).
I have attached examples of just some simple timesheets that would work perfectly for this.
I just do not know where to start and have not been able to find any gems that could help me create this.
Time Sheet 1
TimeSheet 2
Users: Ruby part
Use Devise gem - it will save a lot of time for you.
Add Devise to user model (something like that: rails generate devise User), then autogenerate basic Devise pages (sign in, sign up, etc), see Devise tutorials:
https://launchschool.com/blog/how-to-use-devise-in-rails-for-authentication
http://guides.railsgirls.com/devise
Also you'll probably need something like Job model with fields user_id, time_spent, date or something.
Timesheets: JS part
Time tracking is more front-end part of work, so you'll need to write some JS scripts for time tracking, which will monitor user activity and then send it to Job mobel on Rails side.
Track time spent on page (example):
var page_opened;
$(document).ready(function () {
page_opened = Date.getTime();
$(window).unload(function () {
page_closed = Date.getTime();
$.ajax({
url: "/save_user_time",
data: {
'timeSpent': page_closed - page_opened,
'job_id': job_id
}
})
});
}
Also you defenetly should take a look on some basic Rails tutorials for better understanding:
http://guides.rubyonrails.org/getting_started.html
https://www.codecademy.com/learn/learn-rails
I'm trying to use ActionCable as a transport for GraphQL queries (graphql-streaming). GraphQL queries are arbitrary requests for data, so rather than having one cable per query, I'd like to have one cable and multiplex queries over that cable. The flow might be like this:
Connect to ActionCable
Subscribe to a GraphQL query
Push a query result
Something changes in the app, push another query result
User changes pages, we should unsubscribe from that query
I'm implementing subscription events as streams, so a subscription looks like this:
stream_from(event_name) { evaluate_graphql_and_push }
But when the user changes pages, I want to keep the channel connected but stop streaming from that event.
Is this possible with ActionCable?
You can call unsubscribe method on the subscription (a.k.a. channel) object.
i.e.,
channel = App.cable.subscriptions.create "ChannelName"
onPageChange = function() {
channel.unsubscribe()
}
I have an ember/rails application with three main templates, Home, Contacts, and Payments. Both the contacts and payments templates need an array of contacts. This array needs to be populated from an external api. Currently, for the contacts every time I am going to this template the external api is being hit. Ideally I would like to hit the api asynchronously when a user first signs in, grabs this data once and can refer back to it without hitting the external api until necessary.
With rails I could easily just add has_one :contacts_list for user with a postgres json column and when switching the templates conditionally refresh this whenever needed. I am curious as to the best way to deal with this problem in ember.
You should create a DS.Model for 'contact' and use a has_many on Contacts and Payments model. Then, you could specify 'async: true' like
DS.hasMany('contact', {async: true}),
This will load the contacts asynchronously if they have not been loaded already. If they have been loaded, it will simply return the loaded contacts.
I am assuming that you have the following models: Contacts, Payments.
I've used the setupController method on a route to do this type of caching. Just check to see if the content is already available, and only load it if it's not there. Something like this:
App.ContactsRoute = Ember.Route.extend({
setupController : function(controller,model){
if(!controller.get('content')){
this.store.find('contact').then(function(contacts){
controller.set('content',contacts)
});
}
}
});
As you can probably tell by this question, I am a newbie to both Ruby on Rails and Knockout.
I'm trying to build a RoR web app that will allow a user to pull up their assets data which is stored in a MySQL database, edit that data using Knockout on the front end, and then use Knockout to send the revised data back to the server via Ajax to Rails.
At this URL here: http://knockoutjs.com/documentation/observableArrays.html
it says:
The convention in Rails is that, when you pass into an action a JSON object
graph, the framework can automatically convert it to an ActiveRecord object
graph and then save it to your database. It knows which of the objects are
already in your database, and issues the correct INSERT or UPDATE statements.
I've tried doing Google searches and I haven't found anything that makes it clear to a newbie like myself. So I'm asking this question here.
In Knockout.js, when the user submits, they will be triggering a function "saveAssets" which will send the data in JSON format to "/assets" on the Rails app. The idea is that "self.assets()" will contain multiple instances of Asset objects.
self.saveAssets = function() {
$.ajax('/assets', {
data: ko.toJSON({ assets: self.assets() }),
type: "post",
contentType: "application/json",
success: function() { console.log('hella') }
});
};
When that function executes, here is the JSON that gets posted to the Rails server. Most of the Asset objects have id values, which means they are already in the server and I just want to update them, but there's also one new Asset record without an id number:
{"assets": [
{"id":1,"desc":"DWS Investments Roth IRA Mutual Fund","shares":"810.577","symbol":"SCQGX","price":"41.17","total":"33371.46"},
{"id":2,"desc":"DWS Investments Money Market Fund","shares":"20000.00","symbol":null,"price":1,"total":"20000.00"},
{"id":6,"desc":"credit card debt","shares":"-8700.00","symbol":null,"price":1,"total":"-8700.00","_destroy":true},
{"shares":"0.00","symbol":"","price":1,"total":"0.00"}
]}
And here's the Ruby on Rails controller action code:
def create
respond_to do |format|
format.json {
#assets = params[:assets]
#assets.each do |this_asset|
#a = Asset.new(this_asset)
#a.save
end
}
end
end
What am I supposed to be doing in the "create" action in order to receive the JSON array, parse it into individual "Asset" objects and save/update them to the database?
Thanks for your help!
In a Rails app I've used Faye (Rack adapter) for push notifications (for chat).
I want to use Faye for another use case (more push notifications) but I can't seem to figure it out.
In my app a model can be created from a background job so I want to refresh one of my views (say the index action) when the model gets created.
Like so:
app/models/post.rb
class Post
include Mongoid::Document
after_create :notify_subscribers
private
def notify_subscribers
Faye::Client.publish("/posts")
end
end
app/views/posts/index.html.erb
<%= subscribe_to(posts_url) do %>
uhh what do I do here? ajax call to refresh the whole page??
<% end %>
So is publishing the notification directly from an after_create callback a good idea
and when I get a message from the Faye server how to I go about implementing the "update"?
Do I just do an AJAX call to reload the data from the server? That seems like it would be slow.
Further I want to use something similar for updates to the model (say a user added some comments or the author changed the content) so thrashing the DB all the time doesn't seem like a good plan...
First of all, yes, publishing the notification with after_create is fine. What you should do in your notify_subscribers method is to publish all relevant information about the new post that you want to use in the client so that you don't have to make another unnecessary AJAX request when the notification is received.
So, for instance, if the title and content of the post are relevant for the user to see immediately after it gets created, you would do something like:
def notify_subscribers
client = Faye::Client.new('http://localhost:3000/faye')
client.publish("/posts/new", {
'title' => self.title,
'content' => self.content
})
end
...and then, in the view, you would probably use jQuery to use the data about the new post which you receive from the server. Rails code won't help you here. E.g. you would do this (assuming you're using jQuery and have included faye.js in your header):
<script type="text/javascript">
$(function() {
var client = new Faye.Client('http://localhost:3000/faye');
client.subscribe("/posts/new", function(data) {
/* do whatever you need with data */
});
});
</script>
Finally, if somehow the information you want to transfer is too complex to transfer as part of the notification, or you already have existing AJAX processes for updating your view, you could just publish the post's ID and trigger an AJAX call with jQuery in the subscribe callback function. I'd recommend this only if necessary though.