2015-10-09 12 views
23

Badam "zalecany" sposób korzystania z pomocników widoku Railsów (np. link_to, content_tag) w zwykłej klasie ruby, takiej jak prezenter. Wygląda na to, że na tym froncie jest bardzo niewiele informacji i chciałem się zorientować, co myśli grupa Stack.Zalecany sposób korzystania z pomocników widoku Rails w klasie prezentacji

Tak, mamy opcje są .. (uwaga Używam Rails 4 i jestem mniej zaniepokojony starszymi wersjami)

Dołącz wymaganych modułów ręcznie

Jest to prawdopodobnie najczystszym sposób, ponieważ uwzględniono tylko potrzebnych pomocników. Jednak w niektórych przypadkach okazało się, że ta metoda nie działa, ponieważ zwykły kontekst widoku podany w prostych pomocnikach Railsów jest skonfigurowany dla bieżącego żądania. url_for nie znałby na przykład bieżącego żądania, więc host może nie być zgodny.

class MyPresenter 
    include ActionView::Helpers::UrlHelper 
    include ActionView::Helpers::CaptureHelper 

    def wrapped_link 
     content_tag :div, link_to('My link', root_url) 
    end 
end 

Zastosowanie ActionController::Base.helpers

Ponieważ Rails 3, ActionController::Base włączyła metodę helpers dostępu do bieżącego kontekstu widok. Wierzę, że kontekst widoku zapewniany przez tę metodę jest skonfigurowany tak, jak byłoby to w pomocniku railsowym, ale mogę się mylić. Tak naprawdę nie ma na ten temat dokumentacji, która wydaje się niepokojąca, ale w praktyce działa całkiem dobrze.

class MyPresenter 
    def wrapped_link 
     h.content_tag :div, h.link_to('My link', h.root_url) 
    end 

    protected 

    def h 
     ActionController::Base.helpers 
    end 
end 

wierzę kontekst ten widok może być także mieszane z include, ale szyny zobaczyć pomocników setki sposobów i czuje się brudna, aby włączyć je wszystkie bez wyjątku.

wstrzyknąć Kontekst Dzwoniąc prezenterowi

Wreszcie, moglibyśmy po prostu przekazać kontekst widok do klasy, kiedy to zainicjowany (lub alternatywnie w metodzie render)

class MyPresenter 
    attr_accessor :context 
    alias_method :h, :context 

    def initialize(context) 
     @context = context 
    end 

    def wrapped_link 
     h.content_tag :div, h.link_to('My link', h.root_url) 
    end 
end 

class MyController < ApplicationController 
    def show 
     # WARNING - `view_context` in a controller creates an object 
     @presenter = MyPresenter.new(view_context) 
    end 
end 

Osobiście skłaniają się ku tym dwóm opcjom, ale bez ostatecznej odpowiedzi od zespołu Railsów (które udało mi się znaleźć) poczułem się nieco niepewny. Kto lepiej zapytać niż Stack!

Odpowiedz

5

pójdę z mieszanką drugiej i trzeciej opcji, coś jak:

class MyPresenter 
    def initialize(helpers) 
    @h = helpers 
    end 

    def wrapped_link 
    h.content_tag :div, h.link_to('My link', h.root_url) 
    end 

    private 
    attr_reader :h 
end 

Twoja druga opcja wymaga wszystkie testy jednostkowe mają być zgaszone jak ActionController::Base.helpers który może nie jest dobrym rozwiązaniem i swój trzecia opcja, w której używasz ogromnego kontekstu, aby uzyskać dostęp tylko do niektórych metod.

+0

Dobra rada dotycząca niedokładności' ActionController: : Base.helpers', nie myślałem o tym. Stylistycznie wydaje się, że jest to najlepsza droga do zrobienia, a po kilku badaniach uważam, że najlepszym (jedynym) 'view_context' do użycia jest ten dostarczony przez kontrolera lub pomocnika dzwoniącego do prezentera. – tombeynon

1

Naprawdę uzależniłbym to od tego, jakich metod używasz. Jeśli to tylko podstawy takie jak content_tag itp. Wybrałbym sposób na ActionController::Base.helpers. Można również wywołać niektórych pomocników bezpośrednio, np. w przypadku ścieżek wewnątrz modeli prawie zawsze używam czegoś podobnego do linii Rails.application.routes.url_helpers.comment_path.

Jeśli chodzi o konkretny sterownik, trzecia opcja może być przydatna, ale osobiście "czysty" sposób wydaje się lepszy. Draper ma ciekawe podejście zbyt: Oni zapisać view_context dla bieżącego żądania, a następnie przekazywać połączenia do h -helpers do niego: https://github.com/drapergem/draper/blob/master/lib/draper/view_context.rb

To naprawdę tylko kwestia preferencji. Nigdy nie uwzględniłbym wszystkich pomocników na raz, jak już powiedziałeś. Ale druga opcja jest całkiem niezła, jeśli chcesz sam zbudować warstwę prezentacji bez użycia klejnotów takich jak Draper czy Cells.

+0

Dzięki Rudolf, też zajrzałem do Drapera. Ciekawe, że używają też kontrolera 'view_context', chociaż wygląda na to, że mieli z tym dużo problemów w przeszłości - https://github.com/drapergem/draper/issues/124 – tombeynon

Powiązane problemy