I'm endeavoring to learn rails and am doing so by completing some super basic projects. The current thing I'm working on is a higher-lower game - the user guesses a number, and the server checks the guess against a randomly generated secret number, and responds if the guess is 'higher' or 'lower' than the actual number.
I've got most of the game complete, but I've realized I have no idea how to actually implement notifying the user if the guess was too high or too low. Other view changes in the game are handled by rendering a whole other page, but for this one I wish to display new text in the current page.
This question isn't really to solve my problem per se, I'm just trying to get pointed in the right general direction with controller-view interactions such as these.
Currently the only way I can think to do this is
Logic in the View
Make the data of whether the user guessed higher or lower available by using an instance variable, then use ruby in the html.erb view to determine what text to display based off this.
This seems ... dumb, and in violation of things I've learned about MVC in the past. Any other suggestions would be appreciated.
The cleanest way to do this in the "Rails" way would be to have a new path in your controller, for example show_result, and render a javascript view (show_result.js.erb). Then use a simple line of javascript to update the current DOM. Remember to set your form submission or your link to :remote => true and you're good to go.
Related
So I am writing an app in Rails 5, and I am interested in the security issues of a simple feature I am trying to write. Users make Picks, which are secret from one another until a certain time. If I pass:
#picks = Pick.all
which contains everyones picks,
to the view with the controller, and then filter what is displayed depending on who the user is on the view, would a user be able to access that #picks variable using nefarious methods? At first I thought yes, but now I am thinking that the user just gets the raw view sent with no #picks variable. Unless users can sneaky dev their own html views?
Disregard that it's probably a better idea to do the filtering in the controller anyway, I just want to see if you can expose variables if you give them in full to the view and then filter them there.
Short Answer:
No, the client cannot access the #picks variable directly. Your view would have to display the value of #picks in the view in order for the browser to receive it.
Long Answer:
However, it would be good practice to limit the data assigned to #picks before it gets to the view. As your codebase grows and ages, and perhaps other developers start maintaining it, you may not remember that the #picks variable contains data that should not be displayed in the view.
Six months down the road, when the client wants to update the view based on new feature enhancement, you do not want to rely on the developer who is modifying the view to know that #picks contains sensitive data.
Make life easy on future developers (including you) by restricting the content of #picks to those records that the user is allowed to see at the time. Using the code suggested in the comments is a good idea:
#picks = current_user.picks
Or better yet, add a method to your model that contains the business logic for determining which picks are available to the user at a given time:
class User < ApplicationRecord
...
def authorized_picks
# code that returns the picks this user is allowed to see right now
end
...
end
And then your controller code is:
#picks = current_user.authorized_picks
That way all of your business logic is in the model, where it belongs 90% of the time. This also allows you to keep your code DRY by having the authorization logic all in one place.
Keep your code simple and DRY and you will thank yourself down the road.
No, They won't be able to get the instance variable which we use in haml/erb files. They just get the raw html.
As Ruby on rails does server rendering, all instance variables will be used to prepare view at the server side.
Anyways filtering should be done on controller side as best practice.
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 have a Rails Application where I want to present user with a sequence of Questions in a particular order. A user cannot proceed to the next question unless he has answered the previous one.
Here are some design issues I need help on for an efficient implementation:
To fetch a list of questions for a user I need to make an expensive
db call. Once for a new session, the list if fetched I simply want the
user to see the questions in a particular order starting from the
first question. If the user had attempted some questions in
a pervious session he will jump to the question he last left off. How
to implement it efficiently? I believe I need caching here.
On rendering the views :
How to render the view for this feature? I can have a controller with
the initial question template. When user attempts the question, should
I have question-answer options text updating with AJAX? Do I have to
use jquery for the purpose or any Rails helper could be of help here?
Any design help, rails features-gems I could make use of will be welcomed.
My answer is not specific to Ruby on Rails, but it should still work.
First I wouldn't load data that you potentially won't use in advance. If you have 10 questions, and you only show one at a time, then I would just load the first and then once the user has finished the first, go ahead and load the second. No need to load all ten because maybe the user never makes it to question 10.
Assuming the user leaves pre-maturely, you can just make an AJAX call to pick up where you left off.
I would agree that you should cache those questions though.
The steps would look like this then:
First question - loaded via AJAX. Answer and progress saved via AJAX call.
If (1), then second question loaded via AJAX. Answer and progress saved via AJAX call.
Repeat until questions done.
This way you can use user/login information to make an AJAX call to pick up where you left off. I would imagine this would make your database calls much less expensive.
Apologies in advance as I'm sure this topic has no doubt been asked before but I couldn't find any post that answers my specific query.
Bearing in mind that I'm new to MVC this is where I have got to. I've got a project developed under VS 2010 using the MVC 3 framework. I've got a search page which consists of 6 fields and a nested model which itself holds around 3 fields.
I can successfully post all this data back to itself and the data is successfully passed as a model and back agian so the fields keep the data which the user has supplied.
Before I move on to actually using this search criteria on another view a thought hit me. I want to keep this search criteria, and possibly even the search results in memory for the duration of the users session.
The reasoning behind this is simply to save my users time by:
a) negating the need to keep re-inputting their search criteria regardless of how they enter or leave the search page
b) speed up the user experience by presenting the search results more quickly
The later isn't as important as the first requirement.
I've done some google searches and indeed had a look through this site on similar topics. From what I've read using sessions (which I would typically use if developing a PHP site) is a no no. From the reasons I've read as to why you shouldn't use sessions seem valid and I'm happy to go along with it.
But now I'm left in a place where I'm scratching my head wondering to myself what exactly is best practice to achieve this simple goal that could be applied to similar situations later down the line in the project.
I also looked at the OutputCache method and that didn't behave as I expected it to. In a test I set the timeout for 30 seconds. After submitting a search I clicked the link to my search page to see if the fields would auto-populate, they didn't. But then clicking the search button the values in the cache were retrieved. I thought I was making progress but when I tried to submit a new value the old value from the cache came back i.e. I couldn't actually change my search criteria with the cache enforced. So I've discounted this as an avenue to explore.
The last option seems to suggest the use of cookies as the most likely candidate, but rightly or wrongly I feel this isn't the best solution. I would have thought the MVC 3 design pattern would have an easier and recommended method of persisting values. I'm sure there is but I've just not discovered it yet.
I have started to use JQuery and again this has been mentioned but I'm not sure this is right direction to take either.
So in summary my question really comes down to what is considered by the wider community as best practice for persisting data in my situation. Effiency, scalability and resiliancy is paramount as I'll have a large global user base that will end up using this web app.
Thanks in advance!
Pete
I'd just use cookies. They're simple to use, you can persist them for as long as you want or have them expire when the users closes their browser, and it doesn't sound like you are storing anything sensitive in them.
Sometimes at websites all comments or other data from DB is hidden by default. When user click at link like "Display comments" all comments from database are dynamically selected and placed under the content. It must be great for mysql performance, because content is generated only when user excatly need it. I would like to implement this stuff at my app.
I've got one idea to do this so far. Remote action with #comments = Content.comments and next page.insert_html at RJS template. Is it good idea or maybe I should choose different way?
The decision is purely based on the application that you are developing. For example if in case of stack overflow it does not make sense to show only the question and show answer link. But in case of a blog post it may be fine.
In the above situation, I don't think there will be a good improvement in performance by removing the comments of the content on show page. We can achieve the same functionality by making use of javascript methods. Hide the content on page load and show in on client request.