I am trying to implement the Draper gem for my Rails project and having trouble getting it to work. I'm getting the error message:
undefined method `exists?' for #Draper::CollectionDecorator:0x000055b625da7a10>
The error seems to be coming up from a partial I'm rendering on my index view. The partial is calling "@accounts.exists?" which is where the error is happening. If I remove the call to the partial my decorator works fine. I have a feeling I need to use a delegate command for this but I'm not sure. I am fairly new to Rails and just starting to explore some of the helpful gems out there. I'm hoping someone could take a look at my code and point me in the right direction to get past this error. Thanks! :)
Model: Account.rb
# An account which will store many transactions and belongs to one user
class Account < ApplicationRecord
belongs_to :user
has_many :transactions, dependent: :destroy
validates :name, presence: true, length: { maximum: 50, minimum: 2 }
validates :starting_balance, presence: true
validates :last_four, length: { maximum: 4 }
# validates_associated :transactions
after_create :create_initial_transaction
def create_initial_transaction
update(current_balance: 0.00)
# rubocop:disable Metrics/LineLength
Transaction.create(trx_type: 'credit', trx_date: Time.current, account_id: id, description: 'Starting Balance', amount: starting_balance)
# rubocop:enable Metrics/LineLength
end
end
Controller: accounts_controller.rb
class AccountsController < ApplicationController
before_action :authenticate_user!
before_action :set_account, only: %i[show edit update destroy activate deactivate]
# GET /accounts
# GET /accounts.json
def index
@accounts = current_user.accounts.where(active: true).order('created_at ASC')
@accounts = @accounts.decorate
end
def inactive
@accounts = current_user.accounts.where(active: false).order('created_at ASC')
end
private
# Use callbacks to share common setup or constraints between actions.
def set_account
@account = current_user.accounts.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def account_params
params.require(:account).permit(:name, :starting_balance, :current_balance, :last_four, :active, :user_id)
end
end
Decorator: account_decorator.rb
class AccountDecorator < Draper::Decorator
decorates_finders
decorates_association :user
delegate_all
def last_four_formatted
last_four.present? ? ' ( ... ' + last_four.to_s + ')' : nil
end
end
View: accounts/index.html.erb
<%= render partial: "shared/pagetitle", locals: { page_model: "account", description: "Accounts" } %>
<!-- Render the message if no accounts exist -->
<%= render partial: "accounts/noaccounts", locals: { description: "It looks like you don't have any accounts added. To add an account, click the add account button at the top of the page :)" } %>
<div class="row" id="accounts">
<%= render partial: "accounts/account", collection: @accounts %>
</div>
View Partial: accounts/_noaccounts.html.erb
<% if !@accounts.exists? then %>
<div class="row">
<div class="col s12 m8 offset-m2">
<div class="card ob-card-gradient ob-account-card">
<div class="card-content ob-text-primary">
<span class="card-title">Welcome to mysite!</span>
<div class="row">
<br />
<div class="col s1"><i class="material-icons valign-wrapper">account_balance</i></div>
<div class="col s11">
<%= description %></div>
</div>
</div>
</div>
</div>
</div>
<% end %>
I am not familiar with the draper gem, but you are attempting to call exists?
on what looks like a collection of objects, not on an ActiveRecord object. And since exists?
is defined in ActiveRecord, you're not going to be able to do that.
You can probably safely change this line:
<% if !@accounts.exists? then %>
to:
<% if @accounts.empty? then %>
The .empty?
method is defined in multiple places, but the gist of it is if an object like a collection is empty then it will return true.