jbuilder: Helper methods not available in partials

Hi,

I can’t to access helper methods from a controller concern in a partial view:

This is where the helper methods are defined.

# app/controllers/concern/user_management.rb
module UserManagement
    extend ActiveSupport::Concern

    included do
        helper_method :current_user, :owner?, :system_user?
    end

    protected
    # ... methods
end

Application controller includes the UserManagement concern.

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
    include UserManagement
end

This is just an specific example, but in order to reuse my views, I want to be able to access concern helper methods in partials.

# app/controllers/admin/accounts_controller.rb
module Admin
    class AccountsController < ApplicationController
        # ...
        def show 
        end
        # ...
        private

        def set_account
            @account = Account.find(params[:id])
        end
    end
end

This is the view tree:

app/
    views/
        accounts/
            _account.json.jbuilder
            show.json.jbuilder
        branches/
            _branch.json.jbuilder

Helper methods are available in views:

# app/views/accounts/show.json.jbuilder
#
# I can access owner? and system_user? helper methods from concern here.
#
json.account do
    json.partial! 'accounts/account', account: @account
end

But can’t access helper methods on partials:

# app/views/accounts/_account.json.jbuilder
json.extract! account, :id, :name
# Account has many branches
json.branches do
    json.array! account.branches, partial: 'branches/branch', as: :branch
end

This is the partial where I need to make a decision based on whether the user is a system user or an owner:

# app/views/branches/_branch.json.jbuilder
json.extract! branch, :name
if system_user?
    json.billing_addresses do
        json.array! branch.billing_addresses, partial: 'billing_addresses/billing_address', as: :billing_address
    end
elsif owner?
    json.billing_address do
        json.partial! 'billing_addresses/billing_address', billing_address: branch.billing_addresses.find_by_account(current_user.account_id)
    end
end

Is it possible to execute helper methods from partials? Isn’t it in the same context as the view?

Thanks in advance.

About this issue

  • Original URL
  • State: closed
  • Created 10 years ago
  • Comments: 17

Most upvoted comments

For what it’s worth I am seeing this too.

In app/helpers/application_helper.rb

module ApplicationHelper
  def foo_helper
    "bar"
  end

In _partial.json.jbuilder

json.foo foo_helper

The partial can’t find foo_helper

> undefined local variable or method `foo_helper'

But when I do this hack to load the helper as a new class I can access foo_helper…

json.foo Class.new.extend(ApplicationHelper).foo_helper

But that hack isn’t even very useful because it only extends a new class with ApplicationHelper itself, and the code in ApplicationHelper needs access to other helpers, so I’d have to include every other helper inside ApplicationHelper.

I hope this helps, thanks for your hard work on jbuilder.

I just ran into this same issue. It seems like only methods in ApplicationHelper are available in the partials, but methods from other custom helpers are not included. I did a workaround to move my methods into ApplicationHelper for now.

In addition to @mateusluizfb’s (and @mookie5dc’s) solution, you can extend Your::HelperClass at the top of your jbuilder partial where you want to use the helper methods.

I’m not sure if it’s a good idea - but it does work.

I adapted the @mookie5dc solution to include all the separated helpers in the application_helper. It’s no longer necessary to add all the helper functions in the application_helper. Example:

module ApplicationHelper
  include JsonFormaterHelper
end

I was able to create it in my app but no I have not taken the time to start a new app just to prove it.

@samacs FYI another workaround it looks like my app is using is…

(it’s returning JSON search results)

  def render_json_partial(record, highlight, template)
    view = ActionView::Base.new(ActionController::Base.view_paths, {})
    view.class_eval do
      include ApplicationHelper
      include TextHelper
      include Rails.application.routes.url_helpers
    end
    view.render(partial: template, locals: {source: record, highlight: highlight}, handlers: [:jbuilder])
  end

Including ApplicationHelper into this view and then rendering the view seems to give jbuilder access to the helpers. Might be better than non-DRYing it up.

I just had this problem as well in a .erb file. I solved it by extend-ing the view helper from within the partial. So, it is definitely not a jbuilder problem.