I have a method:
def fb_matches_for_friend_employer_goals(user, friend)
User.where( :is_reachable_on_fb => true, # Users that are reachable on FB via wall posts
"jobs.employer" => friend.interested_employers, # Users that have worked at the employers the friend is interested
:fb_user_id => user.fb_connections, # Users that are friends of user through FB
:fb_user_id.nin => friend.fb_connections, # Users that are NOT friends with the friend through FB
:fb_user_id.ne => user.fb_user_id, # Users that are NOT the user
:fb_user_id.ne => friend.fb_user_id # Users that are NOT the friend (although it's likely the friend hasn't worked at the goal employer)
).fields(:id, :jobs, :fb_connections).all
end
And a test:
describe "#fb_matches_for_friend_employer_goals method" do
let(:friend) { stub_model(User) }
before(:each) do
User.stub(where: User, fields: User, all: User)
friend.stub(interested_employers: ["Apple"])
friend.stub(fb_connections: ["100", "200"])
friend.stub(fb_user_id: "1")
user.stub(fb_connections: ["101", "201"])
user.stub(fb_user_id: "2")
end
it "returns users that are reachable on FB" do
User.should_receive(:where).with( :is_reachable_on_fb => true,
"jobs.employer" => ["Apple"],
:fb_user_id => ["101", "201"],
:fb_user_id.nin => ["100", "200"],
:fb_user_id.ne => "2",
:fb_user_id.ne => "1")
a.fb_matches_for_friend_employer_goals(user, friend)
end
end
I get the following error:
Failures:
1) Algorithm::Helpers::Facebook#fb_matches_for_friend_employer_goals method returns users that are reachable on FB
Failure/Error: User.should_receive(:where).with( :is_reachable_on_fb => true,
<User (class)> received :where with unexpected arguments
expected: ({:is_reachable_on_fb=>true, "jobs.employer"=>["Apple"], :fb_user_id=>["101", "201"], #<SymbolOperator:0x007f9e28bac958 @field=:fb_user_id, @operator="nin">=>["100", "200"], #<SymbolOperator:0x007f9e28bac778 @field=:fb_user_id, @operator="ne">=>"2", #<SymbolOperator:0x007f9e28bac688 @field=:fb_user_id, @operator="ne">=>"1"})
got: ({:is_reachable_on_fb=>true, "jobs.employer"=>["Apple"], :fb_user_id=>["101", "201"], #<SymbolOperator:0x007f9e28babcd8 @field=:fb_user_id, @operator="nin">=>["100", "200"], #<SymbolOperator:0x007f9e28bab6c0 @field=:fb_user_id, @operator="ne">=>"2", #<SymbolOperator:0x007f9e28bab148 @field=:fb_user_id, @operator="ne">=>"1"})
# ./spec/lib/algorithm/helpers/facebook_spec.rb:44:in `block (3 levels) in <module:Helpers>'
From what I can tell, it's just that the SymbolOperators are different. any thoughts on how to avoid this and confirm the right hash is going into the query?
The problem has to do with the way hash equality is calculated in Ruby.
1.9.2-p0 :001 > :something.nin == :something.nin
=> true
1.9.2-p0 :002 > {:something.nin => 'hi'} == {:something.nin => 'hi'}
=> false
1.9.2-p0 :003 > {:something => 'hi'} == {:something => 'hi'}
=> true
For efficiency, I guess Ruby is comparing the hash-codes rather than doing actual ==
comparisons.
1.9.2-p0 :004 > {:something => 'hi'}.hash
=> 2493047093815769983
1.9.2-p0 :005 > {:something => 'hi'}.hash
=> 2493047093815769983
1.9.2-p0 :006 > {:something.nin => 'hi'}.hash
=> 2609636779135588412
1.9.2-p0 :007 > {:something.nin => 'hi'}.hash
=> -424522258459261487
1.9.2-p0 :008 > :something.hash
=> 3062293424662012631
1.9.2-p0 :009 > :something.hash
=> 3062293424662012631
1.9.2-p0 :010 > :something.nin.hash
=> -1304763062464413657
1.9.2-p0 :011 > :something.nin.hash
=> 2727789822935992035
The most permanent fix for your trouble is to define hash
for symbol operators and submit a pull request to plucky. There's some discussion here on writing a hash
implementation.