How to pass parameters from a controller to a template? - ruby-on-rails

It seems that setting multiple instance variables in a controller's action (method) causes problems in the template, only the very first instance variable got passed to the template. Is there any way to pass multiple variables to the template? Thanks! And why, in Ruby's perspective, does the template get access to the instance variables in an action?

You might also want to look into the :locals option of render. Which accepts a hash such that keys are symbols that map to local variable names in your template, and the values are the values to set those local variables to.
Example:
render "show", :locals => {:user => User.first, :some_other_variable => "Value"}
and this template
User ID: <%= user.id %><br>
Some Other Variable: <%=some_other_variable%>
will produce:
User ID: 1<br>
Some Other Variable: Value
When you're reusing partials across multiple controllers. Setting local variables with the :locals option is simpler and much more DRY than using instance variables.

you shouldn't have any problem setting multiple instance variables. For example:
class CarsController < ApplicationController
def show
#car = Car.find(:first)
#category = Category.find(:first)
end
end
will allow you to access both #car and #category in cars/show.html.erb
The reason this works is nothing inherent to ruby, but some magic built into rails. Rails automatically makes any instance variable set in a controller action available to the corresponding view.

Related

how to pass and access data to partial view in ruby on rails?

I'm adding a new partial view in ruby on rails project and want to pass some additional data to the partial. I have code below for rendering a view . I understand this is the way to pass data (id in my case) to partial view. I'm not sure if this is the best way, as I'm new to rubyonrails. How do i access in my partial view file?
render "index" , :locals => {:id => params[:id]}
You can pass data to your view(s) using options on render, one of which is locals, or by setting instance variables which automatically propagate.
Normally what's done is something like this:
#id_param = params[:id]
Where within your view you can use #id_param wherever and whenever:
<%= #id_param %>
I've chosen #id_param for a name here instead of #id to give it a bit more context as #id on its own might prompt questions of "What ID?"
If you want to do the locals method, then:
render 'index', locals: { id: params[:id] }
Using the Ruby 1.9 hash notation for simplicity here, versus the outdated 1.8 style in your original example. This produces a local variable called id that can be used in that view, like:
<%= id %>

In a Rails view, which objects are in the response chain?

When I call a method foo() or refer to an attribute #bar in my view file, which object is going to respond?
For example if I have a partial _ebook.html.erb that looks like
<h2>Your eBook</h2>
<p>Title: <%= #title %></p>
<p>Due Date: <%= due_date(customer) %>
etc.
which object provides #title, due_date and customer? Do those bubble up to the BooksController and its modules/superclasses?
Also, if my render includes locals, for example
render partial: "ebooks", locals: {baz: #qux}
in which object is baz being stored?
It's not other objects provide your template with local variables, it's your template being read by the controller where the object exist in the context.
The erb template annotate variables such as #bar and taken by the controller to render accordingly. If controller actually has a #foo and you want to use it as the #bar in template you plugin locals: {bar: #foo}
I've found most of the answer, at least for Rails 3.2.x. Here's my poorly written description:
As part of rendering, ActionView::Base#prepare creates an instance of an anonymous subclass of ActionView::Base and adds a couple of helper modules.
Then the view_assigns method stores the controller's instance variables in a hash in that instance.
The local variables are passed in as a hash and stored in an instance variable called locals in the same instance.

Rails rendering instance variable from application.html.erb

I am following the Agile Web Development with Rails 4 book and I'm a bit confused on a part about rendering. The simple version of the question is... within the application.html.erb file there it says
render #cart
This is confusing because I thought that there needed to be a controller associated with that view in order to know which partial and #cart variable to use. Is it simply by naming convention that this line looks for a partial like _cart.html.erb? And in that case does it not actually know what #cart is until it renders that partial?
Some clarification would be lovely. Thanks!
This is a shorthand syntax. From the docs:
Every partial also has a local variable with the same name as the partial (minus the underscore). You can pass an object in to this local variable via the :object option:
<%= render partial: "customer", object: #new_customer %>
Within the customer partial, the customer variable will refer to #new_customer from the parent view.
If you have an instance of a model to render into a partial, you can use a shorthand syntax:
<%= render #customer %>
Assuming that the #customer instance variable contains an instance of the Customer model, this will use _customer.html.erb to render it and will pass the local variable customer into the partial which will refer to the #customer instance variable in the parent view.

How to Pass ActiveRecord Objects as Parameters to Helper Methods in Rails

Many helper methods, such as redirect_to, link_to, and url_for, can take an ActiveRecord object as a parameter instead of a hash that specifies the controller and action. I've seen the parameter passed different ways in different documentation. It sometimes gets passed as a symbol, sometimes as an instance variable, and sometimes as a local variable.
I'm confused about how the different parameter styles get expanded to return urls. I know that following REST conventions should create a url constructed of a controller and action but am unsure when Rails needs a specific parameter style to construct that url. Please help me understand the use cases for passing the ActiveRecord object as a symbol, an instance variable, or a local variable. Are there different requirements based on the method call? Or are there underlying differences in url construction?
Here are some examples:
From the API docs:
link_to "Profile", #profile
redirect_to post
<%= url_for(#workshop) %>
<%= form_for :person do |f| %> (this is described as the “generic #form_for”)
From the Ruby on Rails Guides:
<%= link_to 'New book', new_book_path %>
redirect_to(#book)
form_for(#article)
From the Rails 3 Way:
'link_to' "Help", help_widgets_path, :popup => 1
redirect_to post
url_for(timesheets_path)
form_for offer do |f|
Note: Upon further research, it seems that form_for is able to accept a local variable in the case where the calling view template passes a :locals hash as a parameter. The keys are the locals that can be used in the partial and the values are the instance variables from the template. Is that the correct understanding?
You can pass objects to link_to and url_for
You can also pass an object to a path helper
Both #post and post are objects. #post is an instance variable, and post is either a local variable or a method that will return a post
The only "weird" one is the form_for :post variety. This is old school Rails syntax, and will change this to the form_for #post syntax under the hood.

Ruby On Rails Helpers -- Using instance variables in helpers

I have a helper for a controller:
module CourseStepsHelper
def current_quiz_result
#course_step.step.step_quiz.quiz_attempts.where(:patient_id => current_user.id, :step_quiz_id => #course_step.step.step_quiz.id).first
end
end
It has access to #course_step which is defined in the CourseSteps controller show "action". Is this common practice to use instance variables in helpers?
Depending on the level of detail for this quiz result you may actually want to use a partial. In which case the syntax would be:
<%= render :partial => 'quiz/results', :locals => { :quiz => #quiz } %>
If it's relatively simple and you think it should be in a helper you should make simply make quiz a parameter. Requiring views to provide a specific instance variable to use your helper would likely be frowned upon by other developers.
def quiz_result(quiz) # no need to call it "current" when we supply quiz
# do some stuff
end
It also looks to me that you may want to restructure your models in some way. As you can see I implemented my examples with a Quiz class. I'm not sure what your data model looks like but when you are calling properties that are nested that deep it's generally a sign that something is wrong.
I haven't seen a good argument presented for either case, and stumbled onto this question when I was searching for an answer. Personally, I've been using the instance variables in helper methods where it's possible as this is the dryest approach across both helper and view. Rather than passing the instance variable from my view and defining my helper method to accept it, I can just use it directly in the helper. Slightly less typing, anyway...

Resources