I am using render :plain => "some text" and It's working fine.
But as the text gets longer, I wish to place the text in an erb file (e.g. sometext.text.erb) and render the text.erb.
I have a sometext.text.erb in the view folder. But render method doesn't seem to detect it.
How are you rendering plain text? Thanks!
Update: Using the answer below works. So the solution is to set render layout to false. And proceed to use sometext.html.erb instead of sometext.text.erb
Just don't render the layout:
class MyController < ApplicationController
def your_action
render layout: false
end
end
This will follow the convention to find your view, so it will expect your view to be at app/views/my_controller/your_action.html.erb
Related
I want to pass a hash to the render method. In my console everything works fine when I do this:
#object = Object.find(params[:id])
#hash_object = #object.to_liquid
#template = Liquid::Template.parse("Welcome to {{object_title}}")
#template.render('object_title' => #hash_object["title"])
But when i want to render the page through my controller and pass it through an app-proxy which expects vanilla liquid, the hash-key isn't appearing. But it's interpreted, because the view shows blank space. If it wouldn't work at all, the view would show:"Welcome to {{object_title}}" or don't even load because of syntax errors.
I tried almost every possible way to render the template. The next two tryouts are the ones which do not throw an error, but show only a blank where the title should appear:
#pageview = Liquid::Template.parse(File.read(Rails.root + "app/views/app_proxy/show.html.erb"))
render text: #pageview.render('object_title' => #hash_object["title"]), content_type: "application/liquid"
And the second one (which I think is a bit cleaner and more rubylike):
respond_to do |format|
format.html do
render text: #pageview.render('object_title' => #hash_object["title"]), layout: false, content_type: "application/liquid"
end
end
Where is the mistake in these renderings or what am I missing?
# variables are assigned to an instance of a class, not the class itself, so you need to declare it an "initialize" method (or "setup" method, if a test)
render html: instead of render text:
I understand this is a bad idea, but from what I've seen in ApplicationControllers, using:
render :layout => "something" ...
Should render using a layout located at views/layouts/something.html.erb
However, when I am making this call from inside of a view, it errors out with:
Missing partial my_controller_name/something with ...
Searched in:
* "{path here}/app/views"
Which seems to me its looking for a partial, instead of a layout as I specified. Does anyone know what is going on with that?
A sufficient example small enough to reproduce it:
<%= render :layout => 'something' do %>
<div>Hello</div>
<% end %>
This is all under Rails vs 4.0.2
render works differently in controllers than it does in views. In controllers, it's primarily for rendering action templates, while in views, it's primarily for rendering partial templates. When you want to render a specific layout for an action, you have a few options, but all of them are in the controller.
If you want every action in a particular controller to use that layout, you can either specify layout 'something' in that controller (usually near the top) or for a ApplesController, you can create a new layout in app/views/layouts/apples.html.erb and this will automatically be used as the default layout for the ApplesController.
If you want just a single action in a controller to use that layout, you can use your render layout: 'something' inside of a controller action, where the action to render is implied to be the current action.
Links from the Rails docs:
Action Rendering
Partial Rendering
Nested Layouts
I have a method in my posts_controller to display most viewed posts.
def top
#posts = Post.all.order("post.views DESC").page(params[:page]).per(10)
end
In routes I have
resources :posts do
collection do
get :top
end
end
The problem is: when i go to /posts/top i have an error: Missing template posts/top, application/top Do I need to write view files for my every method (top isn't the only one) or I can somehow display them in my index file without duplication of code?
Just render the index template at the end of your method:
def top
#posts = Post.all.order("post.views DESC").page(params[:page]).per(10)
render :index
end
I would suggest you to have a close look to rails layouts and rendering documentation. You will get your answer as well concept behind them. Below is the snippet of doc.
In most cases, the ActionController::Base#render method does the heavy lifting of rendering your application's content for use by a browser. There are a variety of ways to customize the behavior of render. You can render the default view for a Rails template, or a specific template, or a file, or inline code, or nothing at all. You can render text, JSON, or XML. You can specify the content type or HTTP status of the rendered response as well.
I have two different layouts, one is completely custom and the other is bootstrap. For admins we want to render a bootstrap view and for non-admins we render it normally. For the most part this is pretty straight forward because admins and users don't share many views -- but there are some.
My original idea involved overriding render so that it would check if there's a bootstrap version of a file. So for example there would be _user.html.erb and _user.bootstrap.html.erb which would have bootstrap specific templating.
I'd like to not modify any controllers so ideally, something like render 'form' would behave smartly and check if there's an _form.bootstrap.html.erb, and if there isn't it would fallback to _form.html.erb
First attempt
My first attempt looked something like this
# I don't think this is the actual method signature of render
def render(options=nil, extra_options, &block)
# if it should render bootstrap and options is a string and there exists a bootstrap version
# set it up to render the bootstrap view
super(options, extra_options, &b)
end
Current attempt
I'm thinking about registering a template that basically checks if a file exists and then uses erb. I haven't made any progress towards this yet.
I figured it out. This is how I did it:
This is set in the application controller, with a before_filter :render_bootstrap
def render_bootstrap
return unless bootstrap?
new_action = "#{self.action_name}.bootstrap"
has_bs_view = template_exists?(new_action,params[:controller],false) || template_exists?(new_action,params[:controller], true)
if has_bs_view
self.action_name = new_action
end
end
I decided to extend this even further so that inside of a view like show.bootstrap.html.erb you can still use render "form" without doing render "form.bootstrap". This was done by overwriting the rails render helper.
I need to do this for a controller which uses the active_scaffold gem. We have a controller that looked something like this:
class Admin::UsersController < ApplicationController
layout 'admin'
active_scaffold :users do |config|
config.search.columns = [:first_name, :last_name]
end
end
That worked great when we were on Rails 2.3.10, but we're upgrading to Rails 3.0.10. As part of the upgrade, I had to upgrade active_scaffold (currently installed from the rails-3.0 branch of git://github.com/activescaffold/active_scaffold) to be compatible. One problem we were having is that searching the table wasn't working. I would see in my log files:
Rendered <snip>/gems/active_scaffold-25b3d724f35b/frontends/default/views/list.js.rjs within layouts/admin (923.5ms)
Notice that it's rendering the RJS template with the layout specified in the controller. That seems like an unreasonable default to me. Shouldn't RJS templates render without a layout by default? Anyway, I fixed it as such:
class Admin::UsersController < ApplicationController
layout :admin_layout
private
def admin_layout
respond_to do |format|
format.js { false }
format.html { 'admin' }
end
end
end
That fixes the issues with search and pagination. (The RJS template is now rendered without a layout, so the browser can execute the resulting Javascript). I guess my question is, why do I have to tell Rails that it shouldn't render RJS templates with layouts? And is there a better solution? This feels like too much of a hack to me (the bad kind of hack---the kind of hack that will break in the future).
Okay, I figured it out. #numbers1311407's comment under my question led me to check the name of the layout template. It was layouts/admin.haml. With Rails 2, that layout was only rendering for HTML requests, but with Rails 3 it applies to all requests (because it doesn't specify a format type). I renamed it to layouts/admin.html.haml and it works with a simple layout 'admin' in my controller (as opposed to the hack that I had come up with in my question).
So the answer to the question, "Why does Rails render RJS templates within a layout?" is that the layout file was named such that it applies to all formats.
Answer your quastions:
1. There is no magic that Rails renderers layout in for JS format. That's bacause it is default to Rails to render layout with any template unless you explicitly tell to avoid it. You can just look into Rails sources in file: actionpack/lib/action_controller/metal/renderers.rb to see :js renderer.
2.Try to use:
respond_to do |format|
format.js { render *your_any_options*, layout: false }
end