Reputation: 1355
I'm getting an error from one of my controller classes and I can't figure out why. The error is:
SyntaxError in TermsController#show, syntax error, unexpected $end, expecting keyword_end
Here is terms_controller.rb:
class TermsController < ApplicationController
def show
@term = Term.find(params[:id])
if @term.id == 1
@title = "Fall"
else if @term.id == 2
@title = "Winter"
else if @term.id == 3
@title = "Spring"
else if @term.id == 4
@title = "Summer"
end
end
end
My show page currently just consists of:
<h1> <%= @title %> </h1>
It's probably something small that I'm just missing - thanks for your help!
Upvotes: 7
Views: 9654
Reputation: 6312
Why not just do this:
class TermsController < ApplicationController
@@seasons = { 1 => "Fall", 2 => "Winter", 3 => "Spring", 4 => "Summer"}
def show
@term = Term.find(params[:id])
@title = @@seasons[params[:id]] || "Invalid Season"
end
end
Upvotes: 1
Reputation:
The issue that there are not enough end
keywords and it found $end
(the token representing the end of the file) before it could find what it was looking for -- another end
. (The parser token for the end
keyword is either "keyword_end" or "Kend", depending upon ruby version.)
Each if
expression requires a matching end
keyword.
To get around this, use elsif
instead of else if
. It is part of the same if
construct and does not require a matching end
(only the if
requires the matching end
).
if x == 1
"1"
elsif x == 2
"2"
else
"else"
end
Another option is case
which works well if all branches check the same conditional operand (x
in this case):
case x
when 1 then "1"
when 2 then "2"
else "else"
end
If you do want to use else if
(remember, each if
starts a new if
conditional construct) then make sure close each block that a if
opens. I have indented the code to show this point better.
if x == 1
"1"
else
if x == 2
"2"
else
"else"
end
end
Happy coding.
For the pedantic: there is also another form of if
, which is expr if cond
, which doesn't have a matching end
as part of the syntax and the rules talked about above do not apply to it.
In addition, if
and case
are just expressions in Ruby, so it might be more idiomatically written like this
@term = Term.find(params[:id])
@title = case @term.id
when 1 then "Fall"
when 2 then "Winter"
when 3 then "Spring"
when 4 then "Summer"
else "Invalid Term"
end
The if/elsif/end
syntax can be used in the same way, but using case
avoids the repeated mentioning of @term.id
. Another option is to use a Hash to perform this sort of simple mapping -- or the mapping can be encapsulated in a separate method -- but that is covered elsewhere ;-)
Upvotes: 13