How to pass variable to render in controller method in Rails - ruby-on-rails

I am trying to pass a variable to render like this:
def monitor
#peripheries = Periphery.where('periphery_type_name=?','monitor')
render 'index', type: 'Monitor'
end
Here i want to use 'type' variable inside index view which looks like that:
<%= render 'some_partial', periphery_type: type %>
which also render something. But i want to use that 'type' variable

There are two ways to pass variables between the controller and views:
Instance variables
def monitor
#peripheries = Periphery.where('periphery_type_name=?','monitor')
#type = 'Monitor'
render 'index'
end
Rails will export any of the instance variables belonging to the controller to the view context. So you can call #type in the view or any partial.
Locals
def monitor
#peripheries = Periphery.where('periphery_type_name=?','monitor')
render 'index', locals: { type: 'Monitor' }
end
Note that you need to pass a hash to the locals option. You also need to pass the local variable to partial views:
<%= render 'some_partial', locals: { periphery_type: type } %>
Using locals is often a good idea since it encourages decoupling and can make your partials more reusable.

You can use redirect_to some_path(params: params)

In the monitor method, you can pass the type variable to the index view e.g.
def monitor
#type = 'monitor'
#peripheries = Periphery.where('periphery_type_name = ?', #type)
render 'index'
end
and in your view
<%= render 'some_partial', locals: {periphery_type: #type}
(Note this is not a good way to set up the type variable, I would need a better understanding of the class to suggest how to set that variable.)

Related

Accessing controller data in order to pass local variables for rendering a haml partial in a view

I am trying to render a partial within a view. I have the following code in my view which calls upon the haml document being rendered:
= render :partial => 'data_popups/events'
However I need to pass local variables so 'undefined local variable' is solved. The controller, which contains all of the data, is under dataPopupsController#events ... is there anyway to access the data so I can pass local variables to the partial? Any and all help is welcome. Cheers~
As long as the data is available in your outer view, you can pass it to a partial using the locals option. For instance, if this was on your home page, you could pass the data to the controller like this...
# app/controllers/pages_controller.rb
class PagesController < ApplicationController
def home
#data = Model.get_data
end
end
Then, in your view, pass that #data into your partial using the locals option of the render method:
# app/views/pages/home.html.erb
<%= render :partial => 'data_popups/events', :locals => { :data => #data } %>
Without seeing your controller code, here's a basic example of what you could do:
class UsersController < ApplicationController
def index
#data = User.get_data
end
end
# views/users/index.html.erb
<%= #data.some_method %>
<%= render 'data_popups/events', :locals => { :data => #data } %>
# views/data_popups/_events.html.erb
<%= data.some_other_method %>
Notice that when you pass #data as a local to 'data_popups/events', you now reference the local variable as data.

Rails Instance Variable Accessibility Inside Layout

This may be a silly question, but I'm curious to know how it works. Here is the scenario:
Controller
def some_method
#abc = true
render :template => "show", :layout => "lightbox"
end
Now, when I try to access the instance variable #abc inside layout, it comes out to be nil. But, for following scenario:
Controller
def some_method
render :template => "show", :layout => "lightbox"
end
View (show.html.haml)
- #abc = true
The variable is accessible inside layout.
My question is:
Why is it different that I define an instance variable inside view, it's accessible in layout, but if the same variable is defined in controller instead of view, it's not accessible and come as nil?
In the first case: When you use render in the controller action, it does not inherit the controller action scope automatically. You would have to pass the variable to the render call. Something like:
render :template => "show", :layout => "lightbox", :locals => {abc: #abc}
In the view template you would be able to access the variable abc (without the #), containing the controller #abc variable contents
In the second case: when processing the template "show", rails is creating the #abc variable inside the view scope. So you can access it.
The answers provided in this other question can help you understand what is happening. And the Rails API docs are also a good reference for you

Controller variables don't get passed into view after declaring layout: nil

Hi I have a rails application and in my controller I have declared
def home
render 'home', layout: nil
#press_images = Dir.glob("#{Rails.root}/app/assets/images/media/*.{jpg,jpeg,png}")
.map{ |path| path.split('/').last}
puts #press_images
end
And In my view I have
= #press_images.each do |p|
- puts p
Unfortunately the instance variable doesn't get passed in from controller. But when I delete the render 'home', layout: nil line, it works.
How can I pass in instance variable without having to pass in application layout?
place render at the end of method.
You render view before declaring variable #press_images
Change your method like this.
render should be called at he the end of the method
def home
#press_images = Dir.glob("#{Rails.root}/app/assets/images/media/*.{jpg,jpeg,png}")
.map{ |path| path.split('/').last}
render layout: nil
end

Rails – Display object and a collection in RABL template

I'm using RABL as the foundation for a JSON API. I need to display both an object (#user) and a collection (#posts) in a template. Typically, this is no problem. #posts are a child of #user, so, I just do this:
object #user
attributes :id, :name
child :posts do |post|...
The problem is, I run #posts through a helper method (by_category) in the controller like so:
#user = User.find(params[:id])
#posts = #user.posts.by_category(params[:category])
By just fetching the posts as a child node, I don't apply the helper method – and I can't fetch posts by_category.
I'm wondering how to best approach this, and if there's a way to display both an object and a collection in the same RABL template?
Right from the documentation, you can include locals in partials like this example:
You can also pass in other instance variables to be used in your template as:
Rabl::Renderer.new('posts/show', #post, :locals => { :custom_title => "Hello world!" })
Then, in your template, you can use #custom_title as:
attribute :content
node(:title) { #custom_title }
This allows you to use something like:
Controller:
Rabl::Renderer.new('user/show', #user, :locals => { :posts_category => "examples" })
Partial:
attribute id
node(:posts) { |user| user.posts.by_category(#posts_category) }

Rendering a collection of different classes in Rails

I have a collection that contains instances of several different classes, and I want to render the partial for each instance. I can do this using the following code:
<%= render #results %>
My question is: How can I render the different partials in a different base directory? The above code will look for app/views/stories/_story.html.erb, however, the partials for this action are all kept in a different directory - app/search/_story.html.erb. Is there any way of specifying this?
You could create a helper method like this:
def render_results(results)
result_templates = {"ClassA" => "search/story", "ClassB" => "something/else"}
results.each do |result|
if template = result_templates[result.class.name]
concat render(:partial => template, :object => result)
end
end
end
And then in the view call <% render_results(#results) %>
or you can use is_a?(Object)
if is_a?(classA)
render something_A
elsif is_a?(classB)
render something_B
end
I have a similar situation where I have multiple classes so I use a partial for each class like:
for result in #results
= render :partial => "result_#{result.class.to_s.downcase}", :locals => {:item => result}
end

Resources