Leahcim
Leahcim

Reputation: 42009

Which rails form helper should I use for people to rank things?

I have 6 different courses, and I want students to rank them by degree of difficulty. I was looking at number_field (and just going to have students assign a number from the range) but when I tried it out, only some browsers had the up and down arrows to move through the range, while others didn't, and it wasn't a good solution because it just presented a blank field that students might put text into when the database wanted an integer

I then started looking at the form options helper from the API http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#M001593

but I couldn't figure out how to apply it to my situation. I have a Student model, and there's 6 columns on the table -- :math, :science, :french, :english, :history, :geography--currently set to integer type

Is there a way to use the form options helper (shown below from the api) and apply it to my requirements so they rank the classes from 1 to 6 (hardest to easiest etc)?

Example with @post.person_id => 2:

select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, {:include_blank => 'None'})
could become:

<select name="post[person_id]">
  <option value="">None</option>
  <option value="1">David</option>
  <option value="2" selected="selected">Sam</option>
  <option value="3">Tobias</option>
</select>

Upvotes: 0

Views: 132

Answers (1)

Art Shayderov
Art Shayderov

Reputation: 5110

If select suits your needs,

= form_for @student do |f|
  = f.select :math, (1..10)

assuming you want math be rated on 10 scale. I used haml, but it doesn't really matter.

Edit (added validation per OP request :)

class Student < ActiveRecord::Base
  validates_with StudentValidator
end

class StudentValidator < ActiveModel::Validator
  def validate(record)
    courses = [:math, :science, :french, :english, :history, :geography]

    courses.combination(2).each do |f,s|
      f_value = record.send(f)
      s_value = record.send(s)

      if f_value == s_value
        record.errors[:base] << "Two ranks can't be equal"
        record.errors[f] << "can't be #{f_value}, #{s} is #{s_value}"
        record.errors[s] << "can't be #{s_value}, #{f} is #{f_value}"
      end
    end
  end
end

I thought about adding client validation, but disabling select options doesn't work well across browsers AFAIK, so you have to dynamically remove and add options. Looks like too much for me at least for a SO answer. Sorry.

Upvotes: 1

Related Questions