Creating a multiple choice test on Rails using a hash table - ruby-on-rails

I'm in a tech summer camp and our teacher is showing us how to use Ruby on Rails. I told my teacher want I wanted to make and he told us to post here because it's important to learn from other developers.
I was looking on the site and found this question that is similar to what I want to do for my project. I want my friends to be able to read a few pages of text and then do a short test to make sure they were paying attention.
I want to make a hash table like the question I linked above but I don't know where to put it in my app! I would also like to tie it to users somehow so I can see which of my friends completed the test or not.
So far I have made user, question and answer models and would like to use a hash table like this test my fellow students.
# Question:
{ :question_id => 1,
:text => 'What is Minecraft?',
:answers => # Answers:
[{:answer_id => 1, :text => 'A game'},
{:answer_id => 2, :text => 'A food'},
{:answer_id => 3, :text => 'A store'} ],
:correct_answer_id => 1 }
Can someone tell me where I need to put this in my app and how I can save it to a database? My teacher said it is okay if people tell us how to do stuff as long as we tell him in our write up.

If you have related your answers with a has_many relationship to your question you can create answers with questions like this:
question = Question.create!(text => 'What is Minecraft?')
question.answer.create!(:text => 'A game')
question.answer.create!(:text => 'A food')
...
Ids will usually given out by the database, just don't need to define them yourself.

Related

Select menu for type field and map integers to text in rails

