Multiple rails requests leads to uninitialized constant - ruby-on-rails

I have a very simple set up where I make an API call, which calls a function, which will initialize an instance of a class. Weirdly, it works the first time, but any additional attempts to refresh the page gives me an uninitialized constant error for the very class being initialized. Here's an example
Rails 3.1
Ruby 2.0
in app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
require_relative 'test.rb'
def about
build_fleet()
render text: "This worked"
end
end
and in my app/controllers/test.rb:
class Fleet
def initialize(side)
#ships = []
#passive_abilities = []
#side = side
end
end
def build_fleet()
att_fleet = ::Fleet.new("att")
def_fleet = ::Fleet.new("def")
end
I go to localhost/static_pages/about and get "This worked". Hit refresh and see "Fleet uninitialized" complete with the appropriate fleet stack.
When I check the server log I see
>Started GET "/static_pages/about" for 127.0.0.1 at 2014-04-05 15:52:39 -0700
> Processing by StaticPagesController#about as HTML
>Completed 500 Internal Server Error in 4ms
>
>NameError (uninitialized constant Fleet):
> app/controllers/test.rb:10:in `build_fleet'
> app/controllers/static_pages_controller.rb:4:in `about'
What's going wrong on the reload?

This seems related to how rails in development mode tries to automatically reload code on each request.
Try the advice in this answer and replace the call to require_relative with require_or_load "./test.rb"
*Edit: *
I think what's happening is that at the end of every request in development mode, rails undefines most constants it knows about. (Classes are constants.)
The next request comes in and you ask ruby to load the file. But since this second request is part of the same process, ruby remembers that it already loaded test.rb and so it is skipped.
However, it looks like Fleet is a model (even if not a database-backed model). I'd drop it in the app/models/fleet.rb and rails will auto load it just fine.

Related

uninitialized constant - loading class issue?

So, I got mailer app/mailers/dynamic_mailer.rb and model app/models/email_message/outgoing.rb. There is method:
class EmailMessage::Outgoing < EmailMessage
...
def deliver_mail
l = ::DynamicMailer.email_message(self).deliver!
Rails.logger.info "SEND MAIL: #{l.inspect}"
update_attribute(:received_at, Time.now)
end
Locally (developement env) everything works fine. The problem occurs when I'm deploying app to server (staging env) and trying to send email form there. Delayed job prints:
[Worker(host:rdev pid:2279)] EmailMessage::Outgoing#send_email!
failed with NameError: uninitialized constant
EmailMessage::Outgoing::DynamicMailer - 11 failed attempts
It looks like a problem with loading classes on server. Removing double colons before class name fails.
Any help will be greatly appreciated.
Try to specify file with DynamicMailer obviously in file with your model like this require 'app/mailers/dynamic_mailer.rb'. Probably it can help to find necessary class.
Also I've noticed that in error message is mentioned send_email! method but you posted here def deliver_mail method. Whether I don't understand something or you're looking in wrong place.
I just forgot to restart delayed job daemon.
You can do it with capistrano, by adding gem 'daemons' to your Gemfile and updating receipes like that: http://cmar.me/2011/02/21/delayed_job-with-rails-3-and-capistrano/

How do I call the Rails console's reload! command programmatically?

