I am so confused as to why this is happening...
I'm using factory girl, and this factory:
# spec/factories/partners/contact.rb
FactoryGirl.define do
factory :partner_contact, class: Partners::Contact do
first_name "Josh"
last_name { Faker::Name.last_name }
email { Faker::Internet.email }
partner
end
end
But when I run my rspec it says
Mysql2::Error: Field 'first_name' doesn't have a default value: INSERT INTO `partner_contact` (`created_on`) VALUES ('2014-01-30 22:21:53')
Here is the spec that I'm using that generates the above error.
# spec/models/contact.rb
require 'spec_helper'
require 'pp'
describe Partners::Contact do
it "has a valid factory" do
partner = FactoryGirl.create(:partner_contact)
# partner.should be_valid
puts "MEOW MEOW"
end
it "is invalid without a firstname" do
# FactoryGirl.build(:partner_contact, first_name: nil).should_not be_valid
end
it "is invalid without a lastname" do
# FactoryGirl.build(:partner_contact, last_name: nil).should_not be_valid
end
it "is invalid without an email address" do
# FactoryGirl.build(:partner_contact, email: nil).should_not be_valid
end
#it "returns a contact's fullname as a string"
end
As you can see, it's not trying to commit any data that I listed, first_name, last_name or email. Just 'created_on' which is generated via rails.
What's going on here?
Do you have any fixtures for that table? If fixtures are present and enabled, Rails will attempt to load them into your database before your test is evaluated. Look in spec/fixtures.
Your setup seems wrong. Check the FactoryGirl Rails gem. Don't forget to configure RSpec to use FactoryGirl as well.
Related
I am using active record with ruby (but not rails). I am using sqlite3 which has a test.db on file (not just in-memory). When I run the following code snippet using user.create, it complains about argument error (and when I use use.save, it throws an active record exception. Any idea what I might be doing wrong? Thanks
require 'rubygems'
gem 'activerecord'
require 'sqlite3'
require 'active_record'
ActiveRecord::Base.logger = Logger.new(STDERR)
#ActiveRecord::Base.colorize_logging = false
ActiveRecord::Base.establish_connection(
:adapter => 'sqlite3',
:host => "localhost",
:database => 'test.db'
)
class User < ActiveRecord::Base
#attr_accessible :email, :full_name
attr_accessor :email
attr_accessor :full_name
validates :email, presence: true, uniqueness: true
def initialize(email, full_name)
#email = email
#full_name = full_name
end
end
puts "full_name for user:"
full_name = gets.chomp
puts "email address:"
email = gets.chomp
user = User.new(email, full_name)
#user.save
user = User.create!(email: '', full_name: '')
Exception in first case (with User.create!):
main.rb:42:in `initialize': wrong number of arguments (1 for 2) (ArgumentError)
from /var/lib/gems/1.9.1/gems/activerecord-4.2.4/lib/active_record/inheritance.rb:61:in `new'
from /var/lib/gems/1.9.1/gems/activerecord-4.2.4/lib/active_record/inheritance.rb:61:in `new'
from /var/lib/gems/1.9.1/gems/activerecord-4.2.4/lib/active_record/persistence.rb:50:in `create!'
from main.rb:55:in `<main>'
It is complaining about the new method. According to the documentation: (http://api.rubyonrails.org/classes/ActiveRecord/Base.html), you don't need the initialize, because when you inherit from ActiveRecord::Base, you need to initialize your objects with a hash.
user = User.new({email: email, full_name: full_name})
# or
user = User.new(email: email, full_name: full_name)
# then
user.save
You need to drop the initialize and the attr_accessor from your code.
Try to comment User#initialize method and create new user like this:
User.create! email: 'halk#mail.com', full_name: 'Halk'
Explanation
When you declare AR model by heritage from ActiveRecord::Base class you don't need to define your own #initialize method. But you do. When you call User::create! method, you pass only one argument - Hash with two pairs (with email and full_name keys). But User#initialize define two parameters - email and full_name separately. So Ruby exception raise and talk about it:
wrong number of arguments (1 for 2) (ArgumentError)
I have two classes; customer and reservation. And my project is consist of only ruby code, not rails project.
Class reservation reads bulk json file line by line which includes customer hash.
From that hash, I create customer object.
Here's the code within the reservation class.
def parse_json
File.open(#filename, "r" ).each do |line|
#customers << Customer.new(JSON.parse(line))
end
return #customers
end
And in customer.rb I have the following;
validates_presence_of :hash
validate :hash_should_include_all_fields
attr_reader :name, :userid, :latitude, :longitude, :distance
def hash_should_include_all_fields
puts "I'm here #{hash}"
if hash.assert_valid_keys('user_id', 'name', 'latitude', 'longitude')
puts "Valid"
else
puts "Not valid"
end
end
However as I create customer objects, hash_should_include_all_fields method is not called.
What do I miss in here, that would be great if you can help.
Thanks
You're calling new which will build a Customer object but do nothing more.
Calling create! or create will also run validations and write the Object to the database if it's an active_record model.
If you don't want to write it to the databas you can call valid? on the instance created with new
I have a ruby app that I'm using rspec and factorygirl with, and I'm having trouble building a factory. When I run the spec, I get an ArgumentError: missing keywords for the required keywords in initialize. If I pass them in explicitly, the error changes to wrong number of arguments 0 for 2.
Thanks for any help on this.
spec/models/player_spec.rb
require 'spec_helper'
describe Player do
it 'has a valid factory' do
player = build(:player) # or build(:player, name: 'testname', password: 'testpw')
end
end
spec/factories/player.rb
FactoryGirl.define do
factory :player do
name { 'Testname' }
password { 'testpass' }
end
end
models/player.rb
def initialize(name:, password:)
#id = object_id
#name = name
#password = password
end
Change your spec/factories/player.rb with:
FactoryGirl.define do
factory :player do
name 'Testname'
password 'testpass'
initialize_with { new(name:name, password: password) }
end
end
You can find the documentation here although is not explicit to be used in this case.
Did you try to use the syntax that they recommend on the github repo Read Me?
It looks like defining a factory is done with the following syntax:
FactoryGirl.define do
factory :player do
name 'Testname'
password 'testpass'
end
end
They may be equivalent, but this stood out to me as being a potential problem. It seems that blocks are used whenever you are executing logic, not declaring.
I finally got this to work by changing the player#initialize method to accept an options hash instead of keyword arguments params.
I have this in factories.rb:
FactoryGirl.create :user do |user|
user.name "test"
user.age "40"
end
and this in my test file:
require 'spec_helper'
describe "FirstTests" do
it "creates a user" do
user=Factory(:user)
end
end
Like always nothing works. Could somebody explain me why I am getting this?
/usr/local/rvm/gems/ruby-1.9.3-p194/gems/factory_girl-4.1.0/lib/factory_girl/registry.rb:24:in `find': Factory not registered: user (ArgumentError)
Everything is there. why I am getting this error?
You are using create instead of define
FactoryGirl.define do
factory :user do
name "test"
age "40"
end
end
and Factory(:user) instead of FactoryGirl.create(:user), or more simply create(:user)
https://github.com/thoughtbot/factory_girl/wiki/Usage
I'm trying to create a test case for User model. Basically, it will validate first_name and last_name to be present.
What I am trying to do is to check whether the error on a specific field is empty or not and it should be empty. However it always fails.
What is the correct way to do this?
Here is my code
On my user_spec.rb
require 'spec_helper'
describe User do
before do
#user = User.new
end
it "must have a first name" do
#user.errors[:first_name].should_not be_empty
end
it "must have a last name" do
#user.errors[:last_name].should_not be_empty
end
end
On my user.rb file
class User < ActiveRecord::Base
validates :first_name, :presence => true
validates :last_name, :presence => true
end
You can test by simply doing this as well:
describe 'validations' do
it { should validate_presence_of :firstname }
it { should validate_presence_of :lastname }
end
Take a look at the shoulda matchers for all such standard Rails Validation.
This way is not just more concise but also takes care of the positive case. Meaning you then dont need to test the scenario mentioned below:
it "passed validations when first_name is set"
user = User.create(:firstname => 'f', :lastname => 'l')
user.errors[:first_name].should be_empty
user.errors[:last_name].should be_empty
end
RSpec supports the notion of an "implicit" subject. If your first argument to the "describe" block is a class, RSpec automatically makes an instance of that class available to your specs. See http://relishapp.com/rspec/rspec-core/v/2-6/dir/subject/implicit-subject.
require 'spec_helper'
describe User do
it "must have a first name" do
subject.should have(1).error_on(:first_name)
end
it "must have a last name" do
subject.should have(1).error_on(:last_name)
end
end
which results in RSpec output (if using --format documentation) of:
User
must have a first name
must have a last name
You can abbreviate it even further if you are content with the RSpec output defaults:
require 'spec_helper'
describe User do
it { should have(1).error_on(:first_name) }
it { should have(1).error_on(:last_name) }
end
which results in:
User
should have 1 error on :first_name
should have 1 error on :last_name