Having a module and class with the same name - ruby-on-rails

I have a module stat that exists in the directory structure: lib/stat_creator/stat/
In lib/stat_creator/stat.rb I have the files in the lib/stat_creator/stat/ directory that I require, as well as:
module StatCreator
module Stat
end
end
When I use that module I refer to the classes as
StatCreator::Stat::Foo.new
Now I want a root Stat class that lives in app. I've made my Stat class in app/models and set it up in routes.rb. But if I go to rails console and try to use the Stat class in app/models like:
Stat.by_user_id("ID")
I get the error: LoadError: Expected ../lib/stat_creator/stat.rb to define Stat
I thought the point of using namespaces was to avoid this kind of conflict, so I don't understand what I"m doing wrong.

I'd do:
::Stat.by_user_id("ID")

Related

Rspec uninitialized constant for class nested inside module - Ruby on Rails

In a Rails project, I have created a new class inside the lib directory, this class is namespaced inside a module. When creating a spec file for it, I'm seeing NameError: uninitialized constant MyNamespace.
Here is my folder structure
app/
...
lib
my_namespace
my_new_class.rb
another_namespace
another_old_class.rb
spec
lib
my_namespace
my_new_class_spec.rb
another_namespace
another_old_class_spec.rb
Here the (abbreviated) contents of:
lib/my_namespace/my_new_class.rb
module MyNamespace
class MyNewClass
end
end
spec/lib/my_namespace/my_new_class_spec.rb
RSpec.describe MyNamespace::MyNewClass do
it "is true"
expect(true).to eq(true) # irrelevant at this point
end
end
The reason I included another_old_class_spec.rb is that its tests run without issue and I can't find anywhere that it's explicitly loaded or required in the test setup (in case that might be a potential issue).
When running the test with bundle exec rspec spec/lib/my_namespace/my_new_class_spec.rb or even bundle exec rspec spec/lib/my_namespace/ I get
An error occurred while loading ./spec/lib/my_namespace/my_new_class_spec.rb
Failure/Error:
RSpec.describe MyNamespace::MyNewClass do
NameError:
uninitialized constant MyNamespace
Like Georgiy Melnikov implied in his comment, by default the /lib directory is not in autoload paths, so the constant MyNamespace is not automatically resolved.
You basically have two options to fix this:
explicitly require the file with require lib/my_namespace/my_new_class at the top of the spec file
add lib/ to autoload paths (nowadays this is discouraged)

Why lua require won't search current directory?

say I've two files test.lua and m.lua in a folder, in test.lua as:
require("m")
then I run this file, howerver it raise an error:
lua: /Users/xx/works/scripts/test.lua:43: module 'm' not found:
no field package.preload['m']
no file '/usr/local/share/lua/5.3/m.lua'
no file '/usr/local/share/lua/5.3/m/init.lua'
no file '/usr/local/lib/lua/5.3/m.lua'
no file '/usr/local/lib/lua/5.3/m/init.lua'
no file './m.lua'
no file './m/init.lua'
no file '/usr/local/lib/lua/5.3/m.so'
no file '/usr/local/lib/lua/5.3/loadall.so'
no file './m.so'
As you can see the line no file './m.lua' appears but this is not true. ./m.lua exists, and file permission stuff is OK. If I hardcode the path:
package.path = package.path..';'..'/Users/xx/works/scripts/?.lua'
require('m')
It will work as expected.
What should I do to make lua search current directory fisrt (like python's import) when require a module
The current directory is the directory where you launch lua from.
The command line is missing in your example, if you used lua test.lua then it shoud work, if you used lua works/scripts/test.lua then it will not work.

How To Require Lua Socket?

I'm very new to lua development with file manipulation, and now trying to import the lua socket package into my project according to this post, but I can't run even the code below.
I guess the error message indicates I need to import not only the socket.lua but also .\socket\core (probably .dll, since it doesn't have core.lua), while a reply at the post suggested importing only the file.
I'm stuck in just the beginning... What do I have to do for the next step?
local function main()
local socket = require("socket")
end
main()
Exception in thread "main" com.naef.jnlua.LuaRuntimeException: ...n32.win32.x86_64\workspace\TestForCiv\src\socket.lua:13: module 'socket.core' not found:
no field package.preload['socket.core']
no file '.\socket\core.lua'
no file 'C:\Program Files\Java\jre1.8.0_151\bin\lua\socket\core.lua'
no file 'C:\Program Files\Java\jre1.8.0_151\bin\lua\socket\core\init.lua'
...(a bunch of no file errors continues)
Edit: I added the folder structure. Even I add the .dll file it returns the same error.
I don't know the details of you configuration, but try this
require ("src.socket")
you should require a module from the root path of the lib

RoR autoload sub directories

I have created a "services" dir in app/ where I have created some classes (services). Now it's looks like this :
-app
-services
-class1
-class2
-class3
-class4
For now, I have added app/services in config/spring.rb
%w(
.ruby-version
.rbenv-vars
tmp/restart.txt
tmp/caching-dev.txt
app/services
app/errors
).each { |path| Spring.watch(path) }
So my classes in services are loaded.
But now, I want to do this :
-app
-services
-dir1
-class1
-class2
-dir2
-class3
-class4
I got error :
uninitialized constant TransactionService::AuthorizeRequest
How autoload a dir and subdir ?
Rails tries to guess namespaces by dirnames & filenames. So, to have a TransactionService::AuthorizeRequest class name, you should have the exact following structure:
app
- services
-- transaction_service
--- authorize_request.rb
Your class sould looks like :
module TransactionService
class AuthorizeRequest
end
end

Rails same file name for different classes

Having model Price (models/price.rb)
class Price
end
Also in lib directory I have import/detector/price.rb file
class Import::Detector::Price
end
Lib directory added to autoload paths via
config.autoload_paths += Dir["#{config.root}/lib/**/"]
So running Price.new I get error
Unable to autoload constant Price, expected lib/import/detector/price.rb to define it.
Import::Detector::Price.new is ok
What was my mistake?
UPD.
The most interesting
Also having this file models/car/property/price.rb
class Car::Property::Price
end
And everything ok with it. Car::Property::Price is available.
Try
config.autoload_paths += Dir["#{config.root}/lib"]
instead of
config.autoload_paths += Dir["#{config.root}/lib/**/"]
Using **, Dir will return every directory under lib and will put them all (as root directories) in the load path. It should only be the main lib directory in the load path as rails will work out the subdirectories using the namespace.
Rails autoloading — how it works, and when it doesn't

Resources