When using the Rails console, there's a handy reload! function which reloads models and such. How do I call this from another part of my program?
Edit I've been asked for the use case a bit. It was that I had a long running JVM process running Jruby and a clojure repl. I could run RSpec tests from the REPL and could run arbitrary Ruby code from there too. But I couldn't figure out how to reload the Ruby classes so that I could edit the code and see it changed in the Ruby runtime. I no longer use this setup, principally because testing it was such a pain.
(I'm using Jruby and can access the Ruby VM programatically from my backend).
Have you tried touching restart.txt? Unfortunately, I have no experience with JRuby, but confirmed it works on my app.
FileUtils.touch('tmp/restart.txt')
You probably want to do something other than a Get request, and secure it behind some authentication.
I threw it in an Admin controller and added the route to config/routes.
# app/controllers/admin.rb
class AdminController < ApplicationController::Base
##time = Time.now # This value gets cached with the model.
def reboot
FileUtils.touch('tmp/restart.txt')
#restarted_time = ##time
end
end
# config/routes.rb
namespace :admin
get 'reboot'
end
# app/views/admin/reboot.html.erb
<%= #restarted_time.to_s %>

Rails controller doesn't recognize model

I am trying to build a very simple rails application.
When user submits a form I process some files on the server and display the results.
Clearly, I do not need a database for this. However, I created a model so that I can put all my processing logic in it.
In in the controller, I call the process function in the model. for example
# action in controller
def my_action
MyModel.process(params)
end
However, when I run the server and submit the form, rails says MyModel is uninitialized
uninitialized constant MyController::MyModel
What am I doing wrong?
Where do you define MyModel? Is it in app/models/my_model.rb as Rails (to put it simply) expects it to be?

LoadError in StoreController#add_to_cart

I am trying to learn Ruby on Rails using Agile Web Development with Rails third edition and I am completely stuck. I am using Ruby version 1.8.7 and rails 2.3.5 on Linux Mint. Just after the book recommended that I change from cookies to the SQLite database to manage sessions, the application no longer works. I get the following error when I click on the “add to cart” button in http://localhost:3000/store:
LoadError in StoreController#add_to_cart
Expected /home/dave/work/depot/app/models/cart.rb to define Cart
RAILS_ROOT: /home/dave/work/depot
Application Trace | Framework Trace | Full Trace
/usr/lib/ruby/1.8/active_support/dependencies.rb:426:in load_missing_constant'
/usr/lib/ruby/1.8/active_support/dependencies.rb:80:inconst_missing'
/usr/lib/ruby/1.8/active_support/dependencies.rb:92:in const_missing'
/usr/lib/ruby/1.8/active_support/dependencies.rb:437:inload_missing_constant'
/usr/lib/ruby/1.8/active_support/dependencies.rb:96:in const_missing'
/home/dave/work/depot/app/controllers/store_controller.rb:14:infind_cart'
/home/dave/work/depot/app/controllers/store_controller.rb:8:in `add_to_cart'
Request
Parameters:
{"authenticity_token"=>"38s45mRICYPJ7dw+z/rlcBnQN7T8ZwfEThzUTFUrjeM=",
"id"=>"3"}
Show session dump
Response
Headers:
{"Content-Type"=>"",
"Cache-Control"=>"no-cache"}
def add_product(product)
current_item = #items.find {|item| item.product == product}
if current_item
current_item.increment_quantity
else
#items << CartItem.new(product)
end
end
I have done a search on this in Google and a similar error seems to be related to utf-8 encoding. I used Gedit to save the file as Western (ISO 8859-15) encoding and it made no difference. I have also retyped the programs in Vi to no avail. Each time I have made a change, I have stopped and restarted the server and also entered db:sessions:clear into a terminal.
I'm stumped. Any ideas?
This error tends to occur when there is an error in the file being loaded. One way to figure this out is to run:
ruby script/console
... then:
Cart
This should either load up the model OK, or output a more useful error.
Check your app/models/cart.rb , it should be like this
class Cart < ActiveRecord::Base
#stuff here
end
make sure its that.

First Call to a Controller, Constant is defined, Second call, "uninitialized constant Oauth"?

I am trying to get the OAuth gem to work with Rails 3 and I'm running into this weird problem... (independent of the gem, I think I've run into this once before)
I have a controller called "OauthTestController", and a model called "ConsumerToken". The model looks like this.
require 'oauth/models/consumers/token'
class ConsumerToken < ActiveRecord::Base
include Oauth::Models::Consumers::Token
end
When I go to "/oauth_test/twitter", it loads the Oauth::Models::Consumers::Token module and I'm able to connect to twitter no problem. But the second time I try it (just refresh the /oauth_test/twitter url), it gives me this error:
NameError (uninitialized constant Oauth):
app/models/consumer_token.rb:4
app/models/twitter_token.rb:2
app/controllers/oauth_test_controller.rb:66:in `load_consumer'
Why is that? It has something to do with load paths or being in development mode maybe?
Try using require_or_load instead of require. That forces full load each time when in development and can sometimes help with this sort of issue.
Yeah it's something to do with being in development mode. Setting config.cache_classes = true in your development.rb get's it working (but is a pain in the ass)

Resources