I've added a ControllerMacro but the method isn't being made available in my specs. My specs will fail with:
NoMethodError: undefined method `attributes_with_foreign_keys' for FactoryGirl:Module
I'm trying to do this following this discussion on Github. I've looked at other similar questions but most point at using config.include ControllerMacros, :type => :controller instead of config.extend ControllerMacros, :type => :controller which I'm doing already.
Now I know that the controller_macros.rb file is being loaded upon starting the test as I've run the specs through RubyMine's debugger but why the method isn't available is beyond me!
spec_helper.rb
require 'simplecov'
SimpleCov.start 'rails'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'email_spec'
require 'rspec/autorun'
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
config.include(EmailSpec::Helpers)
config.include(EmailSpec::Matchers)
config.include ControllerMacros, :type => :controller
config.include FactoryGirl::Syntax::Methods
config.use_transactional_fixtures = true
config.infer_base_class_for_anonymous_controllers = false
config.order = "random"
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
spec/support/macros/controller_macros.rb
module ControllerMacros
def attributes_with_foreign_keys(*args)
FactoryGirl.build(*args).attributes.delete_if do |k, v|
["id", "type", "created_at", "updated_at"].member?(k)
end
end
end
This example controller spec:
describe "POST create" do
describe "with valid params" do
it "creates a new Course" do
expect {
#post :create, course: FactoryGirl.build(:course)
post :create, course: FactoryGirl.attributes_with_foreign_keys(:course)
}.to change(Course, :count).by(1)
end
The macro you defined is a method within a module. You asked Rspec to include the module, so the method is available to Rspec's instance, which should be used similar to describe, it etc.
However, you used this method as a FactoryGirl's class method. Obviously this is not working.
It looks you want to have a convenient method to quickly build a set of pre-defined attributes of a model in a special case.
This logic is better not to be a "macro", because it's better to use FactoryGirl as a centralized place to store all logic about models.
So, the most convenient way is, beyond your normal factories, define a special factory for this case, say foo, with all association and other logic you need inside it, and inherit from other normal factory.
If it's name is foo, then you can easily build a hash of foo's attributes like FactoryGirl.attributes_for :foo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With