2

I'm using Rails 4.1.7, Rspec 3.0.4 with FactoryGirl and a postgresql ActiveRecord db.

I'm trying to test a method that finds an associated model and then updates a column in that model. The test is crude at this point, but it is making all the associations necessary (I checked in pry). When calling the method the expectation continues to return nil (as the column is nil by default but should update to a date time). Below is the code:

post_picture_spec.rb

require 'rails_helper'

RSpec.describe ModelName::PostPicture, :type => :model do

  describe 'update_campaign method' do

    context 'when the picture is tied to a campaign' do

      before do
        @campaign = FactoryGirl.create(:campaign)
        @campaign.media << @picture1 = FactoryGirl.create(:picture, posted: true, time_scheduled: Date.parse('2014-07-15 18:00:00'), time_posted: Date.parse('2014-07-15 18:00:00'))
        @campaign.media << @picture2 = FactoryGirl.create(:picture, posted: true, time_scheduled: Date.parse('2014-08-20 19:00:00'), time_posted: Date.parse('2014-08-20 19:00:00'))
      end

      it 'should update first item in campaign' do
        # pending("FactoryGirl update issue")
        ModelName::PostPicture.send(:update_campaign, @picture)
        expect(@campaign.time_started).to eq(@picture.time_posted)
      end

  end

end

pictures factory

FactoryGirl.define do
  factory :picture do
    time_approved { Date.parse('2014-08-22 17:00:00') }
    time_posted { Date.parse('2014-08-22 17:00:00') }
    time_scheduled { Date.parse('2014-08-22 17:00:00') }
    processed true
  end
end

post_picture.rb

class ModelName::PostPicture

  def self.call(id)
    [collapsed]
  end

private

      def self.update_campaign(picture)
        campaign = picture.campaign
        campaign_pictures = campaign.pictures.sort_by(&:time_scheduled)
            campaign.update(time_started: picture.time_posted) if campaign_pictures.first == picture
            campaign.update(time_completed: picture.time_posted) if campaign_pictures.last == picture
      end
end

Error:

 Failure/Error: expect(@campaign.time_started).to eq(@picture1.time_posted)

   expected: 2014-07-15 00:00:00.000000000 +0000
        got: nil

   (compared using ==)
user3390658
  • 277
  • 1
  • 3
  • 15
  • I'm confused by `update_campaign`. Why is this a class method? Also, why use `send` instead of simply calling the method directly? – zetetic Nov 14 '14 at 23:09
  • ^ send is used because it is a private method. – user3390658 Nov 14 '14 at 23:45
  • Are you sure about that? Class methods must use `private_class_method` to become private. It sure looks like this should be an instance method, if `campaign_pictures` is an association. Perhaps you could add more of the relevant code? – zetetic Nov 15 '14 at 00:00
  • It's a class method underneath a 'private'. I'll try to post some more up soon, ty – user3390658 Nov 15 '14 at 01:33

2 Answers2

8

Your @campaign variable was already loaded before the modifications were made, so you need to reload it before checking for the new value.

it 'should update first item in campaign' do
  ModelName::PostPicture.send(:update_campaign, @picture)
  @campaign.reload
  expect(@campaign.time_started).to eq(@picture.time_posted)
end
seanlinsley
  • 3,165
  • 2
  • 25
  • 26
2

What I would recommend, is added the association for your pictures in your campaign factory_girl. I think the problem is that you are not actually creating the associations when you are using << on the active record objects.

I would try including the pry gem, and binding.pry in the update_campaign method to see if the models are being created properly.

As an aside, I would also use let syntax instead of doing everything in the before do, just reusability.

Patrick Vice
  • 56
  • 1
  • 4
  • I put the binding.pry on line 4 of the update_campaign method pry> campaign_pictures => #[, #] pry> campaign.time_started => nil pry> campaign # pry> campaign.media => [, ] – user3390658 Nov 14 '14 at 23:44
  • ^ Apologies that didn't come out nice and indented as I typed it :\ – user3390658 Nov 14 '14 at 23:45
  • The picture you passed in doesn't look like it has time_started attribute. Also `private` in ruby doesn't work on class method the way you think it does. [Here is a good explanation/example](http://stackoverflow.com/questions/4952980/creating-private-class-method) – Patrick Vice Nov 15 '14 at 05:04