RavingHermit
RavingHermit

Reputation: 31

How to avoid undefined method `id' for ActiveRecord_Relation?

Hopefully this is not a duplicate question, as I have spent weeks scouring StackOverflow for answers and have not found a solution to my problem.

I have a Ruby on Rails API (Ruby 1.9.3, Rails 4.0.0) and am using ActiveRecord to interact with our database. When a request is made to retrieve the currently scheduled banner, it works perfectly. When no banner is scheduled, however, a 500 response is experienced:

undefined method `id' for #\u003cBanner::ActiveRecord_Relation:0x0000000628fba8\u003

My understanding is that this is because an inherent "id" method is being attempted upon a "nil" which is the result from the database lookup when no qualifying record is found. How do I gracefully handle this scenario so that a 500 error is not encountered and so that I may return a more polite response to the requester?

Here is my controller:

class BannersController < ApplicationController
  load_and_authorize_resource

  respond_to :json

  # Look to see if any banners should be showing right now
  def current
    @banner = Banner.current
  end
end

Here is my model:

class Banner < ActiveRecord::Base
  self.table_name   = 'Banner'
  self.primary_key  = :BannerID

  alias_attribute :name,              :FriendlyName
  alias_attribute :banner_html,       :BannerHtml
  alias_attribute :banner_image,      :BannerImage
  alias_attribute :start_date,        :StartDate
  alias_attribute :end_date,          :EndDate
  alias_attribute :is_active,         :IsActive
  alias_attribute :is_removed,        :IsRemoved
  alias_attribute :start_date_time,   :StartDateTime
  alias_attribute :end_date_time,     :EndDateTime
  alias_attribute :hidden_text,       :HiddenText
  alias_attribute :hidden_background_color,       :HiddenBackgroundColor

  # This returns nil if no banner is scheduled, which then causes the view to return a 500 response because it tries to invoke an "id" method
  scope :current, -> { Banner.where("StartDateTime <= ? AND EndDateTime >= ? AND IsActive=1 AND IsRemoved=0 AND BannerType=1", Time.now.to_s(:db), Time.now.to_s(:db)).first }  
end

Note: I have tried using .find_by and also tried not using .first, but still cannot seem to find a resolution to this.

Here is my view:

json.extract! @banner, :id, :banner_html, :banner_image, :hidden_text, :hidden_background_color

json.request_id request.uuid

The database table "Banner" has a primary key of "BannerID".

Thanks to all who would take the time to look into this. I have spent untold hours reading and trying everything in order to remedy the situation, to no avail.

Upvotes: 3

Views: 367

Answers (2)

m3characters
m3characters

Reputation: 2290

Why don't you just

if [email protected]?
  json.extract...
  ...
else
  json.null!
  (or whatever you want?)
end

Upvotes: 0

Pavan
Pavan

Reputation: 33542

undefined method `id' for \u003cBanner::ActiveRecord_Relation:0x0000000628fba8\u003

The database table "Banner" has a primary key of "BannerID"

Then whey are using :id still!. Change

json.extract! @banner, :id, :banner_html, :banner_image, :hidden_text, :hidden_background_color

to

json.extract! @banner, :BannerID, :banner_html, :banner_image, :hidden_text, :hidden_background_color

Small Note:

By convention, the attributes should be in snake_case.

Upvotes: 1

Related Questions