本文介绍了当我使用Sendgrid Rails Heroku发送电子邮件时,如何抓住或访问不同的模型属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用设计,并用脚手架教科书。
我喜欢实施我的策略。
当买家点击@ textbook.title - >买家可以发送电子邮件到@教科书的卖家。
我有每个模型都有'user_email'的列
所以,只要卖家创建一个@textbook,自动将current_user.email保存到@ textbook.user_email中。



我只是不知道如何抓住卖家的user_email并发送电子邮件。



我有以下



教科书模型:

  class Textbook< ActiveRecord :: Base 

belongs_to:user

validates:title,:presence => true
validates:subject,,presence => true
validates:price,:presence => true
validates:offer,:presence => false
验证:created_at,:presence => false
验证:user_email,:presence => true
validates:description,:presence => true
end

我不确定此模型语法是否适用于subject和current_user.email
联系人型号:

  class Contact< MailForm :: Base 
属性:name,:validate => true
属性:current_user.email,:validate => /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\\ \\ z / i
属性:message,:validate => true

def header
{
:subject => 我喜欢买#{@textbook.id.title},
:to => @ textbook.id.user_email,
:from => %(<#{email}>)
}
end
end

我的细节问题是这样的:
如果用户点击联系人,当买家在特定的教科书里面时,它将用户链接到教科书#show。以下是用户点击联系的形式。



如何确保以下视图访问正确的textbook.id或textbook.title?

 < h1>联系卖家< / h1> 

< div>
<%= form_for @contact do | f |%>
< h3>发送电子邮件:<%= @ textbook.id.title%> < / H3>

<%= f.label:message%>< br>
<%= f.text_area:message,as::text%>< br>

<%= f.submit'发送消息',class:'button'%>
<%end%>
< / div>

特别的是,我不知道如何处理来自不同视图中不同模型的抓取属性。



提前谢谢!



- !# - !# - !# - !# - ! - !# - !# - !# - !# - !# - !# - !# - !# - !# - !# - !# - !





我有这样的联系人控制器:

  ContactsController< ApplicationController 
def new
@contact = Contact.new
end

def create
@contact = Contact.new(params [:contact])
#@contact.request = request
如果@ contact.deliver
flash [:success] =发送电子邮件。
else
flash [:alert] =无法发送电子邮件。
render:new
end
end
end

我刚刚编辑了我的'联系人' MailForm :: Base'

  class Contact< MailForm :: Base 
属性:name,:validate => true
属性:email,:validate => /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\\ \\ z / i
属性:message,:validate => true

def header
{
:subject => 我喜欢买#{textbook.title},
:to => @ textbook.user_email,
:from => %(<#{current_user.email}>)
}
end

end



但是我收到错误:

  ContactsController中的NameError #create 
未定义的局部变量或#< Contact:0x007fbac641be40>的方法`textbook'

提取源(绕行#8):
def标头
{
:subject => 我喜欢买#{textbook.title},
:to => @ textbook.user_email,
:from => %(<#{current_user.email}>)
}

@zeiv I固定的textbook.title - > @ textbook.title
我得到错误另一个错误。

  ContactsController#中的NoMethodError创建
undefined方法标题为nil:NilClass
def标头
{
:subject => 我喜欢买#{@textbook.title},
:to => @ textbook.user_email,
:from => %(<#{current_user.email}>)
}

/textbooks.html.erb:

 < div class =container> 

< p>
< h3>< strong>标题:< / strong>
<%= @ textbook.title%>< / h3>
< / p>

< p>
< strong>主题:< / strong>
<%= @ textbook.subject%>
< / p>

< p>
< strong>价格:< / strong>
$<%= @ textbook.price%>
< / p>

< p>
< strong>接受优惠:< / strong>
<%if @ textbook.offer == true%>
<%='是'%>
<%else%>
<%='否'%>
<%end%>
< / p>

< p>
< strong>说明:< / strong>
< pre><%= @ textbook.description%>< / pre>
< / p>

< p>
< strong>图片:< / strong>
< pre><%= image_tag @ textbook.thumbnail.url(:medium)%>< / pre>
< / p>

< p>
< strong>创建于:< / strong>
<%= @ textbook.created_at.strftime(%d%b。%Y)%>
< / p>

< p>
<%= link_to'Contact',new_contact_path%>
< / p>

<%if @ textbook.user_email == current_user.email%>
<%= link_to'Edit',edit_textbook_path(@textbook)%> |
<%= link_to'返回列表',textbooks_path%>
<%else%>
<%= link_to'返回列表',textbooks_path%>
<%end%>

我有textbooks_controller:

  class TextbooksController< ApplicationController 
before_action:set_textbook,只有:[:show,:edit,:update,:destroy]
#before_action:set_textbook,only:[:show]
#before_action:authorize_resource! :[:new,:index,,show]

#GET / textbooks
#GET /textbooks.json
def index
#@ textbooks = Textbook.all
@textbooks = Textbook.all.order(created_at::desc).paginate(page:params [:page],per_page:10)
#@ textbooks = Textbook.paginate(:page => params [:page],:per_page => 10)
end

#GET /教科书/ 1
#GET /textbooks/1.json
def show
end

我有配置/路由:

 资源:教科书
资源:联系人,仅:[:新建,创建]

devise_for:users

当我在这一刻耙路时4/17 5:05 pm

  new_textbook GET /textbooks/new(.:format)教科书#new 
edit_textbook GET /textbooks/:id/edit(.:format)textbooks#edit
textbook GET /textbooks/:id(.:format)textbooks#show
PATCH /textbooks/:id(.:format )教科书#update
PUT /textbooks/:id(.:format)教科书#update
DELETE /textbooks/:id(.:format)教科书#destroy
联系人POST / contacts(。 :format)contacts#create
new_contact GET /contacts/new(.:format)contacts#new



更新2 - !# - !# - !# - !# - !# - !# - !# - !# - !# - !# - - !# - !



下面是04/17/2016 11:00 pm
@zeiv我做了你告诉我的
但是当我点击视图/教科书/ show.html.erb中的联系人按钮仍然会收到错误

  #views / textbooks / show.html.erb 
< p>
<%= link_to'Contact',new_contact_textbook_path%>
< / p>

我的routes.rb现在有:

  Rails.application.routes.draw做

资源:教科书做
成员做
获得'联系',到:'教科书# new_contact',as:'new_contact'
post'contact',to:'textbooks#send_contact',as:'send_contact'
end
end

现在rake路线:

 前缀动词URI模式控制器#Action 
new_contact_textbook GET /textbooks/:id/contact(.:format)教科书#new_contact
send_contact_textbook POST /textbooks/:id/contact(.format)教科书#send_contact
教科书GET /textbooks(.:format)教科书#index
POST /textbooks(.:format)教科书#创建
new_textbook GET /textbooks/new(.:format)教科书#新
edit_textbook GET /textbooks/:id/edit(.:format)textbooks#edit
textbook GET /textbooks/:id(.:format)textbooks#show
PATCH /textbooks/:id(.:format )教科书#update
PUT /textbooks/:id(.:format)教科书#update
DELETE /textbooks/:id(.:format)教科书#destroy

我得到的错误是:

  NoMethodError in Textbooks#new_contact 

未定义的方法id为nil:NilClass
提取源(绕行#4):
< div>
Texbook id是:<%= @ textbook.id%>
< / div>

我正在运行英雄本地的错误显示:

  10:56:13 PM web.1 |在layouts / application(2.0ms)中渲染教科书/ new_contact.html.erb 
10:56:13 PM web.1 | 7ms内完成500内部服务器错误(ActiveRecord:0.1ms)
10:56:13 PM web.1 | ActionView :: Template :: Error(未定义的方法`id'for nil:NilClass):
10:56:13 PM web.1 | 1:< h1>联系卖家! - 工作? < / H1>
10:56:13 PM web.1 | 2:
10:56:13 PM web.1 | 3:< div>
10:56:13 PM web.1 | 4:Texbook id是:<%= @ textbook.id%>
10:56:13 PM web.1 | 5:< / div>


解决方案

基本上你需要做的是写你的邮件和控制器,使您想要的所有信息传递给邮件程序。因此,如果您想要将教科书模型的实例传递给邮件程序,则需要从发送电子邮件的控制器执行此操作。您可能会希望将您的联系控制器路线嵌套在您的教科书路线中以帮助您。或者,而不是拥有联系人的整个控制器,只需在您的教科书控制器中联系操作

 #route.rb 
...
资源:教科书做
成员做
获取联系人,到:教科书#new_contact,作为:new_contact
postcontact,to:textbooks#send_contact,as:send_contact
end
end

这将为您提供路线,如 / textbook / 24 / contact member do 表示路由是针对您的模型的单个实例而不是整个集合,因此您需要指定在调用帮助者时使用的教科书: code> new_contact_textbook_path(@ textbook.id)。



所以在您的教科书控制器中,您可以这样做:

 #textbooks_controller.rb 
before_action:set_textbook,仅:[:show,:edit,:update,:destroy,,new_contact, :send_contact]
...
def new_contact
#我们没有在此处联系。新建
#只需在这里放置逻辑,您需要显示
结束

def send_contact
message = params [:message]
如果Contact.send_contact(@textbook,current_user,message).deliver
flash [:success] =邮件已发送。
redirect_to @textbook
else
flash [:alert] =发送电子邮件时出现问题。
render:new_contact
end
end

然后把你的 new_contact.html.erb 文件与您其他教科书视图。

  ; H1>联系卖家< / h1> 

< div>
<%= form_tag send_contact_textbook_path(@ textbook.id)do%>
< h3>发送电子邮件:<%= @ textbook.title%> < / H3>

<%= label_tag:message,键入您的消息:%>< br>
<%= text_area_tag:message%>< br>

<%= submit_tag'发送消息',类:'按钮'%>
<%end%>
< / div>

请注意,我正在使用 form_tag form_for ,因为我们没有一个Contact对象来传递它。 (也就是说,联系人不是一个模特,它是一个邮件。)



你的邮件将看起来像这样:

  class Contact< ApplicationMailer 

def send_contact(textbook,current_user,message)
@textbook = textbook
@current_user = current_user
@message = message
mail(
from:#{@current_user.name}<#{@ current_user.email}>,
to:@ textbook.user.email,
subject:我想买#
reply_to:@ current_user.email,

end
end

最后,将邮件的模板/视图放在 /app/views/contact/send_contact.html.erb中

 <!DOCTYPE html> 
< html>
< head>
< meta content ='text / html; charset = UTF-8'http-equiv ='Content-Type'/>
< / head>
< body>
< h1><%= @ current_user.name%>想知道<%= @ textbook.title%>:< / h1>
< p><%= @message%>< / p>
< / body>
< / html>

那应该做到!虽然你可能需要调整一些东西来满足你的需要。另请参阅这些链接了解更多示例:






I am using devise, and scaffolded Textbook.I like to implement my strategy.When buyer clicks an @textbook.title -> Buyer can send an email to the @textbook's seller.I have every model has column for 'user_email'So, Whenever a seller create a @textbook, automatically current_user.email is saved into @textbook.user_email.

I just don't know how to grab the seller's user_email and send email.

I have following

Textbook model:

class Textbook < ActiveRecord::Base

    belongs_to :user

    validates :title, :presence => true
    validates :subject, :presence => true
    validates :price, :presence => true
    validates :offer, :presence => false
    validates :created_at, :presence => false
    validates :user_email, :presence => true
    validates :description, :presence => true
end

I am not sure this model syntax is right for subject and current_user.emailContact model:

class Contact < MailForm::Base
    attribute :name,      :validate => true
    attribute :current_user.email,     :validate => /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
    attribute :message, :validate => true

    def headers
        {
          :subject => "I like to buy #{@textbook.id.title}",
          :to => "@textbook.id.user_email",
          :from => %(<#{email}>)
        }
    end
end

My detail question is this:If a user clicks 'contact' when buyer was inside of a specific textbook ant it links the user to textbook#show. Below is the form when the user clicked 'contact'.

How can I make sure this below view access the correct textbook.id or textbook.title?

<h1> Contact to the Seller </h1>

<div>
    <%=form_for @contact do |f|%>
        <h3>Send email for: <%[email protected]%> </h3>

        <%= f.label :message %><br>
        <%= f.text_area :message, as: :text %><br>  

        <%=f.submit 'Send message', class: 'button' %>
    <%end%>
</div>

Specially, I don't know how to handle grab attributes that is from different model inside different views.

Thank you in advance!

-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!

Update 1:

I have contact controller like this:

class ContactsController < ApplicationController
    def new
        @contact = Contact.new
    end

    def create
        @contact = Contact.new(params[:contact])
        #@contact.request = request
        if @contact.deliver
            flash[:success] = "Email sent."
        else
            flash[:alert] = "Cannot send an email."
            render :new
        end
    end
end

I just edited my 'class Contact < MailForm::Base'

class Contact < MailForm::Base
attribute :name,      :validate => true
attribute :email,     :validate => /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
attribute :message, :validate => true

def headers
    {
      :subject => "I like to buy #{textbook.title}",
      :to => "@textbook.user_email",
      :from => %(<#{current_user.email}>)
    }
end

end

But I got error:

NameError in ContactsController#create
undefined local variable or method `textbook' for #<Contact:0x007fbac641be40>

Extracted source (around line #8):        
    def headers
        {
          :subject => "I like to buy #{textbook.title}",
          :to => "@textbook.user_email",
          :from => %(<#{current_user.email}>)
        }

@zeiv I fixed textbook.title -> @textbook.titleI get error an another error.

NoMethodError in ContactsController#create
undefined method `title' for nil:NilClass
    def headers
        {
          :subject => "I like to buy #{@textbook.title}",
          :to => "@textbook.user_email",
          :from => %(<#{current_user.email}>)
        }

I have views/textbooks.html.erb:

<div class="container">

        <p>
          <h3><strong>Title:</strong>
          <%= @textbook.title %></h3>
        </p>

        <p>
          <strong>Subject:</strong>
          <%= @textbook.subject %>
        </p>

        <p>
          <strong>Price:</strong>
          $<%= @textbook.price %>
        </p>

        <p>
          <strong>Accept Offer:</strong>
          <%if @textbook.offer == true%>
            <%='Yes'%>
          <%else%>
            <%='No'%>
          <%end%>
        </p>

        <p>
          <strong>Description:</strong>
          <pre><%= @textbook.description %></pre>
        </p>

        <p>
          <strong>Image:</strong>
          <pre><%= image_tag @textbook.thumbnail.url(:medium) %></pre>
        </p>

        <p>
          <strong>Created on:</strong>
          <%= @textbook.created_at.strftime("%d %b. %Y") %>
        </p>

        <p>
            <%= link_to 'Contact', new_contact_path %>
        </p>

        <%if @textbook.user_email == current_user.email %>
            <%= link_to 'Edit', edit_textbook_path(@textbook) %> |
            <%= link_to 'Back to list', textbooks_path %>
        <%else %>
            <%= link_to 'Back to list', textbooks_path %>
        <%end%>

And I have textbooks_controller:

class TextbooksController < ApplicationController
  before_action :set_textbook, only: [:show, :edit, :update, :destroy]
  #before_action :set_textbook, only: [:show]
  #before_action :authorize_resource!, except: [:new, :index, :show]

  # GET /textbooks
  # GET /textbooks.json
  def index
    #@textbooks = Textbook.all
    @textbooks = Textbook.all.order(created_at: :desc).paginate(page: params[:page], per_page: 10)
    #@textbooks = Textbook.paginate(:page => params[:page], :per_page => 10)
  end

  # GET /textbooks/1
  # GET /textbooks/1.json
  def show
  end

I have config/routes:

resources :textbooks
  resources :contacts, only: [:new, :create]

  devise_for :users

When I rake routes at this moment 4/17 5:05pm

new_textbook GET    /textbooks/new(.:format)               textbooks#new
           edit_textbook GET    /textbooks/:id/edit(.:format)          textbooks#edit
                textbook GET    /textbooks/:id(.:format)               textbooks#show
                         PATCH  /textbooks/:id(.:format)               textbooks#update
                         PUT    /textbooks/:id(.:format)               textbooks#update
                         DELETE /textbooks/:id(.:format)               textbooks#destroy
                contacts POST   /contacts(.:format)                    contacts#create
             new_contact GET    /contacts/new(.:format)                contacts#new

UPDATE 2 -!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!

below is after 04/17/2016 11:00pm@zeiv I did what you told me.But still I get error when I click 'contact' button in views/textbooks/show.html.erb

#views/textbooks/show.html.erb
<p>
    <%= link_to 'Contact', new_contact_textbook_path %>
</p>

my routes.rb has now:

Rails.application.routes.draw do

  resources :textbooks do
    member do
      get 'contact', to: 'textbooks#new_contact', as: 'new_contact'
      post 'contact', to: 'textbooks#send_contact', as: 'send_contact'
    end
  end

rake routes has now:

Prefix Verb   URI Pattern                            Controller#Action
    new_contact_textbook GET    /textbooks/:id/contact(.:format)       textbooks#new_contact
   send_contact_textbook POST   /textbooks/:id/contact(.:format)       textbooks#send_contact
               textbooks GET    /textbooks(.:format)                   textbooks#index
                         POST   /textbooks(.:format)                   textbooks#create
            new_textbook GET    /textbooks/new(.:format)               textbooks#new
           edit_textbook GET    /textbooks/:id/edit(.:format)          textbooks#edit
                textbook GET    /textbooks/:id(.:format)               textbooks#show
                         PATCH  /textbooks/:id(.:format)               textbooks#update
                         PUT    /textbooks/:id(.:format)               textbooks#update
                         DELETE /textbooks/:id(.:format)               textbooks#destroy

The error I get is this:

NoMethodError in Textbooks#new_contact

undefined method `id' for nil:NilClass
Extracted source (around line #4):
<div>
    Texbook id is: <%= @textbook.id %>
</div>

I am running heroku local the error shows:

10:56:13 PM web.1 |    Rendered textbooks/new_contact.html.erb within layouts/application (2.0ms)
10:56:13 PM web.1 |  Completed 500 Internal Server Error in 7ms (ActiveRecord: 0.1ms)
10:56:13 PM web.1 |  ActionView::Template::Error (undefined method `id' for nil:NilClass):
10:56:13 PM web.1 |      1: <h1> contact seller! - working? </h1>
10:56:13 PM web.1 |      2:
10:56:13 PM web.1 |      3: <div>
10:56:13 PM web.1 |      4:     Texbook id is: <%= @textbook.id %>
10:56:13 PM web.1 |      5: </div>
解决方案

Basically what you need to do is to write your mailers and controllers in such a way that all the information you want is passed to the mailer. So if you want an instance of your Textbook model to be passed to the mailer, you will need to do so from the controller in which you send your email. You might event want to nest your contact controller routes within your textbook routes to help you. Alternatively, rather than having an entire controller for Contact, just have a contact action within your textbook controller.

# route.rb
...
resources :textbooks do
  member do
    get "contact", to: "textbooks#new_contact", as: "new_contact"
    post "contact", to: "textbooks#send_contact", as: "send_contact"
  end
end

That will give you routes like /textbook/24/contact. member do means that the routes are for individual instances of your model rather than the whole collection, so you will need to specify which textbook you are referring to when calling their helpers: new_contact_textbook_path(@textbook.id).

So in your Textbook controller, you would do this:

# textbooks_controller.rb
before_action :set_textbook, only: [:show, :edit, :update, :destroy, :new_contact, :send_contact]
...
def new_contact
  # We are NOT doing Contact.new here
  # Only put logic here that you need to display the form
end

def send_contact
  message = params[:message]
  if Contact.send_contact(@textbook, current_user, message).deliver
    flash[:success] = "Email sent."
    redirect_to @textbook
  else
    flash[:alert] = "There was a problem sending the email."
    render :new_contact
  end
end

Then put your new_contact.html.erb file in with your other Textbook views.

<h1> Contact to the Seller </h1>

<div>
    <%= form_tag send_contact_textbook_path(@textbook.id) do %>
        <h3>Send email for: <%[email protected]%> </h3>

        <%= label_tag :message, "Type your message:" %><br>
        <%= text_area_tag :message %><br>  

        <%= submit_tag 'Send message', class: 'button' %>
    <%end%>
</div>

Notice that I'm using form_tag instead of form_for because we don't have a Contact object to pass it. (That is, Contact isn't a model. It's a mailer.)

Your mailer would then look something like this:

class Contact < ApplicationMailer

  def send_contact(textbook, current_user, message)
    @textbook = textbook
    @current_user = current_user
    @message = message
    mail(
      from: "#{@current_user.name} <#{@current_user.email}>",
      to: @textbook.user.email,
      subject: "I would like to buy #{@textbook.title}",
      reply_to: @current_user.email,
    )
  end
end

And finally, put the template/view for you mailer in /app/views/contact/send_contact.html.erb:

<!DOCTYPE html>
<html>
  <head>
    <meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
  </head>
  <body>
    <h1><%= @current_user.name %> is wondering about <%= @textbook.title %>:</h1>
    <p><%= @message %></p>
  </body>
</html>

And that should do it! Although you may have to adjust some things to suit your needs. Also see these links for more examples:

Contact Form Mailer in Rails 4

https://sendgrid.com/docs/Integrate/Frameworks/rubyonrails.html

这篇关于当我使用Sendgrid Rails Heroku发送电子邮件时,如何抓住或访问不同的模型属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-22 10:13