Неопределенный метод существует? для Draper::CollectionDecorator

Я пытаюсь реализовать драгоценный камень Draper для своего проекта Rails, и у меня возникают проблемы с его работой. Я получаю сообщение об ошибке:

неопределенный метод `существует?' для #Draper::CollectionDecorator:0x000055b625da7a10>

Ошибка, кажется, возникает из-за частичного отображения, которое я отображаю в своем индексном представлении. Партиал вызывает "@accounts.exists?" где ошибка происходит. Если я удаляю вызов частичного, мой декоратор работает нормально. У меня есть ощущение, что мне нужно использовать команду делегата для этого, но я не уверен. Я довольно новичок в Rails и только начинаю изучать некоторые полезные драгоценные камни. Я надеюсь, что кто-то может взглянуть на мой код и указать мне правильное направление, чтобы обойти эту ошибку. Спасибо! :)


Модель: 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

Контроллер: account_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

Декоратор: 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

Просмотр: account/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>

Частичный просмотр: account/_noaccounts.html.erb

<% if [email protected]? 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 %>

person Kevin Custer    schedule 12.10.2018    source источник


Ответы (1)


Я не знаком с драгоценным камнем draper, но вы пытаетесь вызвать exists? для того, что выглядит как набор объектов, а не для объекта ActiveRecord. А поскольку exists? определено в ActiveRecord, вы не сможете сделать это.

Вероятно, вы можете безопасно изменить эту строку:

<% if [email protected]? then %>

to:

<% if @accounts.empty? then %>

Метод .empty? определен в несколько мест, но суть в том, что если такой объект, как коллекция, пуст, то он вернет true.

person anothermh    schedule 12.10.2018
comment
Вау, я изменил свой код, и теперь он отлично работает. Я был в тупике на этом в течение нескольких часов, так что теперь у меня есть дополнительный вопрос. До того, как я попытался использовать Draper, этот фрагмент кода (! @accounts.exists?) работал нормально и вел себя так, как я ожидал. Есть идеи, почему? В любом случае большое спасибо за ответ! - person Kevin Custer; 12.10.2018
comment
Если @accounts был объектом ActiveRecord::Relation (тип объекта, возвращаемый чем-то вроде Account.where(foo: 'bar')), то он будет иметь метод exists?, потому что это объект, созданный ActiveRecord. Когда вы вызываете decorate, он возвращает объект Draper::CollectionDecorator, который не создается ActiveRecord, поэтому у него нет метода. - person anothermh; 12.10.2018
comment
В качестве подсказки по отладке вы можете вызвать object.methods (например, @accounts.methods) в консоли, чтобы получить список методов, доступных для этого объекта. Чтобы пропустить список всех стандартных методов Ruby, которые применяются ко всем объектам, вы можете вызвать @accounts.methods - Object.methods, и он предоставит более краткий список методов. В вашем случае вы увидите, что @accounts не имеет метода .exists?, но Account.all.methods - Object.methods будет включать exists?(*conditions) Account::ActiveRecord_Relation (ActiveRecord::FinderMethods), говоря вам, что метод существует И где его найти. - person anothermh; 12.10.2018