Problem with non activerecord associations in factory girl - ruby-on-rails

I just started to use factory girl to replace fixtures when I am testing. I am working on a twitter client and I am trying to use factory girl to create the twitter objects for testing. When I create them individually it is fine. But, if I try to associate them I get the error below.
Factory.define :status, :class => Twitter::Status, :default_strategy => :build do |t|
t.text 'Test Twitter Status message'
t.association :user, :factory => :twitter_user #this line causes the problems
end
Factory.define :twitter_user, :class => Twitter::User, :default_strategy => :stub do |u|
u.profile_image_url "#{RAILS_ROOT}/public/images/rails.png"
end
The t.association :user, :factory => :twitter_user causes the problems because when it is there this exception is thrown. Is there anyway to fix this? Or is factory girl just designed for activerecord objects? Thanks
NoMethodError: undefined method `save!' for #<Twitter::User:0x4af3de46>
/usr/local/share/jruby-1.1.6/lib/ruby/gems/1.8/gems/thoughtbot-factory_girl-1.2.0/lib/factory_girl/proxy/create.rb:5:in `result'
/usr/local/share/jruby-1.1.6/lib/ruby/gems/1.8/gems/thoughtbot-factory_girl-1.2.0/lib/factory_girl/factory.rb:293:in `run'
/usr/local/share/jruby-1.1.6/lib/ruby/gems/1.8/gems/thoughtbot-factory_girl-1.2.0/lib/factory_girl/factory.rb:237:in `create'
/usr/local/share/jruby-1.1.6/lib/ruby/gems/1.8/gems/thoughtbot-factory_girl-1.2.0/lib/factory_girl/proxy/build.rb:17:in `associate'
/usr/local/share/jruby-1.1.6/lib/ruby/gems/1.8/gems/thoughtbot-factory_girl-1.2.0/lib/factory_girl/attribute/association.rb:13:in `add_to'
/usr/local/share/jruby-1.1.6/lib/ruby/gems/1.8/gems/thoughtbot-factory_girl-1.2.0/lib/factory_girl/factory.rb:290:in `run'
/usr/local/share/jruby-1.1.6/lib/ruby/gems/1.8/gems/thoughtbot-factory_girl-1.2.0/lib/factory_girl/factory.rb:288:in `each'
/usr/local/share/jruby-1.1.6/lib/ruby/gems/1.8/gems/thoughtbot-factory_girl-1.2.0/lib/factory_girl/factory.rb:288:in `run'
/usr/local/share/jruby-1.1.6/lib/ruby/gems/1.8/gems/thoughtbot-factory_girl-1.2.0/lib/factory_girl/factory.rb:217:in `build'
test/functional/tweet_feeds_controller_test.rb:12:in `test_Display_friends_timeline_for_the_'amber'_user'
/usr/local/share/jruby-1.1.6/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/testing/setup_and_teardown.rb:94:in `run_with_callbacks_and_mocha'

I'm pretty sure that factory girl is just for ActiveRecord objects, you should just be able to mock up and stub a Twitter::User object rather than use a Factory, if you were using rSpec maybe (if my syntax is right):
#twitter_user = mock(Twitter::User, :profile_image =>"#{RAILS_ROOT}/public/images/rails.png")
and then attach that to your object that needs it.
This might not be quite right, but it's the path I would start down.

Related

Rails 5, Factory Bot and Paperclip can't find file