[I'm new to rails, and I hope it's not a silly question, seen a similar question but it's for PHP and doesn't help in my case]
To explain my problem, I'm using a analogy to users here. Lets say I have users table in my app, I have added a field called user_type to users table. Now I want to specify which type of user is.
lets say I have 5 types of users eg. moderator, administrator, consumer etc.
I don't want to make user_type field to be string type to store user type. Instead I want to make user_type to store integer and then map these integer values to respective string values.
Advantage to this approach is that I can change what a user type is called. Suppose that I no longer wish to call consumer a consumer and instead wish to call it something else.
I believe storing integer in db is better and gives some flexibility.
I know I can create select menu using formtastic(I'm using active_admin as admin panel, formtastic is used for forms)
<%= f.input :user_type, :as => :select, :collection => {
0 => "Admin",
1 => "Moderator",
2 => "Consumer",
} %>
and then store values in db, and then select these users from db.
I want to know Is there a better way or approach to do it in rails or there is some gem available to do this or some other approach you prefer and why you recommend it.
I'm using postgresql as database.
Thanks!!
I personally like the active_enum gem combined to simple_form because it's really simple to implement and they work fine together.
In your case, you would have to define an enum class like this :
class Type < ActiveEnum::Base
value 1 => 'Admin'
value 2 => 'Moderator'
value 3 => 'Consumer'
end
Then in your User model, you simply add this :
enumerate :user_type, :with => Type
And what is really great with simple_form is that you simply have to call :
<%= f.input :user_type =>
to get a select with all your values.
Try this
# user.rb
USER_TYPES = { moderator: 1, superuser: 2, admin: 3, client: 4 }
# views
select :user, :user_type, User::USER_TYPES
This saves the integer values to the database. If you want to get the the string equivalent, use User::USER_TYPES.key(#user.user_type)
EDIT: forgot to add scopes
scope :moderators, where(user_type: USER_TYPES[:moderator])
scope :superusers, where(user_type: USER_TYPES[:superuser])
...
or
USER_TYPES.each do |user_type, value|
scope :"#{user_type}s", where(user_type: USER_TYPES[user_type])
end

Sort collection according to field in association

I'm having a trouble finding how to do a query with MongoDB/Mongoid here. So I have a model User, that has_many :scores, Score being another model that has a code and a value. The code is unique in the scope of the user. For a given code I want to get the users, sorted by the value of the score.
Basically, what I want to do is something like : User.where('scores.code' => code).order_by('scores.value'), except it cannot be done like this. I tried several things, and I think the answer is related to User.where(:scores.matches => {:code => code}), but this does not return me anything, so I must be missing something here..
Thanks for your time, hope I was clear enough!
I think this is probably what you want:
scores = Score.where('code' => code).order_by('value')
If you want to get the user (assuming that Score class has belongs_to :user), then you can do this:
users_that_matches_code = scores.map { |s| s.user }

Rails 3 - is possible to make IFs in a database query

I have a profile card of user that have registration in my forum.
Person.update_all({:name => params[:person][:name],
:sex => params[:person][:sex],
:age => params[:person][:age],
:avatar => params[:person][:avatar].original_filename,
:city => params[:person][:city]},
{:id => params[:id]})
This is query for updating data in database. But here is a small problem - this will work only in a situation, if I the user send through form avatar (image). If not send avatar - that means the user already have uploaded avatar and the form send only name, sex, age and city. So in this case I'll get error in line :avatar => params[:person][:avatar].original_filename, -- and I would like to ask you for, if exist some elegant way, how to treat this moment.
I thought something like this:
if params[:person][:avatar]
avatar = ':avatar => params[:person][:avatar].original_filename,'
end
Person.update_all({:name => params[:person][:name],
:sex => params[:person][:sex],
:age => params[:person][:age],
avatar
:city => params[:person][:city]},
{:id => params[:id]})
But unfortunately, this doesn't work... How you're solving similar situation?
Thank you.
Well, it seems, like your params[:person] keys are similar to your model fields. So why don't you just pass params[:person] to update_all?
Alternatively, you could create a hash person, initialize it the way you want and then pass it to update_all
person = { :name => params[:person][:name] ,
...
if params[:person][:avatar]
person[:avatar] = params[:person][:avatar].original_filename
end
Person.update(params[:id], person)
I've changed update_all to update, because update_all is used to update all the records (that match the condition), while update find's the record by it's ID.
But again, it's a bad practice and you have to type a lot of unnecessary code.
One more thing. update_all makes a direct DB call, which doesn't involve validations, callbacks etc.
So, if you don't have some special reason for this, you'd better do something like this:
#person = Person.find params[:id]
#person.update_attributes params[:person]
I really think, you should check this book out
Updated once again :)
You see, such things belong to your models, not controllers. You could define a setter in the model:
def avatar=(value)
write_attribute(:avatar, value.original_filename)
end

Searching with thinking_sphinx and filtering results

I have this scenario where I thought it would be pretty basic, but found out that I can't really achieve what I need. This is why I have this question for a thinking_sphinx's expert.
The scenario is this: I need do a search within a list of companies and only return those who has an address (there can be many address by company) which belongs to a particular city or none at all (this I can do).
I have the following models :
class Company < ActiveRecord::Base
has_many :company_addresses
define_index
indexes :name
indexes :description
indexes :keywords
end
end
and
class CompanyAddress < ActiveRecord::Base
end
The CompanyAddress has a city_id property. Without looping through all returned records from a sphinx search, is there a way to achieve the same thing more easily?
I'm using Rails 3.0.3 and thinking_sphinx.
You'll want to add an attribute pointing to the city_id values for the company:
has company_addresses.city_id, :as => :city_ids
And then you can filter on Companies belonging to a specific city:
Company.search 'foo', :with => {:city_ids => #city.id}
If you want both matching to a specific city or has no cities, that's a little trickier, as OR logic for attribute filters is more than a little tricky at best. Ideally what you want is a single attribute that contains either 0, or all city ids. Doing this depends on your database, as MySQL and Postgres functions vary.
As a rough idea, though - this might work in MySQL:
has "IF(COUNT(city_id) = 0, '0', GROUP_CONCAT(city_id SEPARATOR ',')",
:as => :city_ids, :type => :multi
Postgres is reasonably similar, though you may need to use a CASE statement instead of IF, and you'll definitely want to use a couple of functions for the group concatenation:
array_to_string(array_accum(city_id, '0')), ',')
(array_accum is provided by Thinking Sphinx, as there was no direct equivalent of GROUP_CONCAT in PostgreSQL).
Anyway, if you need this approach, and get the SQL all figured out, then your query looks something like:
Company.search 'foo', :with => {:city_ids => [0, #city.id]}
This will match on either 0 (representing no cities), or the specific city.
Finally: if you don't reference the company_addresses association anywhere in your normal fields and attributes, you'll need to force to join in your define_index:
join company_addresses
Hopefully that provides enough clues - feel free to continue the discussion here or on the Google Group.

How to implement search like Stack Overflow

I have implemented the full text search using Sphinx and Thinking Sphinx.
I want to add column wise search. Some thing like:-(taking an example of Stack Overflow)
Suppose you want to see actvities related to you, just type:
user:me
Then it will return a result with all the questions and answers related to piemesons.
If you type
votes:15
then it will return a result with all the questions tagged with having more than 15 votes.
And if you type
user:me votes:15
then it will return all the questions and answers belonging to you with more than 15 votes.
How can I implement this thing?
Right now my search results are based upon full text search. How can these kinds of features be included?
Any options avaliable in Sphinx or Solr or any other search engines?
:with option in thinking sphinx.
First of all, you have to define those attributes in your index definition (check out attributes section here).
has views_count, :as => :views, :type => :integer
has user.id, :as => :user, :type => :integer
Then you could search for posts like this:
Post.search '', :with => {:views => 12..maxint, :user => User.first.id}
(I am not sure if there is any more elegant possibility of giving open ranges, but 12..max_int should be enough)
Two important things:
if you want to count related objects (e.g. responses), you should use counter cache
if your "user" is polymorphic association, I recommend "CRC32(CONCAT(user_type, user_id))" instead of user.id

Resources