开发者

Using content_for inside a controller

开发者 https://www.devze.com 2023-03-11 16:44 出处:网络
This is a weird requirement that may need another approach, but my brain is stuck. I want to accomplish something like this:

This is a weird requirement that may need another approach, but my brain is stuck.

I want to accomplish something like this:

class UsersController < ApplicationController
  before_filter Proc.new { share_params :user_name }, :only => :show
  render_djs
end

class ApplicationController < ActionController::Base
  include ActionView::Helpers::CaptureHelper
  def share_params(*shared)
    content_for(:djs) { shared.inspect }
  end

  def self.render_djs
    before_filter Proc.n开发者_如何学JAVAew {
      render :inline => "<%= yield(:djs) %>" if request.format.djs?
    }
  end
end

I want to use content_for because I may want to add content to the :djs yield in other filters.

However, this code raises undefined method output_buffer=.

I suppose I could use an instance variable, but this seems cleaner, doesn't it?


You need to use the #view_context method to reach the view context and then you can do the same as you would do in a view:

view_context.content_for(:something, view_context.render(partial: 'some_partial'))


you can't use content_for in controllers, even you knew view_context can provide the method. see the issue here: https://github.com/rails/rails/issues/4906

the method view_context always returns a new object. when you call view_context.content_for(:somethin, 'content') it will store content in instance variable of the new object.

you can do an experiment in controllers like the following:

view_context.content_for(:title, 'hello')
view_context.view_flow.content # => {}

a = view_context
a.content_for(:title, 'hello')
a.view_flow.content # =>  {:title=>"hello"}

anyway, if you still want to use content_for in controllers, you can override view_context in controllers as a workaround. but I don't know whether any side effects.

def view_context
  @_view_context ||= super
end


I found this helpful very much in case of setting title for my page.

I can just set content_for from controller

class PostsController < ApplicationController
  def index
    content_for :title, "List of posts"
    ...
  end
end

https://gist.github.com/hiroshi/985457
https://github.com/clmntlxndr/content_for_in_controllers


If like me you are just looking to set content in the controller like a title, then it's probably better to just use a variable that's automatically passed to views and helpers. eg.

controller:

class AController < ApplicationController
  before_action :set_title
  private
    def set_title
      @title = 'Email Subscription'
    end
end

and the helper:

module ApplicationHelper
  def title_suffix
    " - #{@title}" unless @title.nil?
  end
end

and the template:

<!DOCTYPE html>
<html>
<head>
  <title>Standard Title<%= title_suffix %></title>
...


I've found a cleaner way than setting content_for from the controller.

In my case I have sidebar which needs to be displayed for every view.

In my layout I have

<%= yield :sidebar %>

Then I have a partial called _set_sidebar.html.erb which does this

<% content for :sidebar do %>
   <% render :partial => "layouts/sidebar", locals => {:locs => locs} %>
<% end %>

Then I just put a one liner in every view that I want to also have that sidebar

<%= render :partial => "layouts/set_sidebar", locals => {:locs => locs}

Otherwise I was previously using this

https://gist.github.com/985457 with .html_safe when I used render_to_string


view_context did not work in 5.1.4

render inline: erb however, did:


    render inline: <<~ERB, layout: 'layout_expecting_subtabs'
      <% content_for(:subtabs, render(partial: 'somewhere/subtabs') )  %>
      <h1> yielded content </h1>
    ERB

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号