I can't figure out how to give a file in one of my Factories. I'm using the default test suite of rails 5, Factory Bot, and Paperclip. This is the test I'm running:
require 'test_helper'
class AttachmentTest < ActiveSupport::TestCase
test "should be valid" do
p "should look into: #{ActionController::TestCase.fixture_path}"
ressource = build(:attachment)
assert ressource.valid?
end
end
This is my fixture:
include ActionDispatch::TestProcess
FactoryBot.define do
factory :attachment do
file { fixture_file_upload('files/invoice.pdf', 'application/pdf') }
association :attachable, factory: :mission
end
end
I've invoice.pdf in /Users/Daniel/GitHub/haeapua-rails/test/fixtures/files (both values copy / pasted here directly from terminal)
The trace I get
# Running:
"should look into: /Users/Daniel/GitHub/haeapua-rails/test/fixtures/"
E
Error:
AttachmentTest#test_should_be_valid:
RuntimeError: files/invoice.pdf file does not exist
test/factories/attachments.rb:5:in `block (3 levels) in <top (required)>'
test/models/attachment_test.rb:7:in `block in <class:AttachmentTest>'
bin/rails test test/models/attachment_test.rb:5
I'm missing something but can't figure out what. As I'm using FactoryBot, does it change the fixtures/files path? How could I know it?
Edit
Try to move the invoice to this places:
/Users/Daniel/GitHub/haeapua-rails/test/fixtures/files/invoice.pdf
/Users/Daniel/GitHub/haeapua-rails/test/factories/files/invoice.pdf
/Users/Daniel/GitHub/haeapua-rails/test/files/invoice.pdf
/Users/Daniel/GitHub/haeapua-rails/files/invoice.pdf

Created New User - User Exists?

