in Rails, with check_box_tag, how do I keep the checkboxes checked after submitting query?

user866503 picture user866503 · Jun 10, 2012 · Viewed 8.9k times · Source

Ok, I know this is for the Saas course and people have been asking questions related to that as well but i've spent a lot of time trying and reading and I'm stuck. First of all, When you have a model called Movie, is it better to use Ratings as a model and associate them or just keep Ratings in an array floating in space(!). Second, here's what I have now in my controller:

def index

@movies = Movie.where(params[:ratings].present? ? {:rating => (params[:ratings].keys)} :   {}).order(params[:sort])
@sort = params[:sort]
@ratings = Ratings.all

end

Now, I decided to create a Ratings model since I thought It would be better. Here's my view:

= form_tag movies_path, :method => :get do

Include:
- @ratings.each do |rating|
 = rating.rating
 = check_box_tag "ratings[#{rating.rating}]"
= submit_tag "Refresh"

I tried everything that is related to using a conditional ternary inside the checkbox tag ending with " .include?(rating) ? true : "" I tried everything that's supposed to work but it doesn't. I don't want the exact answer, I just need guidance.Thanks in advance!

Update (the controller's method):

Here is the index method within my controller that is reading this hash - for clarity. I apologize for the fuzziness before.

def index    
  @all_stores = Product.all_stores
  @selected_stores = params[:stores] || session[:stores] || {}

  if @selected_stores == {}
    @selected_stores = Hash[@all_stores.map {|store| [store, store]}]
  end
  if params[:stores] != session[:stores]
    # session[:stores] = @selected_stores
    session[:stores] = params[:stores]
    redirect_to :stores => @selected_stores and return
  end
  @products = Product.order("created_at desc").limit(150).find_all_by_store(@selected_stores.keys).group_by { |product| product.created_at.to_date}
. . . etc

Answer

house9 picture house9 · Jun 11, 2012

Couple of things

1) .order(params[:sort]) opens you up for sql injection attacks, someone could potentially delete all of your users by putting this in the query string

http://localhost:3000/movies?sort=email%3B+DELETE+from+users+--

see rails 3 activerecord order - what is the proper sql injection work around?, this problem does not exist with .where, rails will sanitize the input for where method

2) minor thing, AREL delays making the actual call to the db until you iterate on the collection, so you can 'build' up queries, this syntax might be easier to understand then using ternary operator?

@movies = Movie.order(xxxxxx)
@movies = @movies.where(:rating => params[:ratings].keys) if params[:ratings].present?

3) for your ratings, like cdesrosiers says constant is fine, then your view

Movie::RATINGS.each do |rating|
  check_box_tag "ratings[]", rating # <input type="checkbox" name="ratings[]" value="PG" />

EDIT: maintain selected values

# controller
@selected_ratings = (params[:ratings].present? ? params[:ratings] : [])

# view
Movie::RATINGS.each do |rating|
  check_box_tag "ratings[]", rating, @selected_ratings.include?(rating)
  # <input type="checkbox" name="ratings[]" value="PG" checked="checked" />

note the [] in the naming of the checkbox, this will give you params[:ratings] as an array in your controller action

@movies = @movies.where("rating IN (?)", params[:ratings]) if params[:ratings].present? and params[:ratings].any?

some links