I have a file booking.rb in my model directory. It contains the class definition
class Booking < ActiveRecord::Base
def self.setup_connection
wsdlurl = 'http://10.14.47.201:7001xxx/webservice/RetrieveBookingsByCCLV1_01.wsdl'
factory = SOAP::WSDLDriverFactory.new(wsdlurl)
##driver = factory.create_rpc_driver
##driver.return_response_as_xml = true
end
end
I attempt to invoke this method from my application.rb see code below.
module PNR2
class Application < Rails::Application
...
...
Booking.setup_connection
end
end
This fails with the following when I run the app...
C:/Users/sg0209028/RubymineProjects/PNR2/config/application.rb:49:in `<class:Application>': uninitialized constant PNR2::Application::Booking (NameError)
from C:/Users/sg0209028/RubymineProjects/PNR2/config/application.rb:18:in `<module:PNR2>'
from C:/Users/sg0209028/RubymineProjects/PNR2/config/application.rb:17:in `<top (required)>
The reason for the reference to line 49 is that I removed all the comments in this application.rb file to avoid taking space in this note. Line 49 in the original was the Booking.setup_connection line.
I am clearly not understanding how name scoping is working in Rails 3. Maybe I also don't understand when I should be invoking a class method to set up a constant in a Model object. It feels like that should be an application initialization task, but maybe that request should be somewhere else.
Ib case anyone is wondering, I have had this code and invocation of the appropriate web services working in a straingth Ruby (non rails) environment.
Below is the code for that
require 'soap/wsdlDriver'
require 'rexml/document'
require 'soap/rpc/driver'
WSDL_URL = "http://10.14.47.202:7001/xxx/webservice/RetrieveBookingsByCCLV1_01.wsdl"
factory = SOAP::WSDLDriverFactory.new(WSDL_URL)
driver = factory.create_rpc_driver
driver.return_response_as_xml = true
params = {"ccl" => "Booking[BookingName[BookingNameItem[TicketNumber > \"123456789\"]]]", "xmlFormat" => "DefaultBooking"}
response = driver.RetrieveBookingsByCCL(params)
doc = REXML::Document.new response
puts "Number of PNRs = " + REXML::XPath.first(doc, "//count").text
doc.elements.each ("//originCity") {|element| puts "Element = " + element.text}
Can anyone please give this newbie some pointers? Oh and yes I do realize that invoking some SOAP based services instead of back ending with a database is going to have some issues. That I am prepared for once I get the connection to work!
Thanks in advance
Chris
I just realized you were trying to use the Booking class in your application.rb file. I think you are going to have issues because at this point your application is not fully configured, but if you can get around those, to actually use the model, you'll have to require the file at the top of your application.rb file:
require 'rails/all'
require File.join(File.dirname(__FILE__), '../app/models/booking')
Booking is in the root-namespace, and you're calling the function (on your line 49) within the PNR2::Application namespace. You should change it to:
module PNR2
class Application < Rails::Application
...
...
::Booking.setup_connection
end
end
Related
I'm trying to make a Ruby on Rails engine, and I want the initializer to be able to have access to the helpers and models.
I'll write below an example, part of the code, and the error that I have. It may not be the recommended way, because I can see that in some cases I'm repeating myself, but it's the first engine I make.
file lib/my_engine/engine.rb
module MyEngine
require 'my_engine/functions'
class Engine < ::Rails::Engine
isolate_namespace MyEngine
config.autoload_paths += %W( #{config.root}/lib )
end
class GlobalVars
attr_accessor :foo
def initialize
#foo = MyEngine::Functions.new
end
end
class << self
mattr_accessor :GLOBAL
mattr_accessor :USER_CONFIG
self.GLOBAL = MyEngine::GlobalVars.new
# add default values of more config vars here
self.USER_CONFIG = 'default config'
end
def self.setup(&block)
yield self
end
end
file lib/my_engine/functions.rb
module MyEngine
require '../../app/helpers/my_engine/options_helper'
class Functions
include MyEngine::OptionsHelper
attr_accessor :some_link
def initialize
#some_link = get_option('dummy')
end
end
end
There is also a controller named OptionsController in app/controllers/my_engine, and OptionsHelper in app/helpers/my_engine/options_helper.rb:
module MyEngine
module OptionsHelper
def get_option(name)
MyEngine::Option.new
end
end
end
When I try to run the dummy application, this error occurs:
/app/helpers/my_engine/options_helper.rb:4:in `get_option': uninitialized constant MyEngine::Option (NameError)
If I change to just Option.new, I have this error:
/app/helpers/my_engine/options_helper.rb:4:in `get_option': uninitialized constant MyEngine::OptionsHelper::Option (NameError)
For ::MyEngine::Option.new, I have:
/app/helpers/my_engine/options_helper.rb:4:in `get_option': uninitialized constant MyEngine::Option (NameError)
For ::Option.new, I have:
/app/helpers/my_engine/options_helper.rb:4:in `get_option': uninitialized constant Option (NameError)
The dummy application has nothing in it. All helpers and models defined above are in the engine.
Before this, I had other errors because it couldn't access the helper, or the Functions class. I had to add require and include to make it work even if they are placed in the same directory. Also, to work, I had to move GlobalVars from its own file inside engine.rb.
Can somebody show me what I'm doing wrong?
After I used required for every class, I ended with ActiveRecord::ConnectionNotEstablished, and it seems that not everything is loaded and available at that point when the GLOBAL object is created.
So I moved the code that was using the models in a separate init method. Then, I added an after initialize event:
config.after_initialize do
MyEngine.GLOBAL.init
end
I see a possible problem: because you are inside module MyEngine it might be possible that actually rails is looking for MyEngine::MyEngine::Option, so I see two approaches:
just write Option: this will look for MyEngine::Option
write ::MyEngine::Option this will look in the global namespace and find MyEngine::Option
Secondly, if that does not help, even though your path seems correct, but you can always explicitly require "my_engine/option" at the top of the file. I am not entirely sure the autoloading in an engine works in quite the same way, and I tend to, in my engine file, require almost everything (to make sure it works).
In my engine.rb I do
require_relative '../../app/models/my_engine/option'
maybe this will help, but it is not a nice solution.
I am new to rails and get stuck on this problem.
The thing I am trying to do is:
I need to call service A to retrieve an idA and then I use idA to perform other actions. my actions in the controller is something like
class SomeController < ApplicationController
def someAction
idA = getIdAfromServiceA(config)
doSomethingElseToServiceB(idA)
end
end
Since the result from serviceA only depends on config, once the config is loaded, idA should not change. Therefore I want to cache idA.
I tried to use instance variable to cache it, no luck("getIdAfromServiceA is called is printed" on every request)
class SomeController
def getIdAfromServiceA(config)
#IdA ||= getIdAfromServiceAviaHTTP(config)
end
private
def getIdAfromServiceAviaHTTP(config)
puts "getIdAfromServiceAviaHTTP is called"
#make some http call
end
end
I also tried to put it in application.rb to cache it on start up. it shows error: undefined method 'getIdAfromServiceAviaHTTP' for SomeHelper:Module (NoMethodError)
module MyProject
class Application < Rails::Application
config.load_defaults 5.1
require_relative 'relativePathToSomeHelperModule'
config.idA = SomeHelper.getIdAfromServiceAviaHTTP(config)
end
end
So my question is, what's a good way to achieve this ? I've been googling for a while but end up in vain. Could you help me with it ? Thanks !
Create a ruby file in under /config/initializers/ and put that code there.
Option 1:
# config/initializers/ida_from_api.rb
IDA = SomeHelper.getIdAfromServiceAviaHTTP(config)
You can then use IDA through out the application.
Option 2:
# config/initializers/ida_from_api.rb
Rails.configuration.idA = SomeHelper.getIdAfromServiceA(config)
You can then use Rails.configuration.idA through out the application. Check Custom configuration for more details.
FYI - files under initializers loaded at the time of application startup.
I'm trying to do something fairly simple - add a module with helper methods to a Model test, but I keep getting the following error
uninitialized constant NeighborhoodTest::NeighboorhoodTestHelper
The module is located in test/helpers/neighborhood_test_helper.rb
module NeighborhoodTestHelper
def create_polygon
points = self.geolocate
boundary = Geokit::Polygon.new(points)
end
.
.
end
Per the recommendation in this SO answer, did the following inside test/models/neighborhood_test.rb:
require 'test_helper'
require 'helpers/neighborhood_test_helper'
class NeighborhoodTest < ActiveSupport::TestCase
include NeighboorhoodTestHelper
def setup
#crime = crimes(:arrest)
#neighborhood = neighborhoods(:one)
end
test "neighborhood should contain crime" do
neighborhood_boundary = #neighborhood.create_polygon
crime_location = #crime.geolocate
assert neighborhood_boundary.contains?(crime_location)
end
end
I also tried this SO that didn't work. Anyone know why this approach doesnt work in Models?
tests/some_helper.rb
module SomeHelper
def method1
-----------
-----------
end
def method2
-----------
-----------
end
end
tests/test_helper.rb
require some_helper.rb
You can now access method1 and method2 in any of your test cases. Hope it helps you .
I ran into this today with rspec 3.8, and with other helper tests working just fine, I was very curious to know what made this one spec so special.
In my case, it turned out the spec file name, for whatever reason, was given the same file name as the helper module itself. When trying to load the constant it was looking in the spec file, since it had taken the place of "my_helper" and in turn ignoring the actual module. Adding a _spec at the end of the spec file name allowed this error to go away, and that spec ran as intended after.
I know this is a simple issue, but if you have hundreds upon hundreds of spec files, you may not be constantly looking at the file names.
It's my first RoR application.
I want to use this class (app/models/from_db/users/user_base.rb)
module FromDb::Users
class UserBase
include ActiveModel::Serializers::JSON
attr_accessor :Login, :Email
end
end
In this controller (app/controllers/my_controller.rb)
class MyController < ApplicationController
require "from_db/users/user_base"
def default
user = UserBase.new
user.Login = "Marcin"
user.Email = "ja#gmail.com"
end
end
user = UserBase.new throw this error:
uninitialized constant MyController::UserBase
When I put FromDb::Users::UserBase.new everything works fine but I thought that 'require' is like 'using' in C# or 'import' in java. I don't want to have to put this namespace all time before class from other dir. What I am doing wrong?
My second question. Is any way to write require "FromDb/Users/UserBase" instand of require "from_db/users/user_base" ? Now when I put first version (FromDb/Users/UserBase) it throw that error:
cannot load such file -- FromDb/Users/UserBase
I use ruby 2.1.5 and Rails 4.2.1
While require is similar to Java's import, it doesn't have any of the namespace manipulation stuff that import provides. If you really want to have shorter references, you'll need to create them yourself.
class MyController < ApplicationController
UserBase = FromDb::Users::UserBase
def default
user = UserBase.new
# ... etc
end
end
Also, since this is a Rails application, you don't need the explicit call to require (and it's better if you leave it off). If you name everything following the standard conventions, Rails will require the file for you automatically, then reload it whenever the file changes. If you do a manual require you'll lose the autoreloading.
With regards to the first question, try the following to import the namespace
include FromDb::Users
Don't use imports all over the place as they might cause conflicts within your class (see comment by apneadiving).
Or simply create an alias:
FUsers = FromDb::Users
FUsers::UserBase.new...
requirejust loads file's content in memory, so you still have to use FromDb::Users::UserBase and I recommend it, its clearer.
You cant camelize the name: its is meant to be a file name.
You have to give the path from the root, its safer:
require "#{Rails.root}/app/models/from_db/users/user_base"
Notice you dont need require since you have your code in /app
in order to create a shortcut you could do:
def default
user = user_base_class.new
end
def user_base_class
::FromDb::Users::UserBase
end
this way you dont create useless constant.
I have the following in my controller:
class SurveysController < ApplicationController
def index
survey_provider = FluidSurveysProviders::SurveyProvider.new
contact_lists = survey_provider.get_lists()
#survey = Survey.new(contact_lists)
end
And I'm receiving this error:
NameError in SurveysController#index
uninitialized constant SurveysController::FluidSurveysProviders
Excuse my Rails noobiness, I'm sure I'm leaving out something important here. But it seems to me that I am trying to "initialize" the constant with this line:
survey_provider = FluidSurveysProviders::SurveyProvider.new
But that's the same line that's throwing an error because it's not initialized. Where should I be "initializing" the Provider?
Once you require fluid_surveys_providers (or similar) then do this:
include FluidSurveysProviders
Make sure SurveyProvider is wrapped with module FluidSurveysProviders. It may look like this
module FluidSurveysProviders
class SurveyProvider
...
end
end
if its an ActiveRecord object try this
class FluidSurveysProviders::SurveyProvider < ActiveRecord::Base
...
end
The SurveyProvider was not loaded correctly.
For a quick fix, move the class file into app directory, e.g. app/lib/survey_provider.rb. Then all code inside app will be auto-loaded by Rails.
Or make sure the path to class SurveyProvider is included in the autoload_path of Rails. In config/application.rb
config.autoload_paths += %W(#{config.root}/lib) # where lib is directory to survery_provider
If you use Rails 5, be careful that autoload is disabled in production environment. Check this link for more info.