Как я могу сделать помощников рельсов более объектно-ориентированным - PullRequest
1 голос
/ 12 мая 2009

Я бы хотел, чтобы для всех помощников во всем моем приложении на Rails этот синтаксис был заменен:

time_ago_in_words(@from_time)

с этим:

@from_time.time_ago_in_words

В идеале это изменение также сделало бы помощники доступными в любом месте моего приложения (так же, как, скажем, 5.times есть).

Кто-нибудь знает плагин, который это делает? Будет ли трудно катить мою собственную?

Ответы [ 4 ]

4 голосов
/ 12 мая 2009

Если вы создаете новую модель, вы можете заставить ее наследовать методы от существующего класса.

Пример (app / models / mykindofstring.rb):

class Mykindofstring < String

    def all_caps_and_reverse
        self.upcase.reverse
    end 

end

Затем с контроллера:

@my_string = Mykindofstring.new('This is my string')

и, наконец, вызывая его из вида:

<%= @my_string %>

отображается как Это моя строка, а:

<%= @my_string.all_caps_and_reverse %>

отображается как GNIRTS YM SI SIHT.

Класс наследуется от строкового класса, поэтому все методы, применяемые к строке, также применяются к объекту mykindofstring. Метод в нем - это просто новое имя для комбинации двух существующих строковых методов, но вы можете заставить его делать все, что захотите, например, метод для преобразования времени в форматированную строку.

По сути, это просто расширение текущего класса Ruby с помощью ваших собственных методов вместо использования функций / помощников.

Major Edit

Основываясь на комментариях Янса к этому ответу и его собственном ответе на вышеуказанный вопрос, я немного поиграл в Rails и придумал добавить это в application_helper.rb:

module ApplicationHelper
  String.class_eval do
    def all_caps_and_reverse
      self.upcase.reverse
    end
  end
end

Теперь просто вызовите метод для любой строки в приложении:

@string = 'This is a string.'
@string.all_caps_and_reverse

.nirts si sihT

1 голос
/ 19 мая 2014

Если вы используете Ruby 2.1, вы можете использовать уточнения. Они являются альтернативой классам Руби, исправляющим обезьяны. одолжить @ патч обезьяны Джаррода пример:

module MyString
  refine String do
    def all_caps_and_reverse
      upcase.reverse
    end
  end
end

Теперь вы можете использовать это в любом объекте, который вы хотите:

class Post
  using MyString
end
@post.title.all_caps_and_reverse

Вы можете узнать больше о уточнениях здесь.

1 голос
/ 12 мая 2009

Вы не найдете простого способа сделать это для всего своего приложения для всех (или даже большинства) помощников.

Помощники структурированы как модули, предназначенные для включения в классы визуализации представления. Чтобы использовать их, вам нужно иметь при себе копию ActionView (не ОГРОМНАЯ сделка, я полагаю).

Вы всегда можете открыть классы и указать каждого желаемого помощника, хотя:

class Time
  def time_ago_in_words
    ActionView::Base.new.time_ago_in_words self
  end
end

>> t = Time.now
=> Tue May 12 10:54:07 -0400 2009
>> t.time_ago_in_words
=> "less than a minute"
(wait a minute)
>> t.time_ago_in_words
=> "1 minute"

Если вы используете такой подход, я рекомендую кэшировать экземпляр ActionView :: Base, который вы используете. Или, если вы не хотите идти в полутяжелом весе, вы можете создать свой собственный класс, включающий только нужные вам помощники (вы не хотите включать помощников непосредственно в каждый класс Time, Date, String и т. Д., Хотя , так как это довольно сильно загромождает пространство имен метода и конфликтует с естественными именами, которые вы хотите).

0 голосов
/ 12 мая 2009

Сделать модель, TimeAgo или что-то подобное. Реализуйте следующую идею здесь: Фрагмент кода для "превращения в слова" чисел

Затем в вашем контроллере создайте переменные экземпляра, используя этот класс. Тогда, по вашему мнению, позвоните @from_time.in_words

...