As mentioned in this question How can I check for live updates without using setInterval/timeout?
I am aware of websockets, but im interested in maybe a more simplistic solution, could I effectively just let php update a key value pair file and have all pages update accordingly only if a value has changed?
eg. a bidding site where instead of polling for 100 or more items I only update the whole application when someone has essentially placed a bid , making it a one way flow
place bid->process form->update database->refresh all instances of said bid currently open in other windows - hence the file that will store the info and maybe two way binding setup via angular template , or will caching be a issue?
how else do I update the views but all based on the action of someone placing a bid(submitting a form)?
Any ideas as to this approach?
You should use websockets...
if you are new to socket.IO you can use some backend as a service like firebase, this should be really easy to implement.
Related
I have a Rails app and I would like to save the state of my divs if a user is logged in.
Exemple: someone is logged in and clicks on a div to hide it. I would like that to be stored somewhere so if he opens the page again, this div will still be hidden.
I don't want to use local storage, because I want the state to be saved if I go on a mobile or another computer/browser too. It needs to be the same everywhere, depending on the user.
I was thinking about storing each state of each div as boolean in my user model, but this idea does not sound clean at all and I don't think I'll be able to sleep at night if I do this
Any idea?
I think React/Redux would handle that easily (maybe not and it's just local too?) but at the moment I am stuck with Rails..
Thanks a lot!
React/Redux will not save you since nothing magical happens there except for some convenient binding. Behind the curtains they use the same "browser features".
I'm afraid you need to find the best trade-off for you. I'll post some ideas:
Stick to localStorage
Probably not need to say much here since you investigated this.
Bound to Chrome
Since Chrome 25, they gave access to storage.sync and you can develop your system around this. Always try to retrieve data, if there is any and then remember to persist new data and sync it. Maybe other browsers support this, but the downside is you'll have to have the code for those as well.
Experiment with webRTC
You can transfer data between two browsers using webRTC. While I don't have many experience with this, I can't recommend it, but it's definetly an approach you'd like to consider.
Maybe check this project: https://github.com/cjb/serverless-webrtc
Create your own storage
Pick up a storage (I think even firebase/dynamodb will work) and build a system to save user preferences. If you have Auth0, you can keep some logic in there and since they are offering SSO, it will be fairly easy to check for those customizations.
Remember, since you don't want to use localStorage, you'll need to keep sessions and save this preference under a user_id or something.
In my opinion, there is no best solution for this but only what you want to trade in order to support this. If you don't mind keeping the whole business logic, I don't see why creating a storage for this will make it too slow. Measure the load and optimize along the way.
It sounds like this is a user preferences type of configuration. As such, you can probably just store the settings as single field in your User modal. For that you could use either a serializable hash or json type.
So assuming you have a app/models/user.rb
Add an run migration
rails g migration add_view_options_to_users view_options:text
rake db:migrate
Add this to your model
class User < ActiveRecord::Base
serialize :view_options, Hash
end
Then in your users controller you can post to your update action so you'll want to add a field to permitted_params
private
def permitted_params
params.require(:user).permit(:view_options, #other options etc.)
end
From here you'll need to write some javascript to post view_options to users/update or custom route if you prefer. But basically each field's value will be saved inside a controller action so something like:
def update
#user = User.find(params[:id])
opts = #user.view_options || {}
user.view_options = opts.merge(params[:view_options])
if #user.save
render json: { status: true, user_id: #user.id }
else
render json: { status: false, errors: #user.errors.full_messages }
end
end
I am currently working on a project using Symfony2 and seeking some advice on that.
I am thinking of a hybrid application in two(2) different ways a) Login Page shall use traditional form with CRF Token and let symfonty2 handle it. b) All Inner pages ( which potentially are modules ) I want them to be non AJAX, but the other activities inside that shall behave like a Single Page.
For example I have an employee module. When user clicks on that it is entirely loaded from Server ( all the templates and forms etc ) now each activity under employee module like add/update delete/view etc shall be loaded through AJAX and response to be returned in JSON i.e AngularJS.
I am currently thinking of using FOSUserBundle to return html on initial request and then based on request type Accept: application/json it will return the JSON ( remember the add/updat delete/view part? ).
My question is it a better idea to use Angular Partials (html) files or Symfony2 Twig? or would it be better to use Angular JS, but let those partials be rendered by Symfony2 twig? ( I am thinking of Forms here, would want to validate that both from client and server side )
Has any one been through similar problem, if yes then what approach was used to develop HYBRID application using AngularJS and Symfony2 or any other framework? any relevant ideas are appreciated.
I was in the same situation you are. AngularJS+Symfony2 project, REST API, login using FOSUserBundle, etc.
... And every way has pros and cons, so there is no right way, i'm just gonna say exactly what i did.
I choose AngularJS native templates, no CSRF validation, a base template built using Twig, server-side validation, use of the FOSJSRoutingBundle, and some helpers (BuiltResponse and BaseController).
Why native templates?
With the use of verbatim, we solve the variable problems, but we gonna have a more complex logic in our templates.
We also will have a less scalable application. All our forms templates are doing a request in the Symfony application, and one of the best pros of the AngularJS is load our controllers, templates, etc from a storage service, like S3, or CDN, like Cloudfront. As there is no server-side processing, our templates would load so much faster. Even with caching, Twig is slower, obviously.
And both, Twig and AngularJS templates, are really complex to manage, in my own experience. I started making them together, but was painful to manage.
What i did?
I created static templates in front-end, with the same field names, it's not really good. We need to update the templates every time we update the forms, manually. But was the best way i found. As the field names are equal, we won't have problems to ajust the model names in the Angular controllers.
And if you are creating the software as a service, you will need to do it anyway. Will you not load the form templates from the application in a mobile app, right?
Why no CSRF validation?
We don't use CSRF validation in a REST API, obviously. But, if you wanna do it, you need to make a request every time you load a form, to get the CSRF token. It's really, really bad. So, we create a CRUD, and also we need to create a "csrf-CRUD", 4 routes more. That doesn't make any sense.
What i did?
I disabled the CSRF in the forms.
Base template?!
Yep. A base template is just to load any route in our application. Here is what i'm doing:
This will help us to avoid errors when users are going directly to some Application URL if you are using html5 angularjs urls. Simple like that.
Server-side validation, why?
If we do a validation in the Angular, we need to do the same in the server-side, so we have 2 validation codes to maintain. That is painful. Every change we do in the form, we need to change the validation in the front, validation in the back and also the Angular static form. Really, really painful.
What i did?
I basically did a server-side validation using the Symfony constraints. For every request, the application validates the form and check if any error was found, if yes, it gets the first one and send it as a response.
In the AngularJS, the application checks if there is any error inside of the errors key. So, we have a proccess used in all application to do any form request. It's like that:
And the routes?
There is another problem: the routes. Put the url directly is not a reliable way. If we change anything in the url, that route is gone and the users won't like that.
To fix that, we can use the FOSJsRoutingBundle. With that library, we can put the route name directly in the Angular controller, and it will fill with the exact url of the route. It's completely integrated with the Symfony, so parameters will work very well.
Instead using the url directly, we can do it:
Routing.generate('panel_products_show', {id: $routeParams.product_id});
And voilá! We get the route url.
That will solve the biggest part of the problems you have. But there are more.
Problem 1 - Form inputs
The forms from Symfony generally have a prefix, like "publish_product", so every field has a name like [publish_product]name. Ah, how that was a problem for me.
In the Angular, publish_product is not considered a array. You need to put the single quote to do this, like ['publish_product']name. And it's really bad, we need to change every key to use this format. In AngularJS, i was doing like that:
{{ formData('[publish_product]name') }}
Absolutely stupid.
The best solution was simply remove the form prefix in the Symfony, using the createNamedBuilder method instead just createBuilder. I let the first parameter null, and yeah, we don't need to use the prefix anymore. Now, we use:
{{ formData.name }}
So much better.
Problem 2 - Routes hard do maintain
Every request can return anything, i need to repeat much code. That is really hard to maintain, so i just create some application rules, built responses, a BaseController, etc.
createNamedBuilder
createNamedBuilder is a big method. We need to do this, for every form we have:
It's simple to solve. I just created a BaseController and i'm extending every controller from it. I created a simple method that does it.
For every route, we do not need to repeat 3 lines, much better.
Responses
When my application started growing, i had a serious problem: all my responses are different. That was really hard to maintain. For every request i was doing, sometimes i was using "response", sometimes "data", the error messages were lost in the response, etc.
So, i decided to create a buildResponse, that i just need to set some parameters and i get the same result for every route, even GET routes.
response key shows me the status and the message. It can be error or success, and the message os a optional field, that can come blank. For example, a success status with the message "You created the product".
data key shows me any information i need. For example, the user added the product, and now he needs the link to see it. In the data, i put the url of the post, and i easily can get it from the AngularJS controller.
notifications is a specific key for my business logic. Every action can return a notification to the user.
It doesn't matter what keys you have. The most important thing is have a standardized response, because when your application grows, it will be really helpful.
That is a route from my controller:
Completely standardized. The Scrutinizer code quality tool says all my routes are duplicated. :D
Have a BaseController and a builtResponse will help you so much. When i started refactoring my code, each route lost about 4-10 lines.
Details: getFormError return the first error of the form. Here is my method:
public function getFormError(FormInterface $form)
{
if ($form->getErrors()->current()) {
return $form->getErrors()->current()->getMessage();
}
return 'errors.unknown';
}
... And the parameters from the buildResponse are:
1. Status. I get it from a constant in the BaseController. It can be changed, so i believe is important do not use a string value in each route.
2. The translation message. (I use a preg_match to check if it has a translation format, because getFormError already translates the error).
3. The data (array) parameter.
4. The notifications (array) parameter.
Other problem i'm gonna have
The project just have one supported language until now. When i start to work in a multilingual version, i'm gonna have another big problem: maintain 2 versions of the translations: the back-end messages and validations and the text from the front-end. That probably will be a big problem. When i get the best approach, i'll update this answer.
I took some months to get the this approach. So many code refactorings and probaly much more in the future. So i hope it help someone to do not need to do the same.
1. If i get a better way to do this, i'll update this answer.
2. I'm not good at writing english, so this answer probably will have many grammatical errors. Sorry, i'm fixing what i'm seeing.
I have an application where the application's user relates to an HTML page during the application's runtime.
During runtime, the HTML file is being continuously updated. In order to handle every update, the HTML file is being refreshed at a fixed interval.
Is there any other better way to achieve this with more efficiency and/or to hide the refreshing technique from the user's perspective?
Any help will be greatly appreciated.
If what you're doing doesn't involve retrieving data from a server, and instead involves some kind of process that occurs on the page itself, like a clock, I would use setInterval
setInterval(function(){myFunction()},1000);
This would call myFunction() every second, and inside of that function you can change visual elements as appropiate.
You may also want to consider using a Javascript MVC framework such as Backbone.js or Angular.js, which handle changing the appearance of html elements mapped to javascript variables over the lifetime of an application for you.
From your question it sounds as if your updating the HTML file on the server in response to user actions. I'm guessing that's not literally what you meant. If it is, though, there are almost certainly better ways to do what you want to do -- depending on what, exactly, it is.
If you are just showing new information to the user, you will want to use Javascript to update the page's DOM. The easiest way for a beginner to do that would be to start by looking at jQuery tutorials. With Javascript (possibly aided by jQuery) you can easily update the content of any part of your page, without needing to actually change the original HTML file in any way.
If you want the page to be updated for everyone who visits it at a later date, then you need to put the new information in a database, and get the content from the database when you the page is requested or loaded.
It would greatly help if you specified exactly what you were trying to do.
I'm working on a real-time JavaScript Application that requires all changes to a database are mirrored instantly in JavaScript and vise versa.
Right now, when changes are made in JavaScript, I make an ajax call to my API and make the corresponding changes to the DOM. On the server, the API handles the request and finishes up by sending a push using PubNub to the other current JavaScript users with the change that has been made. I also include a changeID that is sequential to JavaScript can resync the entire data set if it missed a push. Here is an example of that push:
{
"changeID":"2857693",
"type":"update",
"table":"users",
"where":{
"id":"32"
},
"set":{
"first_name":"Johnny",
"last_name":"Applesead"
}
}
When JavaScript gets this change, it updates the local storage and makes the corresponding DOM changes based on which table is being changed. Please keep in mind that my issue is not with updating the DOM, but with syncing the data from the database to JavaScript both quickly and seamlessly.
Going through this, I can't help but think that this is a terribly complicated solution to something that should be reasonably simple. Am I missing a Gotcha? How would you sync multiple JavaScript Clients with a MySQL Database seamlessly?
Just to update the question a few months later - I ended up sticking with this method and it works quite well.
I know this is an old question, but I've spent a lot of time working on this exact same problem although for a completely different context. I am creating a Phonegap App and it has to work offline and sync at a later point.
The big revelation for me is that what I really need is a version control between the browser and the server so that's what I made. stores data in sets and keys within those sets and versions all of those individually. When things go wrong there is a conflict resolution callback that you can use to resolve it.
I just put the project on GitHub, it's URL is https://github.com/forbesmyester/SyncIt
I am writing my first Rails app using the twitter gem. I'm simply retrieving search results and trying to cycle through them individually every 5 seconds or so.
My thought was to create a variable and have this variable represent the array index and simply update this variable dynamically with Javascript (every 5 seconds or so). What's the best way to achieve this on the client-side? AJAX? Javascript?
Does this make sense? I will be glad to provide more context if helpful. Thanks.
Sounds you're trying to build a "recent tweets" marquee of some sort. Without knowing your requirements, you could try simply loading the ten most recent tweets in Rails, putting them in ten hidden divs, and then using jQuery just to cycle through the different tweets on the page.
If it is a requirement to "update" the most recent tweets without the user refreshing the page, then yes, you'd probably need an AJAX call.
It's hard to tell what you think you're asking: by the time your JavaScript is executing the server is no longer involved.
If you want to update some sort of count on the server side and persist it in a meaningful way, you can do so via Ajax.
What are you actually trying to do, though?
Ruby runs on the server while JavaScript (usually) runs on the client.
The Ruby generates an HTML document (perhaps with embedded JS) and the server delivers it to the client.
At that stage the Ruby has finished executing. The only way to do anything further with Ruby would be to make a new HTTP request to the server. This could be done by following a link, submitting a form, setting location.href, using XMLHttpRequest or numerous other techniques.
This would cause the Ruby program to be executed again (or a different one to be executed) which would do whatever it did with the input data.
You cannot simply "set a variable" on the server from the client.
In my particular case, I used ruby's .to_json method to convert the data and then manipulated it with javascript. This gave me the flexibility to loop through the data pretty seamlessly. Atleast it seemed to work for my particular situation. Thanks for the help guys!