0

I'm trying to create a friending system for my app.

I am using active_relationships, passive_relationships, state_machine and the concept of followers,followed, following and followers.

I have gotten myself in a bit of a knot comprehending how they all fit together. Looking for help finding clarity to how I use what I've created to access friend id's to view friend profile pages, email friends etc.

To highlight the kinds of things I'm struggling to comprehend: At the moment I'm faced with:

test_should_send_request_email#RelationshipTest
 NoMethodError: undefined method `email'
            app/mailers/user_mailer.`rb:38:in `relationship_requested'
            app/models/relationship.rb:11:in `send_request_email'
            test/models/relationship_test.rb:33:in `block (2 levels) in <class:RelationshipTest>'
            test/models/relationship_test.rb:32:in `block in <class:RelationshipTest>'

I would have thought @followed.email would be a valid method and cant work out why it's considered undefined. i (user/follower) want to email another user (followed) to send them a relationship request. why can I send the email to @followed.email?

model/user.rb:

class User < ActiveRecord::Base
  has_one :profile, dependent: :destroy
  has_many :active_relationships,   class_name:  "Relationship",
                                    foreign_key: "follower_id",
                                    dependent:   :destroy
  has_many :passive_relationships,  class_name:  "Relationship",
                                    foreign_key: "followed_id",
                                    dependent:   :destroy                                
  has_many :following, through: :active_relationships,  source: :followed  
  has_many :followers, through: :passive_relationships, source: :follower   

model/relationship.rb:

class Relationship < ActiveRecord::Base
  belongs_to :follower, class_name: "User"
  belongs_to :followed, class_name: "User"
  validates :follower_id, presence: true
  validates :followed_id, presence: true

  state_machine :state, initial: :pending do
  end

  def send_request_email
    UserMailer.relationship_requested(id).deliver
  end
end

user_mailer.rb:

def relationship_requested(relationship_id)
    relationship = Relationship.find(relationship_id)

    @user = relationship.follower
    @followed = relationship.followed

    mail to: @followed.email,
          subject: "#{@user.name} wants to friend you"
  end
end

relationship_requested.html.erb:

Hi <%= @followed.name %>, 

<%= @user.name %> wants to friend you.

db tables:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name
      t.string :email

      t.timestamps
    end
  end
end

class CreateRelationships < ActiveRecord::Migration
  def change
    create_table :relationships do |t|
      t.integer :follower_id
      t.integer :followed_id

      t.timestamps
    end
    add_index :relationships, :follower_id
    add_index :relationships, :followed_id
    add_index :relationships, [:follower_id, :followed_id], unique: true
  end
end

class AddStateToRelationships < ActiveRecord::Migration
  def change
    add_column :relationships, :state, :string
    add_index :relationships, :state
  end
end

relationship_test.rb:

require 'test_helper'

class RelationshipTest < ActiveSupport::TestCase
  # test "the truth" do
  #   assert true
  # end

  def setup
    @relationship = Relationship.new(follower_id: 1, followed_id: 2)
  end

  test "should be valid" do
    assert @relationship.valid?
  end

  test "should require a follower_id" do
    @relationship.follower_id = nil
    assert_not @relationship.valid?
  end

  test "should require a followed_id" do
    @relationship.followed_id = nil
    assert_not @relationship.valid?
  end

  test "should state pending until other user can accept or reject request" do
    assert_equal 'pending', @relationship.state
  end

  test "should send request email" do
    @relationship = Relationship.create(follower_id: 1, followed_id: 2)
    assert_difference 'ActionMailer::Base.deliveries.size', 1 do
      @relationship.send_request_email
    end
  end
end
sss333
  • 105
  • 2
  • 13
  • seems `NoMethodError: undefined method email'` needs some other part `for ...` – sites Oct 28 '14 at 00:40
  • try `p @followed.class; p @followed.email` after `@followed = relationship.followed`, you can see this output in test log `tail -f log/test.log` or right there in test output. – sites Oct 28 '14 at 00:43
  • Hi @juanpastas! Can you please explain what you mean a little more? I am not familiar with the assumption behind what you've written (I'm fairly new to ROR sorry!). what is 'p'? how does the output help? – sss333 Oct 28 '14 at 01:33

1 Answers1

0

Your test is creating a Relationship record and passing in two ids for follower and following. But do those ids actually correspond to User records? It doesn't look like it, as your test creates no users (do you have fixtures for those two uses?)

So the follower and following associations are nil, even though the relationship is 'valid' (your validations check for the presence of the foreign keys, but not for actual instances of users).

Put some debug information into your test ("puts" to the console or use Pry to pause the execution of the test and interrogated variables).

I'd also recommend looking at using FactoryGirl and Faker gems for generating test data.

Pavling
  • 3,933
  • 1
  • 22
  • 25