rails quiz implementation: saving points per answer - ruby-on-rails

I am making a quiz-like app that has multiple questions that have multiple answers. Each answer has a points and the id_of_next_question attributes - depending on the answer the user should be presented with a different question.
The easy way to do this would be to do sth like this:
< #question.answers.each do |answer| %>
<= link_to answer.content, question_path(answer.id_of_next_question) %>
< end %>
But this has the down side that the user would see the ids of the Questions in the path and I don't know how I would collect the answer.points with link_to.
What would be a proper way to make a i.e. .../play.html view that shows the 1st question, and depending on the answer, calculates points=points+answer.points and renders the next question with answers without changing the ".../play.html" path?

One way to achieve this would be to have your links act like a form which creates a new question_result (a model where you save the user's choice),
for example
< #question.answers.each do |answer| %>
<= link_to answer.content, question_results_path(:question_id => #question.id , :answer_id => answer.id) , :method => :post %>
< end %>
then in a question_results_controller, you can have a create action, which calculates the points using the answer_id, and redirects the user back to the play.html path, with as a parameter the next question id so that the user can continue the quiz. You could save the points total as a cookie (although a more proper way to do it would be to have a user model, and save the results per user in the db)

Related

setting a dynamic link_to rails

I'm pretty new to rails and I'd like to set my links for a certain page dynamically. I have a table called "Unfinished" and it has a column called "link" (corrected from "links") I'd like to be able to call the "link" record in the view to set my link_to link path.
I am trying to do this...
<%= link_to #unfinished.link(:p => #post.id) do %> FINISH <% end %>
...but that's not working.
my controller says:
def show
#post = Post.find(params[:id])
#unfinished = Unfinished.where('progress = ?', #post.progress).last
end
and the controller logic works fine...until I try to put the #unfinished.link into link_to
Edit:
Error Message:
wrong number of arguments (1 for 0)
Model
class Unfinished < ActiveRecord::Base
end
The type of links are :
step1_path
step2_path
step3_path
I am making a multipage form that you can save partway through. Based on a value in the #post.progress column (like 1, 2, 3) the correct path to complete the post will be provided (step1_path, step2_path etc...)
try this.
<%= link_to eval(#unfinished.link.to_s) do %> FINISH <% end %>
since the link you want is actually a named route, so you will need to eval it.
but with this you wouldn't be able to be able to pass in the post id, which you will need.
If the route is the same for all records (save for what part you are on based on the progress attribute) do you even need to store it in the database? You could just make the link method return the path (that you would still need to eval).
something like
def link (post)
"step#{self.progress}_path(post.id)"
end
and then eval the link on the way back. but Not sure if that will work, just thinking out loud...
There are gems that do multi-stage forms perhaps looking into them might help?

Disable upvote button in acts_as_votable gem after an up vote

Context:
I have a forum thread model which acts_as_votable.
The up vote functionality works fine
The up vote button allows the current_user to up vote the forum thread only once, which is the desired functionality. I am trying to change the css of the up vote button to a different color once the current_user had clicked on it.
<%= link_to forum_thread do %>
<h3>
<%= link_to like_forum_thread_path(forum_thread), method: :put, class: "" do %>
<span class="glyphicon glyphicon-arrow-up"></span>
<% end %>
<%= forum_thread.get_upvotes.size %>
<%= forum_thread.subject %>
</h3>
<% end %>
Problem:
One way to do this is to get a list of all the user_id's(using #forum_thread.votes_for_ids) who have up voted the forum thread and check if the current_user user id matches the list. If so, then disable the button. Is there a more efficient way to do this ?
Solution first:
#user.voted_for? #post
Its available in the documentation as well. Here
Now, lets go to the details:
You current solution does the following:
Fetch all the votes on the Post. Ideally, see to it that you get MySQL to return as fewer ActiveRecord objects as possible. Because, there is a considerable performance loss converting each MySQL row into an Active Record.
Looping through all the ActiveRecords and collecting the USER_ID in it. Looping is another performance hindrance, if you could easily avoid it.
Instead, prefer a MySQL query that returns the ROW/Data of what exactly we need, "If the current user had voted on the Post". something like (You would need to use the correct/apt database table names):
PostVote.find_by_post_id_and_user_id(post_id, user_id).
The above returns if the user had voted or not.
Alternatively, Acts_As_Votable does provide the same without you having to do the heavy lifting:
#user.voted_for? #post

Rails Forms and Associations - Adding multiple objects with a quantity form

I am new to rails, but not to programming or databases.
A BETTER PHRASING OF MY QUESTION IS IN MY ANSWER BELOW.
For simplicity in this example, I have 3 models:
User
Subscription
Default_Subscription
User has_many Subscriptions
Subscription belongs_to User
Default_Subscription has_many Subscriptions
Subscription belongs_to Default_Subscription
Default_Subscription is a pre-populated table with certain types of subscriptions.
During the subscription process, the default subscriptions are listed at one point, and there
is a quantity box alongside each one.
The user enters the quantities for each subscription and hits submit to continue on.
My question is:
How would one go about creating a new subscription for each quantity in a number form?
So you would have a list something like so:
<ol>
<%= each subscription with quantity box %>
</ol>
<%= button_to %>
When the user hits the button, how do you add up the quantity from each box and add a new subscription for each one? Do I have to use javascript to get the numbers? Do I somehow use rails forms even though this quantities are not associated with any specific database field? Any recommendations or pointing me in the right direction to figure this out on my own would be great.
This form box IS NOT A FIELD FOR ANY MODEL, it's a count for an association. Let me rephrase: Each quantity in the form boxes represent the number of NEW Subscriptions to be created. Each of these subscriptions BELONGS_TO 1 DEFAULT_SUBSCRIPTION. In essence, the number represents the number of new subscriptions ASSOCIATED WITH THAT DEFAULT SUBSCRIPTION.
I'm using rails 3.2.1, and ruby 1.8.7
Thank you
Not sure I totally understand your description, but I'll take a shot.
Use the 'form_for' function to build your form, based on an instance of #default_subscription (established in the "new" action in your controller). If there are default values in #default_subscription, will show in the fields and the user can change them as they see fit. (this assumes your DefaultSubscription model has three attributes: sub1, sub2 and sub3.)
<%= form_for #default_subscription do |f|
<%= f.label :sub1 %><br />
<%= f.number_field :sub1 %>
<%= f.label :sub2 %><br />
<%= f.number_field :sub2 %>
<%= f.label :sub3 %><br />
<%= f.number_field :sub3 %>
<% end %>
When the user clicks the submit button the contents of the form with we assembled into a hash and passed into your controller's "update" action via params[]. You can extract the subscription hash like this:
user_subscription = params[:default_subscription]
At this point you have all the numbers that the user entered into the fields in the user_subscription hash. You can now parse the hash to extract the numbers, do your math, and then create the appropriate subscriptions per the user's input. (one note: the numbers could be strings and you might need to convert them back to integers as I've shown below.)
For example, to total all the subscription values and save that total into a user's subscription:
total = 0;
user_subscription.each do |key, value|
total += value.to_i
end
new_sub = current_user.subscription.new
new_sub.total = total
new_but.save
As I said, I don't understand your description clearly, so this might not be germane, but hope it is close to what you were looking for.
Good luck.
I have figured out one way, and reading my original post again, the whole thing is really confusing because I didn't know how to say exactly what I was trying to accomplish. I must say a lot of the reason I was confused is because the form I wanted did not correspond to any model, just an association count, which is ultimately a basic html form if you want to create a bunch of new objects without having their attributes yet. I'll first clarify then show my solution.
Clarification:
I have 2 Tables:
Subscription
Default_Subscription (Pre-Populated)
Subscription belongs_to Default_Subscriptions
Default_Subscription has_many Subscriptions
A User is subscribing to my website. This process is a step by step: not everything happens on the same page.
This all happens in a subscribe_controller. Each action corresponds to a step in the process.
One of the actions is default_subscriptions. This action lists the Default_Subscriptions a User can choose from, except they do not just choose, they can enter an amount for each type of Default_Subscription they'd like.
When the Default_Subscriptions are listed on the default_subscriptions page, I wanted a form with an html number input alongside each of these Default_Subscription. When the form is submitted via a next button, I had no idea how to gather the quantities from each html input and create an array of Subscription.new, with each Subscription's default_subscription_id corresponding to the proper Default_Subscription.
One Possible Solution:
def default_subscriptions
#def_subscriptions = Default_Subscription.all
end
Lets say the page I want proceed to after all the quantities are entered on the default_subscriptions page is review_subscriptions.
Here's what I did to create the proper form to proceed to the next action in the controller:
<%= form_tag( {:controller => 'subscribe', :action => 'review_subscriptions'}, :method => 'post' ) do %>
<ol>
<% #def_subscriptions.each do |ds| %>
<li>
<%= ds.name + ' ' %>
<%= number_field_tag("subscription_counts[#{ds.id}]") %>
</li>
<% end %>
</ol>
<%= submit_tag('Next') %>
<% end %>
The trick here is that string passed to the number_field_tag. By placing a single set of square brackets at the end of the string for a field_tag method parameter, the part before the brackets is the name of the hash, and the thing in the brackets is a key in the hash, and the submit button causes the corresponding value for each key to be the value of the field. Pretty cool!
The parameters passed to the next action would contain a hash called subscription_counts, and iterating through this hash would give a corresponding new subscription amount for each default_subscription_id. Like so:
def review_subscriptions
subscription_counts = params[:subscription_counts]
subscription_counts.each do |id, amount|
counter = Integer(amount)
until counter == 0
new_subscription = Subscription.new
new_subscription.default_subscription_id = Integer(id)
#subscriptions << new_subscription # #subscriptions is an instance variable
counter -= 1
end
end
end
I'd just like to point out, the more I work with them, the more I love them; I love Rails, and I love Ruby. They are super fun and classy. An until loop... how cool is that? If you have other solutions, now that my question is more obvious, please chime in! I know others out there are trying to find some slick ways to create multiple new objects in a one to many association with a single post call like this. Technically my objects aren't saved in the database yet, but that wouldn't be to hard now.
The main reference which helped me the most in reaching this solution was:
http://guides.rubyonrails.org/form_helpers.html
If you are new to rails, and confused about forms, read this. I feel like a master now. Rails devs are really good at documenting things!

Rails Search Form

I'm creating an application that tracks users and achievements (think, xbox live, etc.) These tables are linked via a join table. I would like to have a search form on my index that lets users type in a users name and a new page is loaded with a list of all achievements that user has earned. I'm not entirely sure how to set up this search form, on the index, to actually search the user table and return the results on a new page. Any help would be greatly appreciated. If you require more information then I'll be happy to provide it.
Here's a bit of skeleton code to get you started based off what I think you need from what you have said. I hope this is useful.
For the search bit you could do something like this in your index view:
<%= form_for User.new, :url => "search" do |f| %>
<%= f.label :name %>
<%- f.text_field :name %>
<%- end %>
In your controller:
def search
q = params[:user][:name]
#users = User.find(:all, :conditions => ["name LIKE %?%",q])
end
and in your search view:
<%-#users.each do |user| %>
Name: <%=user.name %>
<%- user.achievements.each do |achievement| %>
<%= achievement.name %>
<%- end %>
<%- end %>
You would, of course, need to ensure the users and achievement models are correctly linked:
class User << ActiveRecord::Base
has_many :achievements
end
There are plenty of tutorials and things about this e.g.:
http://blog.devinterface.com/2010/05/how-to-model-a-custom-search-form-in-rails/
Look the thing is every basic explanation in Rails3 starting with the Initial Tutorial provided by them explains you how to setup a new Controller/Model. The example was only one of thousands explaining the same problem.
It is a very broad range of different things you can do to achieve this. Basically you have to put some code in the controller:
which handles the search (including the activerecord stuff or whichever technique you use to access your model)
which sets some variables necessary for the search form
Setup two routes etc... Its to broad and completely covered even by the basic official rails3 tutorial.
Here is an application based on searchlogic is very useful and you can search by whatever you want
https://github.com/railscasts/176-searchlogic
You may want to check out the Ransack gem. https://github.com/activerecord-hackery/ransack

Issues with Relationships

You can take a look at the app I'm referring to at:
http://github.com/585connor/QA
So, I've built this question & answer app... kind of. I can get the
answers to be listed on their respective questions but I cannot figure
out how to get the user info to be displayed on those questions/answers.
For example I'd like to put the username next to each answer and the
username next to each question. Also, when viewing the show action of
the users controller, I'd like to be able to see a list of that
particular user's questions and answers.
There are three tables: questions, answers and users. Can you take a
look at the github repository and try to point me in the right direction
for what steps I should take/concepts I should learn in order to achieve
what I'm trying to do?
Becase you have a
belongs_to :user
in your question and answer model, you can access the associated user-model by calling .user on a question or answer object:
# controller
#question = Question.find :first
# view
<%= #question.user.name %>
Accessing the user's questions and answers is similar:
# controller
#user = User.find :first
# view
<% #user.questions.each do |question| %>
<%= question.title %>
<% end %>

Resources