I have a new feature in my Rails project. I need to insert a "New!" flag in its menu, so user will notice that a new feature is available. Once the new feature page is visited, this "flag" must disappear.
How is it possible with Ruby on Rails?
The absolute simplest way is to look for a sawFeatureX cookie and set it when the page is rendered or the user dismisses the notification.
A more robust solution would be to store the info on the user model in the db, but that ends up giving you a lot of one-off boolean fields which may or may not be what you want.
There are MANY variations. You could use something like HelloBar to point out the new content without inlining it into the menu. So. Many. UX. Variations.
But for a one-time thing, a cookie or db-backed solution seems simple and easy.
I hate this problem.
A cookie is easy, but gross and doesn't scale. You really don't want to pay the price of sending this data back and forth on every request until the end of time.
Saving on the user record seems like a sin against database design.
A separate DB table with all these "I saw feature X" seems like such overkill and I hate something that is just going to grow without bound being in my main DB.
You can put it in Redis, memcached, but do you really need to store it in RAM? that's the most expensive place to do this.
I think the ideal solution is something like https://www.prefab.cloud/documentation/once_and_only_once which is a service (i wrote) that stores this little "bob saw X" off in a database I don't need to manage/care. It handles cacheing etc so that it's as fast as having it in Redis/etc but durable and doesn't get expired.
Related
I've built a Rails app, basically a CRUD app for memos/notes.
A notes title must be unique. If a user enters a name already taken a warning message is shown prompting them to chose another.
My question is how to make this latency for this feedback as close to zero as possible. When creating a note little UX speed bumps like this will get annoying for user quickly.
Of course the main bottleneck is the network. Inspired by Meteor (and mini-mongo) I was thinking some kind of local storage could be a solution?
I.E. When app first loads, send ALL JSON to the client with ALL note titles. The app (front end is Angular JS) could check LocalStorage (or App Cache, Web SQL?) instead of incurring a network round trip. The feedback would be instant.
I've used LocalStorage in the past to augment an app, but in the scenario it'd really seriously depend on it. I'm not sure how confident I'd be building on something that user might not have. Also as the number of user Notes/Memos I have doubts how feasible it is to send a JSON object down the wire with ALL the note titles. That might get pretty big. On the other hand MeteorJS seems to do this with no probs.
Has anyone done something similar or have any pointers? Thanks!
I don't know how Meteor works here, but you're right that storing all note titles in localStorage is not a good idea. Actually, you don't need localStorage here, you can just put it in a JS array, because you need this data only once (when checking new note title).
I think, there could be 2 possible solutions:
You can change your business requirements and allow non-unique title. Is there really a necessity for titles to be unique?
You can verify note title when user submits form. In this case you can provide suggestions for users, so they not spend time guessing vacant title.
Or, if titles must be unique only within a user (two users can have same title for their notes), you can really load all note titles in JS array and check uniqueness while users types in a title.
Or you can send an AJAX request checking title uniqueness as soon as user finished typing the title. In this case you can win some seconds.
Or you can send an AJAX request as soon as user typed in 3 symbols. The request will return all titles that begin with these 3 symbols, so you don't need to load all the titles.
I am not sure what is better perfomance whise so I ask you guys.
The problem is following:
I have a system where each User gets a certain amount of credit for certain events. So I gave my User an attribute named creditscore that gets altered on those events. Everything works well. But now I want the user to actually see what he did when and how much credit he got for this.
What would be better here:
Saving the whole history in a text attribute and add lines for each event
or
writing an extra model associated with the user and create an instance for every event.
or
or
something way different?
Since there are several events per user per day it would be either a huge text or a huge amount of instances. What would be better looking at website performance.
You absolutely do NOT want to store the history in a text attribute. Management of this will be a nightmare as will querying the data.
You could create a CreditEvent model and store the individual events in there. That would work fine.
However, before you start, check rubygems.org and ruby-toolbox.com to see if someone has already done the hard work. I know of at least one gem that seems to do exactly what you want to do:
https://github.com/merit-gem/merit
I'm using acts_as_taggable_on for tagging items across my system so that they're easily searchable.
Now I have a UX problem: I'm noticing lots of places where users choose certain minor states (for example, closing a one-time help box or moving to the next javascript-run step in a given page). We have here situations that are both too minor/numerous/dynamic/fast-changing to be put into a database table (imagine having to migrate with every UX change!), and that there is a need to persist some of these choices beyond the session.
In this case, is there anything wrong with using tags to store these simple decisions? For example, user.set_tags_on(:ui, "closed_index_help") or user.set_tags_on(:ui, "tutorial_1_done"), then showing/hiding these elements in the future by looking at the user's ui_list.
Are there drawbacks to this I'm not considering or is this a prudent way to go?
Another way might be to store the information in the SESSION. You will of course have to migrate the session information to be stored in the DB rather than the cookie, but at least that way - you only have to retrieve the session once.
I am trying to figure out a way to persist ActiveRecord objects across requests in the most efficient way possible.
The use case is as follows: a user provides some parameters and clicks "show preview". When that happens, I am doing a lot of background computation to generate the preview. A lot of ActiveRecord objects are created in the process. After seeing the preview, the user clicks "submit". Instead of recomputing everything here, I would like to simply save the ActiveRecord objects created by the previous request. There is no guarantee that these two requests always happen (e.g. the user may opt out after seeing the preview, in which case I would like to remove these objects from the persistence layer).
Are there any proven efficient ways to achieve the above? Seems like it should be a common scenario. And I can't use sessions since the data can exceed the space allotted to session data. Moreover, I'd rather not save these objects to the DB because the user hasn't technically "submitted" the data. So what I am looking for is more of an in-memory persistence layer that can guarantee the existence of these objects upon executing the second request.
Thanks.
You can save you a lot of unnecessary work by just saving it to the DB and not add other not-really-persistent-layers to your app.
A possible approach: Use a state attribute to tell, in what state your record is (e.g. "draft", "commited"). Then have a garbage collector run to delete drafts (and their adjactent records) which haven't been commited within a specific timeframe.
Im not sure if not saving the object in a dirty state would be the best option as you could manage this with some sort of control attribute like state or status.
Having this would also be pretty great as you could validate data along the way and not do it until the user decides to submit everything. I know Ryan Bates has a screencast to create this sorts of complex forms (http://railscasts.com/episodes/217-multistep-forms).
Hopefully it can help.
Is the reason the data can exceed the space allotted to session data because you're using cookie based sessions? If you need more space, why not use active record based sessions? It's trivial to make the change from cookie based sessions and is actually the recommended way (so why it's not the default I don't know)
I'm developing a webapp that allows the editing of records. There is a possibility that two users could be working on the same screen at a time and I want to minimise the damage done, if they both click save.
If User1 requests the page and then makes changes to the Address, Telephone and Contact Details, but before he clicks Save, User2 requests the same page.
User1 then clicks save and the whole model is updated using TryUpdateModel(), if User2 simply appends some detail to the Notes field, when he saves, the TryUpdateModel() method will overwrite the new details User1 saved, with the old details.
I've considered storing the original values for all the model's properties in a hidden form field, and then writing a custom TryUpdateModel to only update the properties that have changed, but this feels a little too like the Viewstate we've all been more than happy to leave behind by moving to MVC.
Is there a pattern for dealing with this problem that I'm not aware of?
How would you handle it?
Update: In answer to the comments below, I'm using Entity Framework.
Anthony
Unless you have any particular requirements for what happens in this case (e.g. lock the record, which of course requires some functionality to undo the lock in the event that the user decides not to make a change) I'd suggest the normal approach is an optimistic lock:
Each update you perform should check that the record hasn't changed in the meantime.
So:
Put an integer "version" property or a guid / rowversion on the record.
Ensure this is contained in a hidden field in the html and is therefore returned with any submit;
When you perform the update, ensure that the (database) record's version/guid/rowversion still matches the value that was in the hidden field [and add 1 to the "version" integer when you do the update if you've decided to go with that manual approach.]
A similar approach is obviously to use a date/time stamp on the record, but don't do that because, to within the accuracy of your system clock, it's flawed.
[I suggest you'll find fuller explanations of the whole approach elsewhere. Certainly if you were to google for information on NHibernate's Version functionality...]
Locking modification of a page while one user is working on it is an option. This is done in some wiki software like dokuwiki. In that case it will usually use some javascript to free the lock after 5-10 minutes of inactivity so others can update it.
Another option might be storing all revisions in a database so when two users submit, both copies are saved and still exist. From there on, all you'd need to do is merge the two.
You usually don't handle this. If two users happen to edit a document at the same time and commit their updates, one of them wins and the other looses.
Resources lockout can be done with stateful desktop applications, but with web applications any lockout scheme you try to implement may only minimize the damage but not prevent it.
Don't try to write an absolutely perfect and secure application. It's already good as it is. Just use it, probably the situation won't come up at all.
If you use LINQ to SQL as your ORM it can handle the issues around changed values using the conflicts collection. However, essentially I'd agree with Mastermind's comment.