John Dough
John Dough

Reputation: 125

Rails Model/Join table doesn't work properly

I am trying to join two pre-existing tables, "Report" and "Person", via the creation of a new join table "LastViewer". Basically, the Viewer table will track which person last viewed a report.

I created a Rails Model by creating a file "last_viewer.rb" like this:

class LastViewer < ActiveRecord::Base
  belongs_to :report
  belongs_to :person
end

This generated the following migration:

class CreateLastViewers < ActiveRecord::Migration
  def change
    create_table :last_viewers do |t|
      t.references :person
      t.references :report

      t.timestamps
    end
    add_index :last_viewers, :person_id
    add_index :last_viewers, :report_id
  end
end

Now, I started adding code so that my app would track changes. I added the following to the correct controller:

@viewer = LastViewer.new
@viewer.person_id = get_current_user[:id] # correctly gets the person's ID from the correct session
@viewer.report_id = @report.id
@viewer.save

And now, to the view I wanted to display the last viewer, I added:

<% @reports.each_with_index do |report,index| %>
  <% query = LastViewer.where(:report_id => report.id).last %>
  <% name = query.person.name || "No Person found" %>
  <% time = Format.to_time(query.created_at.localtime) %>
<% end %>

The error I get is:

undefined method `name' for nil:NilClass

on the line

  <% name = query.person.name || "No Person found" %

Edit:

The respective part of the Person model:

class Person< ActiveRecord::Base
  attr_accessible :hid, :name, :email, :cell, :display
  has_many :last_viewer
end

The respective part of the Report model:

class Report< ActiveRecord::Base
  has_many :last_viewer
end

Upvotes: 1

Views: 353

Answers (2)

MrYoshiji
MrYoshiji

Reputation: 54882

First, you need to change your relations to this: (plural on has_many :last_viewers)

class Person < ActiveRecord::Base
  has_many :last_viewers


class Report < ActiveRecord::Base
  has_many :last_viewers

class LastViewer < ActiveRecord::Base
  belongs_to :report
  belongs_to :person
  validates :report_id, :person_id, presence: true

Then, try to force the creation of the LastViewer object, to raise an error and see what's wrong with your object:

@viewer = LastViewer.new
@viewer.person_id = get_current_user[:id]
@viewer.report_id = @report.id
@viewer.save! # adding a ! will raise errors if object not valid

# one-line equivalent:
@viewer = LastViewer.create!(person_id: get_current_user[:id], report_id: @report.id)

I'm pretty sure it will an error like "person_id is not supposed to be blank". I think your method get_current_user[:id] does not return the id.

After you fixed this problem, I recommend you to refactor your view to:

<% @reports.each_with_index do |report, index| %>
  <% last_viewer = report.last_viewers.last %>
  <% last_person_name = last_viewer.try(:person).try(:name) %>
  <% time = Format.to_time(query.created_at.localtime) %>
<% end %>

Upvotes: 1

user1454117
user1454117

Reputation:

query.person is nil. You can use try to prevent the error:

<% name = query.person.try(:name) || "No Person found" %>

Upvotes: 2

Related Questions