I went to create a user=User.new (:screen_name => "jeff holmes", :email "jeff92#jeff.com", :password "1234") I had some validations I was trying to see if it would pass:
class User < ActiveRecord::Base
validates_uniqueness_of :screen_name, :email
validates_length_of :screen_name, :within => 4...20
validates_length_of :password, :within => 4...20
validates_length_of :email, :within => 6...50
def validate
errors.add(:email, 'must be valid.') unless email.include? ("#")
errors.add(:screen_name, 'cannot include spaces.') if screen_name.include?(" ")
end
end
After I try to create the user all this stuff pops up and I have no idea what it is.
NameError: undefined local variable or method `user' for main:Object
from (irb):3
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/railties-4.2.1/lib/rails/commands/console.rb:110:in `start'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/railties-4.2.1/lib/rails/commands/console.rb:9:in `start'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/railties-4.2.1/lib/rails/commands/commands_tasks.rb:68:in `console'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/railties-4.2.1/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/railties-4.2.1/lib/rails/commands.rb:17:in `<top (required)>'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:274:in `require'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:274:in `block in require'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:240:in `load_dependency'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:274:in `require'
from /Users/coreyholmes/RubymineProjects/worklink/bin/rails:8:in `<top (required)>'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:268:in `load'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:268:in `block in load'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:240:in `load_dependency'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:268:in `load'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spring-1.3.6/lib/spring/commands/rails.rb:6:in `call'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spring-1.3.6/lib/spring/command_wrapper.rb:38:in `call'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spring-1.3.6/lib/spring/application.rb:183:in `block in serve'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spring-1.3.6/lib/spring/application.rb:156:in `fork'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spring-1.3.6/lib/spring/application.rb:156:in `serve'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spring-1.3.6/lib/spring/application.rb:131:in `block in run'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spring-1.3.6/lib/spring/application.rb:125:in `loop'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spring-1.3.6/lib/spring/application.rb:125:in `run'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spring-1.3.6/lib/spring/application/boot.rb:18:in `<top (required)>'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
from /Users/coreyholmes/.rbenv/versions/2.2.2/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
Then after all that stuff pops up I go user.save and this appears.
NameError: undefined local variable or method `user' for main:Object
Whats going on? What am I doing wrong here.
Thanks
Not 100% certain on the problem at hand but here's a little overview of the create process
user = User.new # creates the user object/instance but DOES NOT save or populate the ID column/attribute/method
# OR ...
user = User.new(params[:user]) # often what you see in a controller action
user.valid? # checks to ensure your validations pass ... duh :)
user.save # saves the users
# from here, you can do a few things:
user.persisted? # this checks if the user was saved in the DB
user.id
# will now show you the user's id ...
# in your original post's code it appears you check for the id _before_ the save and it has to be saved before that attribute/method is populated.
The User Exists is Rails checking to see if that user is already in the DB before it tries to save it (my sense is that your User model validates the email and screen_name methods/attributes)
As for seeing the user after it's created you can do a couple of things:
If you're in a console, just type user to get the output.
In a web view (read: browser), you would go to http://localhost:3000/users/ID_OF_NEW_USER (this assumes you have a show action in your UsersController and a show view (show.html.erb or show.html.haml) ... and if you generated a scaffold (rails generate scaffold User email:string ..., you have these!)
Again, not totally sure I understood your request but I hope this helps you understand this flow a little better.
UPDATE:
Just saw the additions to your post. This code is incorrect:
user=User.new (:screen_name => "jeff holmes", :email "jeff92#jeff.com", :password "1234")
It should be
user=User.new (:screen_name => "jeff_holmes", :email => "jeff92#jeff.com", :password => "1234") # note the missing '=>' for email and password and the space in the screen_name, which is invalid according to the model
You are doing fine.
user = User.create name: "name", email: "email#test.com", password: "123456"
By calling the create method of a class its running all validations. Unless they failed its calling the save method. Since user is a new_object? rails will create the user.
After that you are having the user instance in your variable "user".
The other way is
user = User.new
user.email = "test#test.de"
....
user.save
Here again, the save method will call validations, and if they pass it will save the object to the database.
You can get the ID with user.id or User.last (which will load the latest user out of the database).
The best way to test those behaviors and play with it is the rails console. you can run it with rails c
you are doing fine.
just a little hint: have a look at the gem called "devise" which implements you a complete user-auth logic within 15 minues. no line of code needs to be written.

Custom validations causing errors

I am new to rails and am following the Depot application in the Pragmatic Agile Web development with rails and I am having an odd problem.
In my product model I created a validator for confirming that the image asked for in the image url field actually exist as an asset. Here is my product model code.
class Product < ActiveRecord::Base
attr_accessible :description, :image_url, :price, :title
validates :description, :price, :title, :presence => true
validate :image_url_exists, on: :create
def image_url_exists
if Rails.application.assets.find_asset(image_url) == nil
errors.add(:image_url, 'is not valid. The image does not exist.')
end
end
end
Now the problem is when I run my unit test. Here is what it is:
require 'test_helper'
class ProductTest < ActiveSupport::TestCase
test "the products attributes should not be empty" do
p = Product.new
assert p.invalid?
end
end
But doing so triggers a bunch of errors in my code. Without the custom validtor, everything seems to work just fine. Here are the errors I am currently getting.
test_the_products_attributes_should_not_be_empty(ProductTest):
TypeError: can't convert nil into String
/var/lib/gems/1.9.1/gems/sprockets-2.2.2/lib/sprockets/base.rb:156:in `initialize'
/var/lib/gems/1.9.1/gems/sprockets-2.2.2/lib/sprockets/base.rb:156:in `new'
/var/lib/gems/1.9.1/gems/sprockets-2.2.2/lib/sprockets/base.rb:156:in `find_asset'
/var/lib/gems/1.9.1/gems/sprockets-2.2.2/lib/sprockets/index.rb:60:in `find_asset'
/var/lib/gems/1.9.1/gems/sprockets-2.2.2/lib/sprockets/environment.rb:78:in `find_asset'
/home/saurabh/Desktop/SCRIPTS/Rails/depot/app/models/product.rb:6:in `image_url_exists'
/var/lib/gems/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:418:in `_run__4343689776242734370__validate__107120755283260520__callbacks'
/var/lib/gems/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:405:in `__run_callback'
/var/lib/gems/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:385:in `_run_validate_callbacks'
/var/lib/gems/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:81:in `run_callbacks'
/var/lib/gems/1.9.1/gems/activemodel-3.2.9/lib/active_model/validations.rb:228:in `run_validations!'
/var/lib/gems/1.9.1/gems/activemodel-3.2.9/lib/active_model/validations/callbacks.rb:53:in `block in run_validations!'
/var/lib/gems/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:403:in `_run__4343689776242734370__validation__107120755283260520__callbacks'
/var/lib/gems/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:405:in `__run_callback'
/var/lib/gems/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:385:in `_run_validation_callbacks'
/var/lib/gems/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:81:in `run_callbacks'
/var/lib/gems/1.9.1/gems/activemodel-3.2.9/lib/active_model/validations/callbacks.rb:53:in `run_validations!'
/var/lib/gems/1.9.1/gems/activemodel-3.2.9/lib/active_model/validations.rb:195:in `valid?'
/var/lib/gems/1.9.1/gems/activerecord-3.2.9/lib/active_record/validations.rb:69:in `valid?'
/var/lib/gems/1.9.1/gems/activemodel-3.2.9/lib/active_model/validations.rb:203:in `invalid?'
The problem is Rails.application.assets.find_asset(image_url), image_url is nil when you create a refresh object at test:
p = Product.new # Here p.image_url => nil
You can find the reason of the error looking at log
/var/lib/gems/1.9.1/gems/sprockets-2.2.2/lib/sprockets/base.rb:156:in `initialize'
Here (link) the line 156 where error happens, path was nil here.
So to solve this problem you need to add a condition at your if to check if image_url isn't nil, here is my sugestion
if self.image_url.nil? || Rails.application.assets.find_asset(self.image_url).nil?
errors.add(:image_url, 'is not valid. The image does not exist.')
end

