Controller variables don't get passed into view after declaring layout: nil - ruby-on-rails

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

Related

active admin how to render form on index page if object not created

I can't understand what I do wrong. My code won't work if subscription blank, but if I created it from rails c, all works fine...
# frozen_string_literal: true
ActiveAdmin.register Subscription do
actions :index
index do
result = Subscriptions::GetPricing.call(admin: current_admin)
if result.success?
render partial: 'subscription_form', locals: { amount: result.plan.amount }
else
flash[:alert] = result.message
render partial: 'subscription_errors'
end
end
end
Now i get: There are no Subscriptions yet. simple message.
And i want left all styles, nav panel, etc how it default, but in container should be store my code from partials.
If your intent is to display an input form if the table is unpopulated then try this:
controller do
def index
collection.size == 0 ? redirect_to(new_subscription_path) : super
end
end
I think what you are trying to do is a bit wrong. index do block is to render the view level mainly. If you want to override controller action you will have to do it like below -
controller do
def index
# your code here
end
end
Have a look at the documentation -
https://activeadmin.info/8-custom-actions.html
https://activeadmin.info/3-index-pages.html

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

How to pass variable to render in controller method in 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.)

Render partial from helper_method

Ok so I have a helper method in the application controller:
def run_test(test_name)
#computation stuff
render :partial => test_name
end
And I call it like so in views:
<%= run_test("testpartial") %>
and it renders ok with only 1 (although... the render partial seems to be returning an array instead of just the partial content?), but if I put the run_test helper call in the view twice I get a double render error, which shouldn't be happening with partials.
Any ideas?
render in a controller versus render in a view are different methods. The controller eventually calls render on a view, but the controller's render method itself expects to be called only once. It looks like this:
# Check for double render errors and set the content_type after rendering.
def render(*args) #:nodoc:
raise ::AbstractController::DoubleRenderError if response_body
super
self.content_type ||= Mime[formats.first].to_s
response_body
end
Note how it raises if called more than once?
When you call helper_method you give the view a proxy to the controller's version of render, which is not intended to be used in the same way as ActionView's, which is, unlike the controller's, expected to be called repeated to render partials and whatnot.
Looks like in Rails 3.2 this just works:
# application_helper.rb
def render_my_partial
render "my_partial"
end
You could try using render_to_string method in the view helper
render_to_string :partial => test_name, :layout => false

Rails render jbuilder in action

I want to push to websockets what normally would be returned from a jbuilder view when the route is called but I cannot call render twice in an action:
def
...
#resource_receivers = "#{#resource.model_name.singular.capitalize}Receiver".constantize.where("#{#resource.model_name.singular}_id": #resource)
#resource_receivers.each do |resource_receiver|
resource_receiver.create_activity :sent, owner: #current_user, recipient: resource_receiver.receiver
end
to_return = render 'api/received/show'
Pusher.trigger('resources', 'resource.received', JSON.parse(to_return.first))
return render :task
end
How would I solve this? Or in general, I'd like to return what normally would be returned from the jbuilder anywhere else in my application, for example if I wanted to refactor this to have a method that pushes to the user
If you want to render a view and assign it to a variable instead of setting it as the response body, then you can use render_to_string.

Resources