Search code examples
ruby-on-railspaper-trail-gem

Paper trail display has many objects


I'm using the paper trail gem to track version changes on order web application. I'm having trouble displaying the has_many versions

Order model:

class Order < ActiveRecord::Base
  has_paper_trail
  has_many :line_items, dependent: :destroy, inverse_of: :order, order: "position", autosave: true
end

line item model:

class LineItem < ActiveRecord::Base
  belongs_to :order, inverse_of: :line_items
  has_paper_trail
end

Order Controller:

@order = Order.find(params[:id])
@versions = PaperTrail::Version.where(item_id: params[:id]).order('created_at ASC')
@line_items = LineItem.find_all_by_order_id(params[:id])
@line_item_versions = @line_items.versions

history html:

<% @line_item_versions.each_with_index do |version, index| %>
  <b>Version: </b><%= index + 1 %><br/>
  Event ID: <%= version.id %><br/>
  <b>Target:</b> <%= version.item_type %>
  <small>(id: <%= version.item_id %>)</small>; <b>action</b> <%= version.event %>;<br/>
<% end %>

The problem is the .versions works when a single object (from .find) is found. However, when an array of objects (from the .find_all_by) is passed to the .versions it returns this error

undefined method `versions' for #<Array:0x007f859d37eb30>

Solution

  • You are defining:

    @line_items = LineItem.find_all_by_order_id(params[:id])
    

    Which means @line_items is an Array of several LineItem records. Then, you call:

    @line_item_versions = @line_items.versions
    

    But the .versions method is an instance method of LineItem (one line_item has_many versions). This causes the error undefined method 'versions' for Array (@line_items is an array here).


    To solve this problem, I think you should do the following (but there is many options, depending on what you want to do):

    <% @line_items.each do |line_item| %>
      <%= line_item.name %>
    
      <% line_item.versions.each_with_index do |version, index| %>
        <b>Version: </b><%= index + 1 %><br/>
        Event ID: <%= version.id %><br/>
        <b>Target:</b> <%= version.item_type %>
        <small>(id: <%= version.item_id %>)</small>; <b>action</b> <%= version.event %>;<br/>
      <% end %>
    <% end %>