NoMethodError for object

Here is the code
#add email of team lead of the current user
def add_the_tl_email(to_address, session_user_id)
ul = UserLevel.find_by_user_id(session_user_id)
if !ul.team.nil? && !ul.role.nil?
User.user_status('active').joins(:user_levels).where(:user_levels => {:position => 'tl',
:role => ul.role,
:team => ul.team }).each do
|u| to_address << u.email
end
end
end
The error from spec:
1) CustomersController GET customer page 'create' successful should create one customer record
Failure/Error: post 'create', :customer => #customer
NoMethodError:
undefined method `team' for nil:NilClass
# ./app/mailers/user_mailer.rb:36:in `add_the_tl_email'
# ./app/mailers/user_mailer.rb:15:in `notify_tl_dh_ch_ceo'
# ./app/controllers/customers_controller.rb:27:in `create'
# ./spec/controllers/customers_controller_spec.rb:48:in `block (5 levels) in <top (required)>'
# ./spec/controllers/customers_controller_spec.rb:47:in `block (4 levels) in <top (required)>'
team is a field in user_level. Here is the user_level in factory:
Factory.define :user_level do |level|
level.role "sales"
level.position "member"
level.team 1
level.association :user
end
In rails console, the ul.team.nil? returns either true or false on test data generated by factory.
Since team is a field in user_level, why there is error in spec like: NoMethodError:
undefined method `team' for nil:NilClass ?
Thanks.
The issues is that nil.team is not a method*
NoMethodError:
undefined method `team' for nil:NilClass
That is, ul evaluates to nil: check ul.nil? before checking ul.team.nil?... but might want to find out why the find failing to start with ;-)
Happy coding.
*This is what the real error message says, the title of the post is garbage :-/
The call in
ul = UserLevel.find_by_user_id(session_user_id)
returned nil and thus nil was assigned to ul.
So when you called
!ul.team.nil?
Ruby tried to call team on nil. nil is an instance of NilClass and there is no method named team on NilClass.

uninitialized constant Active Scaffold rails 2.3.5

