Using Instance Variables in a Sinatra Webapp
I’m trying to get into the habit of taking notes with code examples for concepts that aren’t quite clear to me - think “rubber duck note-taking”. I wasn’t super clear about the uses of instance variables in Sinatra routes, so I went through this exercise here.
If you made a GET route like this:
get "/" do
@test = "This is a test"
erb :intro
end
Then @test
would be accessible in the intro
view.
In the below post route:
post "/test" do
if some_condition
@redirect_test = "Instance variable before a redirect"
redirect "/"
else
@erb_test = "This is a test before calling an erb view"
erb :intro
end
end
@redirect_test
will not be available on the intro
view. A redirect will issue a new request, and our instance variable will not persist.
@erb_test
will be available on the intro
view. No new request is issued , only a call (erb
is a method) to the view, so the instance variable will still be available to the view. However on refresh (another request), this value will not persist.
Based on my understanding of the above, it seemed liked you’d rarely set an instance variable inside a post route. However, I was seeing examples of setting instance variables in post routes out in the wild which tripped me up for a while. One of these was from a todo list app:
# Edit an existing todo list
post "/list/:id" do
id = params[:id].to_i
@list = session[:lists][id]
list_name = params[:list_name].strip
error = error_for_list_name(list_name)
if error
session[:error] = error
erb :edit_list, layout: :layout
else
@list[:name] = list_name
session[:success] = "The list name has been edited"
redirect "/lists/#{id}"
end
end
The role of @list
here on line 3 is just to get a handle on the on the correct list contained in the session. When list_name
is assigned to @list[:name]
this changes the title of the list. However, since this is all happening in the route we could make the instance variables local variables and they could perform the same function. Specifically I mean changing @list
to list
on line 4 and again on line 12. It’s not too important, but in my mind this makes the example simpler.
If this project went on to require that we display the current list being edited, then we’d need to reconsider the above change we just made. In this case it’s important to set an instance variable in the route so the view can access this variable as well, so we’d need to switch list
back to @list
, etc.