ActionView::Template::Error:
undefined method `host' for nil:NilClass
これは、それがであるとあなたに言っていrequest
ますnil
。これは、コントローラーのスコープ外(つまり、拡張するクラス内ActionMailer::Base
) request
が存在しないためです。
のように他のデータを行うのと同じように、request
オブジェクトまたは必要な部分(request.host_with_port
)だけをメーラーに渡す必要がありuser
ますemail_confirmation
。
したがって、次のようなcreateメソッドがあります
def create
@user = User.new
@user.assign_attributes(params[:user])
@user.save
@user.send_email_confirmation
end
User
モデルの中には、send_email_confirmation
このような方法があります
class User < ActiveRecord::Base
def send_email_confirmation
UserMailer.email_confirmation(self).deliver
end
あなたのメーラーは次のemail_confirmation
ように見えます
def email_confirmation(user)
@user = user
@url = "http://www.domain.com/"
mail(to: user.email, subject: "Email Confirmation")
end
モデルからメーラーにリクエストを送信するのは最善の方法ではありません。関心の分離をより明確に保つ必要があります。request
これは問題の一部であり、コントローラーアクションからメーラーテンプレートに何かを渡そうとしたときに、望ましくない複雑さを見つけている理由です。
私が提案するのは、ワーカークラスを作成することです。ここでは、でクラスを設定する方法を説明します。lib/
同じ概念をのようなものに適用できますlib/your_app/workers/user.rb
。
このクラスでは次のことができます
module YourApp
module Workers
module User
extend self
def create!(params, options{})
options.reverse_merge! host: ""
user = User.new
user.assign_attributes(params)
user.save
UserMailer.email_confirmation(user, host).deliver
user
end
end
end
end
その場合、コントローラーのアクションは単純に
def create
@user = ::YourApp::Worker::User.create!(params[:user], host: request.host_with_port)
end
これで、メーラーメソッドは次のようになります。
def email_confirmation(user, host)
@user = user
token = "" # define token somehow
@url = "#{host}/confirm/#{token}"
mail(to: user.email, subject: "Email Confirmation")
end
最後に、使用されなくなったためsend_email_confirmation
、モデルからemail_confirm_url
メソッドを削除したり、ヘルパーからメソッドを削除したりできます。注意すべき2つのこと
- 上記の私の例には、検証/エラーチェックの方法で何も含まれていません
- 私の例では、どこ
token
が定義され、使用されているかについて推測しています。
ご覧のとおり、この「worker」クラスを導入することで、重複することなく機能を明確に分離できます。