I update my rails application 2.0.2 to 2.3.5. I use active scaffold for the administration part.
I change nothing in my code but a problem is coming with the update.
I have a controller 'admin/user_controller' to manage users.
Here is the code of the controller:
class Admin::UserController < ApplicationController
layout 'admin'
active_scaffold :user do |config|
config.columns.exclude :content, :historique_content, :user_has_objet, :user_has_arme, :user_has_entrainement, :user_has_mission, :mp, :pvp, :user_salt, :tchat, :notoriete_by_pvp, :invitation
config.list.columns = [:user_login, :user_niveau, :user_mail, :user_bloc, :user_valide, :group_id] #:user_description, :race, :group, :user_lastvisited, :user_nextaction, :user_combats_gagner, :user_combats_perdu, :user_combats_nul, :user_password, :user_salt, :user_combats, :user_experience, :user_mana, :user_vie
config.create.link.page = true
config.update.link.page = true
config.create.columns.add :password, :password_confirmation
config.update.columns.add :password, :password_confirmation
config.create.columns.exclude :user_password, :user_salt
config.update.columns.exclude :user_password, :user_salt
config.list.sorting = {:user_login => 'ASC'}
config.subform.columns = []
end
end
This code hasn't change with the update, but when I go in this page, I got this error:
uninitialized constant Users
/Users/Kiva/.gem/ruby/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:443:in `load_missing_constant'
/Users/Kiva/.gem/ruby/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:80:in `const_missing'
/Users/Kiva/.gem/ruby/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:92:in `const_missing'
/Users/Kiva/.gem/ruby/1.8/gems/activesupport-2.3.5/lib/active_support/inflector.rb:361:in `constantize'
/Users/Kiva/.gem/ruby/1.8/gems/activesupport-2.3.5/lib/active_support/inflector.rb:360:in `each'
/Users/Kiva/.gem/ruby/1.8/gems/activesupport-2.3.5/lib/active_support/inflector.rb:360:in `constantize'
/Users/Kiva/.gem/ruby/1.8/gems/activesupport-2.3.5/lib/active_support/core_ext/string/inflections.rb:162:in `constantize'
/Users/Kiva/Documents/Projet-rpg/jeu/vendor/plugins/active_scaffold/lib/extensions/reverse_associations.rb:28:in `reverse_matches_for'
/Users/Kiva/Documents/Projet-rpg/jeu/vendor/plugins/active_scaffold/lib/extensions/reverse_associations.rb:24:in `each'
/Users/Kiva/Documents/Projet-rpg/jeu/vendor/plugins/active_scaffold/lib/extensions/reverse_associations.rb:24:in `reverse_matches_for'
/Users/Kiva/Documents/Projet-rpg/jeu/vendor/plugins/active_scaffold/lib/extensions/reverse_associations.rb:11:in `reverse'
/Users/Kiva/Documents/Projet-rpg/jeu/vendor/plugins/active_scaffold/lib/active_scaffold/data_structures/column.rb:117:in `autolink?'
/Users/Kiva/Documents/Projet-rpg/jeu/vendor/plugins/active_scaffold/lib/active_scaffold.rb:107:in `links_for_associations'
/Users/Kiva/Documents/Projet-rpg/jeu/vendor/plugins/active_scaffold/lib/active_scaffold/data_structures/columns.rb:62:in `each'
/Users/Kiva/Documents/Projet-rpg/jeu/vendor/plugins/active_scaffold/lib/active_scaffold/data_structures/columns.rb:62:in `each'
/Users/Kiva/Documents/Projet-rpg/jeu/vendor/plugins/active_scaffold/lib/active_scaffold.rb:106:in `links_for_associations'
/Users/Kiva/Documents/Projet-rpg/jeu/vendor/plugins/active_scaffold/lib/active_scaffold.rb:59:in `active_scaffold'
/Users/Kiva/Documents/Projet-rpg/jeu/app/controllers/admin/user_controller.rb:11
I search since 2 days but I don't find the problem, can you help me please.
the naming convention in your application seems buggy
it should be:
class Admin::UsersController < ApplicationController
not UserController as it is. maybe it won't fix your problem, but it worth a try!
It seems to be a problem with the way the Model is defined. I had the very same issue when accessing tables in the database with a rake backup task. The problem was that I had a table defined in the database through "belongs_to". I didn't think I needed a model for that table but constantize kept failing. Introducing the model fixed the problem.
Table : users_clients
Model : UsersClient
Starting with Rails 2.3.x you have to install the Render Component plugin:
./script/plugin install git://github.com/ewildgoose/render_component.git -r rails-2.3
See instructions here: https://github.com/activescaffold/active_scaffold/wiki/getting-started

Resources