Ruby on Rails未定义方法`session'用于#OrderNotifier

时间:2014-09-07 02:16:20

标签: ruby-on-rails ruby ruby-on-rails-4

我正在开发一个使用Rails 4书的Agile Web Development之后的在线商店网站,而且我是rails的新手。

这是我在侧边栏中呈现为购物车的_line_item.html.erb模板。

<% if line_item == @current_item %>
    <tr id="current_item">
<% else %>
    <tr>
<% end %>
        <td><%= line_item.quantity %>&times;</td>
        <td><%= line_item.product.title %></td>
        <td class="line_item_price" align="right">
            <%= number_to_currency(line_item.total_price) %>
        </td>
        <% if !session[:cart_id].nil? %>
            <td><%= button_to "X", line_item, method: :delete, remote: true, 
                                        :disabled => !@order.nil? %></td>
        <% end %>
    </tr>

因此,当用作侧杆时,它可以完美地运行。但是我也希望使用模板来确认电子邮件,但显然我不希望那些X按钮出现在那里,所以我在button_to帮助器之外添加了一个if条件。我认为它可能有效,因为在我的orders_controller.rb中,

    ......
def create
@order = Order.new(order_params)
@order.add_line_items_from_cart(@cart)

*LINE38* respond_to do |format|
           if @order.save
             Cart.destroy(session[:cart_id])
             session[:cart_id] = nil
    *LINE42* OrderNotifier.received(@order).deliver
     ......

如果创建操作成功,我将会话[:cart_id]设置为nil。如果我不使用_line_item.html.erb作为模板,一切正常,创建订单并发送电子邮件,因为没有按钮问题。但是,如果我这样做,在我从orders_controller.rb触发创建操作后,浏览器会为#OrderNotifier“未定义的方法'会话':0x007ffd207bc800&gt; ”。

所以这是我的问题,如果方法或其他任何未定义,是不是没有?这里的根本问题是什么?如何按照我的预期修复它?

您可以前往http://online-bookstore.herokuapp.com/查看该网站的详细信息,但是FYI电子邮件发送部分未部署在那里,所以当它说“感谢订单”时,它不会发送电子邮件。

这是mailers中的order_notifier.rb /

......
def received(order)
  @order = order

  *LINE23* mail to: order.email, subject: 'Your Order Confirmation'
end
......

错误消息:

Showing /home/jeremy/online-store/app/views/line_items/_line_item.html.erb where line #9 raised:

undefined method 'session' for #<OrderNotifier:0x007ff296453108>
Extracted source (around line #9):

        <td><%= line_item.quantity %>&times;</td>
        <td><%= line_item.product.title %></td>
        <td class="line_item_price" align="right"><%= number_to_currency(line_item.total_price) %></td>
  *LINE9* <% if !session[:cart_id].nil? %>
        <td><%= button_to "X", line_item, method: :delete, remote: true, 
                                            :disabled => !@order.nil? %></td>
        <% end %>

Trace of template inclusion: app/views/order_notifier/received.html.erb

Rails.root: /home/jeremy/online-store

Application Trace | Framework Trace | Full Trace
app/views/line_items/_line_item.html.erb:9:in '_app_views_line_items__line_item_html_erb___1832667105729053783_70339760911020'
app/views/order_notifier/received.html.erb:8:in '_app_views_order_notifier_received_html_erb__517934132095274867_70339761303220'
app/mailers/order_notifier.rb:23:in 'received'
app/controllers/orders_controller.rb:42:in 'block in create'
app/controllers/orders_controller.rb:38:in 'create'

非常感谢您的帮助!!

1 个答案:

答案 0 :(得分:1)

您无法在session课程中使用OrderNotifersession仅在控制器和视图的上下文中可用。但是您可以将session传递给Mailer并将其提供给那里。

# change the line in your controller where you create you Mailer
OrderNotifier.received(@order, session).deliver

# change order_notifier.rb
def received(order, session)
  @order   = order
  @session = session
  ...

# change to line that currently raises the exception to
<% if @session[:cart_id] %>

这使得整个session对象@session在您的邮件程序和邮件程序视图中可用。这不是最佳做法,但应立即解决您的问题。

如果您只需要视图中的card_id,那么将该值传递给您的视图会更好:

# in controller
OrderNotifier.received(@order, session[:card_id]).deliver

# in mailer
def received(order, card_id)
  @order   = order
  @card_id = card_id
  ...

# in mailer view
<% if @cart_id %>