0

I have been looking at this for some time, with no luck.

I am working with Ruby on Rails. I am attempting to use .each to iterate through an array and use each element to set a variable name. Specifically, the variable will control whether the checkbox on a form is displayed as checked.

I keep recieving this error: `@PG-13_check' is not allowed as an instance variable name It seems like prior problems involving this error revolve around a failure to declare the instance variable with @. But I have included that.

Model:

class Movie < ActiveRecord::Base 
  attr_accessible, :title, :rating, :description, :release_date 
  def self.ratings 
    ratings = [G, PG, PG-13, R] 
  end
 end

Controller Code:

@movies = Movie.all
@all_ratings = Movie.ratings
@all_ratings.each do |x| 
  instance_variable_set("@#{x}_check", "true")
end

In turn, the view reads:

= check_box_tag "ratings[#{rating}]", 1, checked = @#{rating}_check, :id => "ratings_#{rating}"  
iammurp
  • 27
  • 1
  • 6

2 Answers2

0

Just double-checked, and Ruby variables aren't allowed to have hyphens in them. Only numbers, letters, and underscores are -- i.e., if it doesn't match /[a-zA-Z_][a-zA-Z0-9_]*/ it isn't an allowed variable name. This means that you can't declare a variable named PG-13_check. However, you could declare one called PG13_check, which is (IMO) clear enough. You can get that with a very simple application of String#gsub:

x.gsub('-', '')

So in your code, this would look like:

@all_ratings.each do |x| 
  instance_variable_set("@#{x.gsub('-', '')}_check", "true")
end

If you want to convert it back to the original form, you could use something like this instead:

@all_ratings.each do |x| 
  instance_variable_set("@#{x.gsub('-', '_')}_check", "true")
end

Then, to get x back, you can get the string form and use:

variable_name.split('_')[1..-2].join('_').gsub '_', '-'

That probably isn't the most efficient way, but it's the first that I thought of. What it does is strip off the _check at the end (.split('_')[1..-2].join('_')), then replace all _ with -.

Nic
  • 6,211
  • 10
  • 46
  • 69
  • 2
    An identifier can't start with a digit. – Sergio Tulentsev Apr 14 '15 at 15:09
  • Thanks! Can I apply the same method in the view though? In other words, I am using a predetermined model, Movies with :ratings that = PG-13. Therefore, when I iterate through :ratings to create the checkbox form, I would need to .gsub the '-' so that it matches the instance variable in my controller. – iammurp Apr 14 '15 at 15:13
  • Well, you can use the full range of unicode word characters in variable names, plus some special chars like `_`. Some exceptions apply on order to have a sane parser. E.g., it can't start with a number on order to prevent the thing to be parses as a number. Apart from that, you are free to use whatever you like, even this: `ಠ_ಠ` – Holger Just Apr 14 '15 at 15:36
  • @iammurp Would stripping the '_check' and gsubbing underscores for hyphens work, or are there other considerations you haven't shown that prevent that? If that'd work I'll put it in now. – Nic Apr 14 '15 at 16:12
  • It would not work because I cannot change the Movie :rating "PG-13", and in the view, I have to iterate through the ratings to get the variable names, including "PG-13" -- so the _check is not the problem. The problem was (a) including "-" in the variable name, and even if I remove the "-" with gsub, (b) removing the "-" from the variable in the view to match the instance variable created in the controller. – iammurp Apr 14 '15 at 19:43
  • I was having a similar problem. I resolved using the **underscore** method which lets you do `'my-string'.underscore` and returns `my_string`. See [this thread](http://stackoverflow.com/a/1509939/1498118) – a.barbieri Apr 14 '17 at 08:05
0

I am a beginner, so I hope I don't look bad for missing something that was too obvious and, hence, wasting everyone's time. But I ultimately just put a conditional statement in my check_box tag, which accomplished my task. This is for an edx class, so I won't put the actual answer. It was to the effect of:

= check_box_tag "ratings[#{rating}]", 1, checked = does the params hash includes the rating that was checked true ? false, :id => "ratings_#{rating}"

Thanks for all the responses, I learned a lot!

iammurp
  • 27
  • 1
  • 6