Rails: сделать так, чтобы пользовательский помощник URL вел себя как встроенный помощник _path и _url

Мне трудно понять «Rails Way», чтобы добавить URL-адрес подтверждения электронной почты в почтовую программу.

Я предпочитаю не делать это исключительно с помощью REST, потому что, ну, это сложно с текстовой электронной почтой, потому что они не могут PUT запрашивать.

вот мои маршруты.rb: get 'confirm/:id' => 'Confirmations#confirm'

и в моей почтовой программе я хотел бы поместить email_confirm_url(@user.email_token) там, где я хочу, чтобы URL-адрес встречался.

Я создал помощника:

#app/helpers/confirmations_helper.rb
module ConfirmationsHelper
  def email_confirm_url(token)
    "/confirm/#{token}"
  end  
end

все это вроде как работает, за исключением случаев, когда я звоню email_confirm_url(@user.email_token)

Я буквально получаю: "/confirm/abcdefg…"

Когда я хочу: http://myhostname/confirm/abcdefg…

Или в разработке: http://localhost:3000/confirm/abcdefg…

Как сделать так, чтобы мой хелпер URL больше походил на встроенные хелперы <resource>_path и <resource>_url в Rails? хотя на самом деле я полагаю, что мне действительно нужно только нужно _url.

#Edit: у меня есть это в моей конфигурации среды:

#config/environments/development.rb
...
config.action_mailer.default_url_options = { :host => "localhost:3000" }

person Meltemi    schedule 11.01.2013    source источник


Ответы (3)


Недавно я написал помощник для преобразования моего метода _path в метод _url.

Rails использует ActionDispatch::Http::URL.full_url_for для создания методов _url и передает Rails.application.routes.default_url_options для установки host, port и protocol.

Это означает, что вы можете сгенерировать URL-адрес из заданного пути с помощью

ActionDispatch::Http::URL.full_url_for(Rails.application.routes.default_url_options.merge(path: path))

Мой помощник в работе выглядит так:

def self.url_helper(route_name)
  define_method("#{route_name}_url") do |*args|
    path = public_send(:"#{route_name}_path", *args)
    options = Rails.application.routes.default_url_options.merge(path: path)
    ActionDispatch::Http::URL.full_url_for(options)
  end
end

Затем это можно использовать в сочетании с помощником пути для создания метода email_confirm_url:

url_helper :email_confirm
def email_confirm_path(token)
  "/confirm/#{token}"
end 
person James EJ    schedule 22.05.2018

Чтобы получить доступ к объекту запроса, вы должны реализовать эту функцию в контроллере вашего почтовика и передать его в шаблон с помощью переменной.

приложение/почтовые программы/emailer.rb

@tracking_url = "http://#{request.host}:#{request.port}/confirm/#{token}"

app/view/emailer/template_name.html.erb

<%= link_to 'name', @tracking_url %>
person zarazan    schedule 11.01.2013
comment
ActionView::Template::Error: undefined method 'host' for nil:NilClass Кажется, я что-то припоминаю об отсутствии доступа к host или host_with_port в Mailers?!? Как-нибудь обойти это? - person Meltemi; 11.01.2013
comment
обновленный ответ на основе приведенного выше комментария, дайте мне знать, если это сработает. - person zarazan; 12.01.2013

Как насчет использования уже существующего URL плюс конкатенация? т.е. вы можете использовать root_path и root_url, затем вы объединяете, и поведение точно такое же, как у рельсов!

Например, вы можете сделать это:

def mystrangemethod_url(option1, option2)
  "#{ root_url }/#{ option1 }/#{ option2 }"
end

Готово. Простое и единственное требование — установить укажите корневой путь в route.rb. Также с опцией, которую вы установили в development.rb, она будет работать и в почтовых программах.

person Francesco Belladonna    schedule 04.02.2014
comment
Я думаю, что Q больше похож на то, как получить прозрачный доступ к mystrangemethod_url из представления. - person mlt; 09.01.2017