Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undefined method render in Rails controller - Trying to respond to Sendgrid with a 200 status code

I'm using the Sendgrid Parse API along with the Griddler gem to accept incoming emails. For the most part, this works fine; however, if you don't respond to Sendgrid with a status code 200, they will assume that the app didn't correctly receive the POST request and keep trying to make a POST for 3 days. I'm trying to respond with a status code and am having issues.

In regular RESTful routes, you can do something like...

render :status => 200

However, this must be done in a controller to recognize the render method, I believe. Griddler suggests that you create an EmailProcessor model and use a 'process' method to deal with the email.

From what I understand, you can't use the render method in models. So, I created an EmailProcessorsController class with a class method as seen below.

class EmailProcessor < ActiveRecord::Base

  include ApplicationHelper

  def initialize(email)
    @email = email
    @to = email.to # this is an array
    @from = email.from
  end

  def process
    # do other stuff
    EmailProcessorsController.render_ok
  end
end 

class EmailProcessorsController < ActionController::Base

  def self.render_ok
    render :status => 200
  end
end

Below is the error I get from my app. It doesn't like the render method :(

NoMethodError (undefined method `render' for EmailProcessorsController:Class):
  app/controllers/email_processors_controller.rb:6:in `render_ok'
  app/models/email_processor.rb:16:in `process'

I'm a newer dev and this probably something uber simple, but I'm stuck. Any thoughts and comments on the problem as well as design are greatly appreciated. Thanks!

UPDATE!

Per the suggestion of @meagar I moved the render call to the controller as seen below, but now I get a different error, and I'm not sure what to make of it.

class EmailProcessorsController < ApplicationController

  def initialize(email)
    @email = email
    @to = email.to # this is an array
    @from = email.from
  end

  def process
    # do other stuff
    render :status => 200
  end
end 

Without the render call, I don't get an error. Here's the error I get when calling render...

Module::DelegationError (ActionController::RackDelegation#status= delegated to @_response.status=, but @_response is nil: #<EmailProcessorsController:0x000001063b1558 @email=#<Griddler::Email:0x00000106378ac8 @params={"headers"=>"Received: by mx-007.sjc1.send
like image 221
Brantley Beaird Avatar asked Oct 02 '14 01:10

Brantley Beaird


1 Answers

render is an instance method, not a class method. You need to instantiate an instance of your controller, but that won't work regardless.

It's a serious error to try to render from your model. The model has no idea there is an HTTP request involved. Your controller should be creating your model, invoking whatever action on it, waiting for success, and then your controller should be rendering a response. What you're trying to do is fundamentally broken.

like image 112
meagar Avatar answered Dec 05 '22 09:12

meagar