Rails 6.1.3.1
Rspec
basic behavior spec code:
describe "index" do
it "should show me the list" do
visit dashboard_targets_path
end
end
the routes file
namespace :dashboard do
resources :targets
end
error shows me the exception, but strangely it appears as if it isn't calling through to the app, just fails right in my test code:
1) interaction for Dashboard::TargetsController index should show me the list
Failure/Error: visit dashboard_targets_path
NoMethodError:
undefined method `empty?' for nil:NilClass
# ./spec/system/dashboard/targets_behavior_spec.rb:16:in `block (3 levels) in <top (required)>'
# /Users/jason/.rvm/gems/ruby-2.6.6/gems/webmock-3.12.2/lib/webmock/rspec.rb:37:in `block (2 levels) in <main>'
# /Users/jason/.rvm/gems/ruby-2.6.6/gems/rspec-wait-0.0.9/lib/rspec/wait.rb:46:in `block (2 levels) in <main>'
it seems to be failing inside the test code, if I drop into the debugger there and run dashboard_targets_path directly I also get the same exception, so the problem is just using the helper within the TEST ENVIRONMENT
within the dev environment, this function works
the problem here was the the config/environments/test.rb file does have default_url_options.
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
when you hit errors that disappear into the Rails gems, a good way to debug them is like so:
begin
// your failing code here
rescue StandardError => e
puts e.backtrace
byebug
puts e.inspect
raise (e)
end
WARNING: do not leave this code in your app or check it in unless you explicitly want to use exception handling for flow control (not recommended!). This is recommended ONLY for debugging purposes.
here you will see the full backtrace to the line number in the Gem where it is failing. when debugging Gems be careful— remember to un-do any changes you make and know that your monkey-patching inside of the Gem code doesn't affect your production code.
I am a beginner programmer in Ruby and Ruby on Rails , I'm trying to run a rake command in my task , but when I do the following happens:
rake daily_tasks:process_api
rake aborted!
ActiveRecord::AssociationTypeMismatch: Estado(#47392639701120) expected, got NilClass(#47392580444120)
/home/thiagoamaralr/Desktop/proponente-master-4f8a3b2ddb02a90b2c173cf31383505018d02dd/app/services/create_programa_api.rb:21:in `call'
/home/thiagoamaralr/Desktop/proponente-master-74f8a3b2ddb02a90b2c173cf31383505018d02dd/lib/tasks/daily_tasks.rake:7:in `block (3 levels) in <top (required)>'
/home/thiagoamaralr/Desktop/proponente-master-74f8a3b2ddb02a90b2c173cf31383505018d02dd/lib/tasks/daily_tasks.rake:5:in `each'
/home/thiagoamaralr/Desktop/proponente-master-74f8a3b2ddb02a90b2c173cf31383505018d02dd/lib/tasks/daily_tasks.rake:5:in `block (2 levels) in <top (required)>'
Tasks: TOP => daily_tasks:process_api
(See full trace by running task with --trace)
Follow the task I'm trying to run:
namespace :daily_tasks do
desc "Process the day to day tasks"
task process_api: :environment do
SiconvApi::Programa.find.each do |programa|
if programa.data_inicio_recebimento_propostas && (programa.data_inicio_recebimento_propostas.to_date >= Date.parse("2015/06/01"))
CreateProgramaApi.call(SiconvApi::Serializers::Programa.new(programa))
end
end
end
end
And this is content create_programa_api.rb:
class CreateProgramaApi
def self.call(programa_api)
params = programa_api.to_h
params[:orgao] = Orgao.where("lower(name) = ?", programa_api[:orgao][:nome].mb_chars.downcase).first_or_create(name: programa_api[:orgao][:nome])
params[:orgao_vinculado] = Orgao.where("lower(name) = ?", programa_api[:orgao_vinculado][:nome].mb_chars.downcase).first_or_create(name: programa_api[:orgao_vinculado][:nome])
params[:orgao_executor] = Orgao.where("lower(name) = ?", programa_api[:orgao_executor][:nome].mb_chars.downcase).first_or_create(name: programa_api[:orgao_executor][:nome])
params[:estados] = []
if programa_api[:estados].size == 27
params[:estados] << Estado.find_by(sigla: 'Todos')
else
programa_api[:estados].each do |e|
params[:estados] << Estado.find_by(sigla: e)
end
end
params[:atendes] = [Atende.where("lower(name) = ?", programa_api[:atende_a].mb_chars.downcase).first_or_create(name: programa_api[:atende_a])] if programa_api[:atende_a]
params.delete(:atende_a)
programa = Programa.find_by(codigo: programa_api[:codigo])
if programa
programa.update(params)
else
Programa.create! params
end
end
end
Thanks for your attention!
You have nil object in params[:estados], and Rails can't save this association.
Easiest way to remove them is to call params[:estados].compact! after line 14
This block of code is your problem:
params[:estados] = []
if programa_api[:estados].size == 27
params[:estados] << Estado.find_by(sigla: 'Todos')
else
programa_api[:estados].each do |e|
params[:estados] << Estado.find_by(sigla: e)
end
end
If no record is found, the #find_by returns nil. This is why you are getting the error:
ActiveRecord::AssociationTypeMismatch: Estado(#47392639701120) expected, got NilClass
When calling Programa.create!(params).
One solution would be to call params[:estados].compact! after the if statement (this is using Array#compact! to remove any nil values).
Or, you could instead write that section of code like this:
params[:estados] = Estadio.where(
sigla: (programa_api[:estados].size == 27 ? 'Todos' : programa_api[:estados])
)
With this code, there is no longer a need to call compact! since we already end up with an empty array if no records are found (i.e. there are no nil values).
Note that the behaviour here isn't quite the same - what happens if there are multiple Estado records with the sigla equal to one of programa_api[:estados] or 'Todos'? Previously you were only fetching the "first" such record, whereas now you'd be fetching all of them. This may not be an issue (or may even be the correct behaviour!!) - it's just something to be aware of, at least.
I'm upgrading a Rails 4.0 app to Rails 4.2. All the tests passed prior to the upgrade. However, I am now getting several errors (but no failures). This is the output of one of the tests:
Run options: --seed 30437
# Running:
E
Finished in 1.738307s, 0.5753 runs/s, 0.0000 assertions/s.
/opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/actionpack-4.2.1/lib/action_dispatch/testing/assertions/routing.rb:171:in `method_missing': private method `location' called for #<[MyTestClass]:0xb46557c> (NoMethodError)
from /opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/actionpack-4.2.1/lib/action_dispatch/testing/integration.rb:397:in `method_missing'
from /opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/minitest-5.6.0/lib/minitest/test.rb:265:in `block in to_s'
from /opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/minitest-5.6.0/lib/minitest/test.rb:264:in `map'
from /opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/minitest-5.6.0/lib/minitest/test.rb:264:in `to_s'
from /opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/minitest-5.6.0/lib/minitest.rb:580:in `%'
from /opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/minitest-5.6.0/lib/minitest.rb:580:in `block in aggregated_results'
from /opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/minitest-5.6.0/lib/minitest.rb:579:in `each'
from /opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/minitest-5.6.0/lib/minitest.rb:579:in `each_with_index'
from /opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/minitest-5.6.0/lib/minitest.rb:579:in `each'
from /opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/minitest-5.6.0/lib/minitest.rb:579:in `map'
from /opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/minitest-5.6.0/lib/minitest.rb:579:in `aggregated_results'
from /opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/minitest-5.6.0/lib/minitest.rb:566:in `report'
from /opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/minitest-5.6.0/lib/minitest.rb:638:in `each'
from /opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/minitest-5.6.0/lib/minitest.rb:638:in `report'
from /opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/minitest-5.6.0/lib/minitest.rb:134:in `run'
from /opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/minitest-5.6.0/lib/minitest.rb:56:in `block in autorun'
I can't seem to find anything in my code that could be causing this error. Looking at some of the files mentioned in the stacktrace, it looks like it is erroring while trying to generate a failure message. (Double fail...)
What is the cause of this error?
Edit:
The first line of my test is s = login(:user). If I place a return before that line, the test passes, but if I place it after that line, I still get the error. The login function is defined in my test_helper.rb as follows:
def login(user)
open_session do |sess|
u = users(user)
sess.extend(MySession)
sess.get "/users/sign_in"
sess.assert_response :success
sess.post_via_redirect "/users/sign_in",
user: {
email: u.email,
password: "<password>"
}
assert_equal '/', sess.path
assert_equal "Signed in successfully.", sess.flash[:notice]
end
end
The module MySession contains a few helper methods.
Edit 2:
I opened a rails console session, required my test class, and did MyTestClass.private_methods. This was the output:
=> [:initialize, :_stash_object_in_method, :_superclass_delegating_accessor, :included, :extended, :prepended, :method_added, :method_removed, :method_undefined, :initialize_copy, :attr, :attr_reader, :attr_writer, :attr_accessor, :initialize_clone, :remove_const, :using, :remove_method, :undef_method, :alias_method, :public, :protected, :private, :define_method, :attr_internal_ivar_name, :attr_internal_define, :DelegateClass, :Digest, :timeout, :default_src_encoding, :Nokogiri, :irb_binding, :create_fixtures, :load, :require, :initialize_dup, :sprintf, :format, :Integer, :Float, :String, :Array, :Hash, :warn, :raise, :fail, :global_variables, :__method__, :__callee__, :__dir__, :eval, :local_variables, :iterator?, :block_given?, :catch, :throw, :loop, :respond_to_missing?, :trace_var, :untrace_var, :at_exit, :syscall, :open, :printf, :print, :putc, :puts, :gets, :readline, :select, :readlines, :p, :srand, :rand, :trap, :require_relative, :proc, :lambda, :binding, :caller, :caller_locations, :exec, :fork, :exit!, :system, :spawn, :sleep, :exit, :abort, :Rational, :Complex, :set_trace_func, :gem_original_require, :Pathname, :URI, :rubygems_require, :BigDecimal, :j, :jj, :JSON, :not_implemented, :y, :open_uri_original_open, :pp, :singleton_method_added, :singleton_method_removed, :singleton_method_undefined, :method_missing]
Edit 3:
I opened a rails console session, required my test class, and did test = MyTestClass.new and then test.private_methods. This time, the output did contain :location. This app does have a Location model, and this output appeared in between several other of the app's models, so I suspect that is the problem. The question is now: why do my test classes have private methods named after my app's models? How can I fix or work around this problem? (Obviously I could rename the Location model, but I'd prefer to avoid that, if possible.)
Did the location method change from public to private on whatever class you're calling it on between Rails 4.0 and 4.2?
Maybe I'm misunderstanding, but the error seems pretty straightforward. Somewhere (in your code, or maybe a gem you rely on that's changed versions as well) a method called location is being called which is private. The stack track shows you where it's happening, so take a look at that code and see what's going on.
Might also be helpful to see the test code, but the stack trace is pointing you to the source from which you can trace back what's going on.
I looked through the code on github as well and can't find anything. Any chance you defined a method called location on MyTestClass that overrides the one in MiniTest::Test ? Also, if you go into your console and simply require the MyTestClass, and call .private_methods on it (or rather an instance of it), does :location indeed show up in the list? Any include statements anywhere that you can find in your code that might be bringing in a location method into MyTestClass?
It looks like this question/answer might provide a way to track down where these methods are coming from.
Using the .method and .source_location methods from #jefflunt's link, I was able to find the cause of the problem. When I did test.method(:location).source_location from the rails console, I got this output:
=> ["/opt/rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/fixtures.rb", 885]
When I looked up that line in that file, I found a method that defines private accessor methods for each fixture. Since I had fixtures defined for my Location model, that was the cause of this problem.
Since I don't see another way around this problem (aside from perhaps ditching fixtures, which I'm not ready to put time into just yet), I'll be renaming my Location model.
I am migrating data from a database and getting an error I cannot understand. I am new to Ruby and am looking for both what is wrong with my code and also the most effective commands for debugging. I cannot even really read my error.
Here is my error:
/Users/skline/.rvm/gems/ruby-1.9.2-p136#rails3tutorial/gems/activemodel-3.0.6/lib/active_model/attribute_methods.rb:367:in `method_missing': undefined method `answer=' for #<Question:0x00000102d59758> (NoMethodError)
from /Users/skline/.rvm/gems/ruby-1.9.2-p136#rails3tutorial/gems/activerecord-3.0.6/lib/active_record/attribute_methods.rb:46:in `method_missing'
from ./script/migrate.rb:139:in `block (2 levels) in <main>'
from /Users/skline/.rvm/gems/ruby-1.9.2-p136#rails3tutorial/gems/activerecord-3.0.6/lib/active_record/relation.rb:13:in `each'
from /Users/skline/.rvm/gems/ruby-1.9.2-p136#rails3tutorial/gems/activerecord-3.0.6/lib/active_record/relation.rb:13:in `each'
from ./script/migrate.rb:137:in `block in <main>'
from ./script/migrate.rb:111:in `each'
from ./script/migrate.rb:111:in `<main>'
Any tips for reading this error and for how to debug.
Note here is my code:
NetworkCommunications.all.each do |nc|
if nc.NETWORK_COMM_TYPE_ID==1 && nc.SENDER_CONSUMER_ID != 0
q = Question.new
q.created_at = nc.LAST_MOD_TIME
category = CommunicationInterestMapping.where(:COMMUNICATION_ID => nc.COMMUNICATIONS_ID).first
if category
cie = ConsumerInterestExpertLookup.find(category.CONSUMER_INTEREST_EXPERT_ID)
if cie
q.category = Category.find_by_name cie.CONSUMER_INTEREST_EXPERT_NAME
else
puts "No category"
end
end
message = NetworkCommunicationsMessage.where(:COMMUNICATIONS_ID => nc.COMMUNICATIONS_ID).first
q.title = message.SUBJECT
q.description = message.MESSAGE
q.permalink = message.QUESTION_SLUG
email = find_email_from_consumer_id(nc.SENDER_CONSUMER_ID)
q.user = User.find_by_email email
children = NetworkCommunications.where(:PARENT_COMMUNICATIONS_ID => nc.COMMUNICATIONS_ID)
puts children
if children
children.each do |ncc|
if ncc.NETWORK_COMM_TYPE_ID == 2
q.answer = Answer.new
q.answer.created_at = ncc.LAST_MOD_TIME
message_a = NetworkCommunicationsMessage.where(:COMMUNICATIONS_ID => ncc.COMMUNICATIONS_ID).first
q.answer.text = message_a.MESSAGE
email_a = find_email_from_consumer_id(ncc.SENDER_CONSUMER_ID)
q.answer.user = User.find_by_email email_a
end
end
end
begin
q.save!
rescue Exception => e
puts "Exception: #{e} title: #{message.SUBJECT}"
end
end
end
To read the stack dump, look at the first line then read downwards:
/Users/skline/.rvm/gems/ruby-1.9.2-p136#rails3tutorial/gems/activemodel-3.0.6/lib/active_model/attribute_methods.rb:367:in `method_missing': undefined method `answer=' for #<Question:0x00000102d59758> (NoMethodError)
from /Users/skline/.rvm/gems/ruby-1.9.2-p136#rails3tutorial/gems/activerecord-3.0.6/lib/active_record/attribute_methods.rb:46:in `method_missing'
from ./script/migrate.rb:139:in `block (2 levels) in <main>'
The first line tells you where the problem was triggered and why: In ActiveModel's attribute_methods method because no setter for answer was found in the object. This was triggered from a call in line 139 of your migrate.rb script. The trick with a stack trace is to read through it, looking for the scripts you've written. Odds are really good the problem is in our code so it's always good to start from the assumption the bug is ours.
if ncc.NETWORK_COMM_TYPE_ID == 2
q.answer = Answer.new
is where the problem is. Your Question class doesn't have a setter for answer. Either you're missing or misspelled an attribute_accessor call or misspelled a def answer= method.
To debug I recommend using Ruby Debugger 1.9. gem install ruby-debug19. It's 1.9.2 studly and easy to use. You can set a breakpoint in your code, then run it from the command-line, which will run until the breakpoint is reached and will stop in the debugger. From there you can list the current lines using l, display the contents of variables using p or do a require 'pp' if you have pretty-printer installed. You can single-step into methods using s or step over them using n, for "next". There's also c to continue, c 100 to continue to a particular line number; 100 in that example. You can use b 100 to set a break-point at line 100, and then c to run, stopping at 100 every time. irb will drop you into IRB with the variables to that point already initialized so you can poke at them. There are lots of other commands, but those are the ones I use most often.
It probably means you have defined the answer attribute for your question class:
class Question < ActiveRecord::Base
attr_accessor :answer
[...]
end
You should also learn how to use rdebug so that you can step through the code and figure this out without help.
I think your model Question doesn't have answer attribute.
In this cast you can study how to debug rails app
I know this has to be something stupid, but I keep getting the following error in one of my examples:
undefined method `new' for #<Class:0x211d274>
I have created a simple example to show the error:
describe LateCharge do
before :each do
#membership = Membership.new
#location = mock_model(Location, :late_payment_rate => 10)
end
it "should initialize" do
LateCharge.respond_to?('new').should == true
#charge = LateCharge.new(#membership, #location)
end
end
The strange part is, when I run the example by itself, it passes. When I run it with all my examples, it fails with the following error:
NoMethodError in 'LateCharge should initialize'
undefined method `new' for #<Class:0x211d274>
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:1964:in `method_missing_without_paginate'
/Users/l33/.gem/ruby/1.8/gems/mislav-will_paginate-2.3.11/lib/will_paginate/finder.rb:170:in `method_missing'
./spec/models/late_charge_spec.rb:15:
It is failing on the line: #charge = LateCharge.new(#membership, #location)
I do not have any problems instantiating the LateCharge object at run time or from the console.
Anyone have any ideas?
Seems to me the following information is key to your issue:
will_paginate/finder.rb:170:in `method_missing'
Hey Lee - not sure if you're still having this problem, but I had the exact same thing and it's because another spec I had was unstubbing the function.