Reputation: 4052
I just figured out how to display a country name from a country id number on model User. Here is the basic code I am using in a controller and two views to display the name after finding User by its id:
@country_name = Country.find(@user.country_id).name
I am using Factory Girl to simulate user records where the default for country_id is 1 for the United States. Before I added this logic my Rspec2 tests were clean. Now I get the following error when I run my tests. Every test which has similar logic in the view or controller produces the error.
ActiveRecord::RecordNotFound:
Couldn't find Country with id=1
Here are two of the Rspec2 tests I am doing:
describe "profile page" do
let(:user) { FactoryGirl.create(:user) }
before { visit user_path(user) }
it { should have_selector('span', text: user.first_name+' '+user.last_name) }
it { should have_selector('title', text: user.first_name+' '+user.last_name) }
end
The profile page references @country_name which is set as stated above. The country name displays on the screen as expected.
I'm thinking that I need to add something to the Rspec2 tests somehow. I was not sure where to do this. Since @country_name is an instance variable not related to User I felt that maybe I needed to do something directly in my Rspec2 file.
Any help would be appreciated. I have not found anything like this so far but I will continue looking.
Update 6/8/2012 7:27 pm CDT
Here is my user controller logic. Adding the second line here produced the RSpec2 errors. I changed nothing in the RSpec2 tests. @country_name is referenced in show.html.erb.
def show
@user = User.find(params[:id])
@country_name = Country.find(@user.country_id).name
end
I decided to try this but got the same error:
describe "profile page" do
let(:user) { FactoryGirl.create(:user) }
let(:country) { FactoryGirl.create(:country) }
before { visit user_path(user) }
it { should have_selector('span', text: user.first_name+' '+user.last_name) }
it { should have_selector('title', text: user.first_name+' '+user.last_name) }
end
I added the following to factories.rb separate from the user factory.
factory :country do
id 1
name "CountryName"
iso "CN"
end
Again my application logic for the country name is working wonderfully.
Update 6/11/2012 9:09 am CDT
Here is my factories.db file. country_id has a default value of 1 in User. I tried this with country_id defined as below and without a declaration for country_id. I also had the country factory without the id. I still got the errors as described. I tried this before submitting my question here.
FactoryGirl.define do
factory :user do
sequence(:first_name) { |n| "First Name #{n}" }
sequence(:last_name) { |n| "Last Name #{n}" }
sequence(:username) { |n| "Username#{n}" }
sequence(:email) { |n| "person_#{n}@example.com" }
password "foobar"
password_confirmation "foobar"
sequence(:city) { |n| "City #{n}" }
sequence(:state_province) { |n| "State/Province #{n}" }
active_user "1"
country_id 1
factory :admin do
admin true
active_user "3"
end
factory :blocked do
active_user "1"
end
factory :rejected do
active_user "2"
end
factory :not_visible do
active_user "3"
visible false
end
factory :visible do
active_user "3"
visible true
end
end
factory :country do
id 1
name "CountryName"
iso "CN"
end
end
Update 6/11/2012 5:37 pm CDT
After several hours of continuing to search AND COMPLETELY REBOOTING MY COMPUTER (sigh) I was finally able to get the tests to work. I replaced country with user.association :country in the user factory. I put my original two statements after the describe "profile page" do statement back. With the suggested changes I now have no errors. I guess the association will create corresponding rows in Country.
Thanks so much for all the help. It was a combination of the help received with one modification that solved this one.
On to figuring out how to check for changed values.......
Update 6/12/2012 10:55 am
It looks like with all the correcting of code I am able to use @user.country.name with no errors. I will change my code to use this streamline coding.
Upvotes: 0
Views: 170
Reputation: 6034
Let is more for setting up variables for use in the test, if you're using database cleaner or something similar, these are probably getting destroyed in the database on each test run. You should be setting up your factories in the before block:
Edit: I've just realised this is probably because you're trying to match records by explicitly entering ids. This won't work (ids are automatically set by the database), but Factory Girl should deal with your associations, see what happens when you set up the before block like this:
before(:each) do
country = FactoryGirl.create(:country)
user = FactoryGirl.create(:user, country: country)
visit user_path(user)
end
I would also remove the
id 1
line from your country factory, and the line setting up the country_id to 1 on the user factory.
Edit 2: You need to tell Factory Girl about your associations, don't try to set them up by explicitely setting the id field because that won't work.
Remove
country_id 1
from the user factory
id 1
from the country factory, and add this line to the user factory:
country
(yes, just country on it's own - Factory Girl is clever enough to figure out what's going on from that as long as the factory and association is named the same)
By the way, you could change this:
@country_name = Country.find(@user.country_id).name
to
@country_name = @user.country.name
It won't help here, but it's cleaner.
Upvotes: 2