Create controller tests for Mongoid embedded models
I'm working on a Rails 3 app that allows users to follow movies by adding them to their queue, so that they're notified when the movies are premiering.
Since I'm using Mongoid, I've structured it so that when a user adds a movie to their queue, they create an embedded document, adds, and they also increment an add_counter on the Movie model by 1.
I've been able to get my specs to pass confirming that this behavior is working in the model level, but now that I'm building the controller, I can't seem to get a passing response. I've been looking everywhere for a solution and even after sleeping on it and coming back to it I haven't been able to figure out what I'm doing wrong.
Here is my controller spec:
# spec/controllers/adds_controller_spec.rb require 'spec_helper' describe AddsController do before(:each) do @user = Factory(:user) @movie = Factory(:movie) end describe '#create' do context 'given valid params' do before(:each) do sign_in @user end it "creates a new add" do add_count @user.adds.count post :create, :movie_id => @movie.id @user.adds.count.should == add_count + 1 end end end end
Here's my controller:
# controllers/adds_controller.rb class AddsController < ApplicationController before_filter :authenticate_user! def create @movie = Movie.find(params[:movie_id]) @user = current_user @user.add_to_queue!(@movie) respond_to do |format| format.js end end end
And here are my models:
# models/movie.rb class Movie include Mongoid::Document include Mongoid::Timestamps include Mongoid::MultiParameterAttributes field :add_counter, :type => Integer, :default => 0 # models/user.rb class User include Mongoid::Document include Mongoid::Timestamps include Mongoid::MultiParameterAttributes embeds_many :adds def add_to_queue!(movie) if already_added?(movie) == false adds.create!(:movie_id => movie.id) movie.add_counter += 1 end end def already_added?(movie) adds.where(:movie_id => movie.id).exists? end # models/add.rb class Add include Mongoid::Document include Mongoid::Timestamps include Mongoid::MultiParameterAttributes field :movie_id, :type => String key :movie_id embedded_in :user
Finally, here's the feedback from Rspec when I run the controller test:
Failures: 1) AddsController#create given valid params creates a new add Failure/Error: @user.adds.count.should == 1 expected: 1 got: 0 (using ==) # ./spec/controllers/adds_controller_spec.rb:25:in `block (4 levels) in <top (required)>'
This code is overly complex. I would get rid of the Add class. The concept of adding should not be modeled by a object but by a relation.
Make two classes (simplified):
class Movie include Mongoid::Document has_and_belongs_to_many :user_queues, :class_name => "User", :inverse_of => :movie_queue end
class User include Mongoid::Document has_and_belongs_to_many :movie_queue, :class_name => "Movie", :inverse_of => :user_queues end
Syntax may not be exact here but treat them like arrays and you'll be golden.