Rails - Как использовать помощник внутри контроллера

207

хотя я понимаю, что вы должны использовать помощник внутри представления, мне нужен помощник в моем контроллере, так как я создаю объект JSON для возврата.

Это выглядит примерно так:

def xxxxx

   @comments = Array.new

   @c_comments.each do |comment|
   @comments << {
     :id => comment.id,
     :content => html_format(comment.content)
   }
   end

   render :json => @comments
end

как я могу получить доступ к своему html_formatпомощнику?

AnApprentice
источник
2
Вы можете рассмотреть ответ @ grosser, он гораздо более полный.
Tokland
Я знаю, что это старо, но ... что не так с обычными рубиновыми классами? : p
Тарек

Ответы:

205

Примечание: это было написано и принято в Rails 2 дня; в настоящее время ответ грубее - путь.

Вариант 1. Вероятно, самый простой способ - включить вспомогательный модуль в контроллер:

class MyController < ApplicationController
  include MyHelper

  def xxxx
    @comments = []
    Comment.find_each do |comment|
      @comments << {:id => comment.id, :html => html_format(comment.content)}
    end
  end
end

Вариант 2: Или вы можете объявить вспомогательный метод как функцию класса и использовать его следующим образом:

MyHelper.html_format(comment.content)

Если вы хотите использовать его как функцию экземпляра и функцию класса, вы можете объявить обе версии в вашем помощнике:

module MyHelper
  def self.html_format(str)
    process(str)
  end

  def html_format(str)
    MyHelper.html_format(str)
  end
end

Надеюсь это поможет!

Ксавье Холт
источник
Спасибо, но я немного запутался. Прямо сейчас мой помощник находится в /app/helpers/application_helper.rb ... И вы предлагаете мне переместить помощника в ApplicationController?
AnApprentice
Я добавил 'include ApplicationHelper' в мой application_controller, но при этом возникает ошибка с 'NoMethodError (неопределенный метод `html_format' для ApplicationHelper: Module): '
AnApprentice
1
@AnApprentice Похоже, вы поняли это, но я немного подправил свой ответ, надеюсь, прояснить ситуацию. В первой версии вы можете просто использовать html_format- вам нужно только MyHelper.html_formatво второй.
Ксавье Холт
4
Это не работает, когда вспомогательный метод, который вы хотите использовать, использует методы представления, такие как link_to. Контроллеры не имеют доступа к этим методам, и большинство моих помощников используют эти методы. Кроме того, включение помощника в контроллер выставляет все методы помощника как общедоступные действия, что не очень хорошо. view_contextпуть в Rails 3.
GregT
@GregT - Раньше я не видел ответа грубее, так как он появился немного позже, но мне он тоже больше нравится. Он только что получил мой голос.
Ксавье Холт
304

Ты можешь использовать

  • helpers.<helper>в Rails 5+ (или ActionController::Base.helpers.<helper>)
  • view_context.<helper>( Rails 4 и 3 ) (ПРЕДУПРЕЖДЕНИЕ: это создает новый экземпляр представления за вызов)
  • @template.<helper>( Рельсы 2 )
  • включить помощника в одном классе, а затем singleton.helper
  • include помощник в контроллере (ВНИМАНИЕ: превратит все вспомогательные методы в действия контроллера)
грубее
источник
56
Этот ответ еще лучше! В рельсах 3 простой вызов view_context.helper_functionпрост и прекрасно работает. ActionController::Base.helpers.helper_functionодинаково хорош
trisweb
29
view_context= гений
n_i_c_k
5
ВНИМАНИЕ: не используйте view_context. Он будет создавать новый экземпляр представления для каждого вызова ...
Fny
7
ActionController::Base.helpers.helper_functionне похоже на работу. Я получаю NoMethodError - undefined method spell_date_and_time' for #<ActionView::Base:0x007fede56102d0>:при попытке вызвать ActionController::Base.helpers.spell_date_and_time()метод контроллера. Звонок view_context.spell_date_and_time()работает, однако.
сом
37
rails 5: просто используйте helpers.helper_functionв своем контроллере ( github.com/rails/rails/pull/24866 )
Маркус
80

В Rails 5 используйте helpers.helper_functionсвой контроллер.

Пример:

def update
  # ...
  redirect_to root_url, notice: "Updated #{helpers.pluralize(count, 'record')}"
end

Источник: Из комментария @Markus на другой ответ. Я чувствовал, что его ответ заслуживает его собственного ответа, так как это самое чистое и простое решение.

Ссылка: https://github.com/rails/rails/pull/24866

Джерри Шоу
источник
6
Немного странно, что в консоли вы будете звонить helperв единственном числе, а в контроллере - во множественном числе.
Товарищ незнакомец
10

Моя проблема решена с помощью Варианта 1. Вероятно, самый простой способ - включить ваш вспомогательный модуль в ваш контроллер:

class ApplicationController < ActionController::Base
  include ApplicationHelper

...
Тадэу Эстевес-младший
источник
1
Единственный недостаток, что он добавляет действия контроллера с именем вспомогательных функций. Но я тоже так делаю :)
Феликс,
9

В общем, если помощник должен использоваться в (просто) контроллерах, я предпочитаю объявлять его как метод экземпляра class ApplicationController.

Франко
источник
5
Как защищенный метод
Бенджамин Крузье
3

В Rails 5+ вы можете просто использовать функцию, как показано ниже на простом примере:

module ApplicationHelper
  # format datetime in the format #2018-12-01 12:12 PM
  def datetime_format(datetime = nil)
    if datetime
      datetime.strftime('%Y-%m-%d %H:%M %p')
    else
      'NA'
    end
  end
end

class ExamplesController < ApplicationController
  def index
    current_datetime = helpers.datetime_format DateTime.now
    raise current_datetime.inspect
  end
end

ВЫВОД

"2018-12-10 01:01 AM"
Ravistm
источник
0
class MyController < ApplicationController
    # include your helper
    include MyHelper
    # or Rails helper
    include ActionView::Helpers::NumberHelper

    def my_action
      price = number_to_currency(10000)
    end
end

В Rails 5+ просто используйте помощников ( helpers.number_to_currency (10000) )

AlbertM
источник