2015-04-03 5 views
7

często mają wiele szyn aplikacje uruchomione równolegle, więc mam skonfigurowane je stosować różne porty:Domyślne_url_opcje w ActionMailer: Jak automatycznie pobrać port z DefaultOptions?

# Change default port of development server, see http://stackoverflow.com/questions/18103316 
require 'rails/commands/server' 
module DefaultOptions 
    def default_options 
    super.merge!(Port: 3001) 
    end 
end 

Teraz ważne jest, że to działa również dla ActionMailer w env rozwoju:

config.action_mailer.default_url_options = {host: 'localhost:3001'} 

Ale zamiast tego na twardym dysku, chcę ustawić go bezpośrednio z poziomu DefaultOptions. Jak to jest możliwe?

Odpowiedz

1

Oto małe odchylenie od kodu:

# config/boot.rb 
require 'rails/commands/server' 
module DefaultOptions 
    PORT = 3001 

    def default_options 
    super.merge!(Port: PORT) 
    end 
end 

# This line was part of the Stack Overflow answer you quoted, and is important 
# With newer Ruby versions, you can call `prepend` directly 
Rails::Server.prepend(DefaultOptions) 

Wynika to przepełnienie stosu odpowie pan zacytował, z wyjątkiem wydobywania port do stałej DefaultOptions::PORT. Teraz zauważ, że nie ma nic magicznego w nazwie modułu DefaultOptions, po prostu definiuje zwykły moduł, który jest następnie dodawany do Rails::Server. Mogłeś nazwać go tak, jak chciałeś. Po uruchomieniu serwera programistycznego tworzony jest nowy obiekt Rails::Server iw pewnym momencie wywoływana jest metoda default_options dla tego obiektu. Z powodu użycia prepend, wyszukiwanie metody osiągnie najpierw metodę określoną w DefaultOptions. super w tej metodzie po prostu wywołuje oryginalny nieprzypisany default_options zdefiniowany w Rails::Server.

Powodem, dla którego "trudno" uzyskać wartości w default_options jest to, że jest to metoda instancji, co oznacza, że ​​można uzyskać do niej dostęp tylko w instancji klasy Rails::Server, a my zazwyczaj nie posiadamy blokady obiekt serwera. Można uzyskać do niego dostęp w następujący sposób:

# config/development.config 
require 'rails/commands/server' 
Rails::Server.new.default_options[:Port] 

Ale myślę, że to niepotrzebne uzależnienie i tworzenie obiektu. Nazwa Rails::Server oznacza również, że możemy chcieć mieć tylko jeden obiekt tej klasy, a ja nie tworzyłbym instancji obiektów serwera tylko po to, aby uzyskać ich skrót konfiguracji. W związku z tym wyodrębnianie portu do stałej, bez względu na to, czy masz odwołanie do obiektu serwera - DefaultOptions::PORT - jest czystsze w moim umyśle.

Więc teraz, że mamy trzymać DefaultOptions::PORT stałej, można używać go w mailer:

# config/development.rb 
    config.action_mailer.smtp_settings = { 
    :port => DefaultOptions::PORT, 
    :address => '...', 
    :user_name => '...', 
    :password => '...', 
    :domain => '...', 
    :authentication => :plain 
} 

Można również rozważyć Mailer'a i portu definicji w pliku yaml, więc co robisz nie trzeba "posypywać" częściami swojej konfiguracji w różnych lokalizacjach - może to zaoszczędzić ci później.

Jeśli chcesz to zrobić, możesz utworzyć klasę opakowania samodzielnie, która używa YAML.load_file, aby załadować nowy plik konfiguracyjny yaml do wartości mieszania. Alternatywnie, sprawdź gem Figaro, daje wygodny sposób na umieszczenie wszystkich konfiguracji Rails w jednym pliku - application.yml - i dostęp do nich z dowolnego miejsca przy użyciu ENV.

Jeśli było użyć Figaro, na przykład, mają klucz application.ymlPORT, wówczas kod może wyglądać następująco:

# config/boot.rb 
require 'rails/commands/server' 
module DefaultOptions 
    def default_options 
    super.merge!(Port: ENV['PORT']) 
    end 
end 

Rails::Server.prepend(DefaultOptions) 

# config/development.rb 
config.action_mailer.smtp_settings = { 
    :port => ENV['PORT'], 
    :address => ENV['SMTP_SERVER'], 
    :user_name => ENV['SMTP_LOGIN'], 
    :password => ENV['SMTP_PASSWORD'], 
    :domain => ENV['MAILER_DOMAIN'], 
    :authentication => :plain 
} 
0

Można użyć Rails::Server::Options, aby uzyskać potrzebne informacje, a następnie odpowiednio skonfiguruj ActionMailer:

config.action_mailer.default_url_options = { host: Rails::Server.new.options[:Host], port: Rails::Server.new.options[:Port] }