I am in the process of learning how to use Classes, Modules and Namespaces. I am doing some playground stuff by myself and created a user with some permissions.
User.rb
class User
include Permissions
end
u = User.new.set_permissions
Permissions.rb
module Permissions
def set_permissions
p 'Settings permissions'
end
end
I am currently getting this error when I run this User.rb file.
uninitialized constant User::Permissions (NameError)
Why would this be happening? I tried include and require but saw the same error. They are two serpeate files within the same folder. There are no subfolders like lib or anything in this directory.
You need this at the top of user.rb:
require_relative 'permissions'
This will load the code from permissions.rb so that when you call include Permissions, the Permissions module has been defined.
What you can do in that specific case is,
require './permission'
class User
include Permission
def permit
set_permission
end
end
then you can easily call permit on newly created User instance.
User.new.permit
this will let you achieve load and run a module function.
Related
Rails 5.2 here.
I want to test a class defined in app/lib/legacy/export.rb:
# app/lib/legacy/export.rb
module Legacy
class Export
def initialize ; end
end
end
However, a test in test/services/legacy_export_test.rb
# test/services/legacy_export_test.rb
require 'test_helper'
class LegacyExportTest < ActiveSupport::TestCase
test 'can be initialized' do
Legacy::Export.new
end
end
will spit out NameError: uninitialized constant Legacy::Export.
It works well if I put the class definition in app/lib/export.rb (and remove the module definition).
I can also reference this class in Controllers and in the rails console (rails c).
Trying to reference the class starting with the top-level-"namespace" (::Legacy::Export) does not help either. I find answers to questions how to reference lib folders (and subdirectories) in the test/ folder, but this is not what I need.
require 'lib/legacy/export will tell me cannot load such file, as will require 'legacy/export'.
I assumed that the (Auto-)Load-stuff of Rails and MiniTest are the same, but obviously there is some additional configuration to be done.
What has to be done? Where would I find this information?
The problem is that your class namespace / class path doesn't match how Rails autoloading works out of the box.
When you use a class that wasn't previously declared, Rails by default will look on specific paths (defined on config.autoload_paths)
app/controllers
app/controllers/concerns
app/models
app/models/concerns
...
When you use User for the first time, as it's not defined (yet) it will loop over those paths and try to require app/controllers/user.rb, app/controllers/concerns/user.rb, app/models/user.rb, until it founds the User class
if your class is namespaced as Legacy::Export, then it will look for app/models/legacy/export.rb, app/models/concerns/legacy/export.rb, app/controllers/legacy/export.rb, etc.
That's why it can't find your class: Your file is located on app/lib, that's not within the paths Rails use to look for.
There are different solutions:
Option #1
Require the file explicitly. (The Ruby way)
require_relative '../../app/lib/legacy/export'
Option #2
Add app/lib to autoload_path (in config/application.rb)
(The Rails Way)
module YourApp
class Application < Rails::Application
# ...
config.autoload_paths << Rails.root.join("app/lib")
end
end
Option #3
Adapt namespace to match what autoloading expects (instead of changing the configuration)
Example: move you file to something like app/models/legacy/export.rb
I'm working with cucumber/ruby and I wanted to create a new module with some methods to use them in my step definitions.
I was reading how to do this here, https://github.com/cucumber/cucumber/wiki/A-Whole-New-World. But when I've tried the following I get an error:
create the new module under /root_location/lib/new_module.rb
create the module as:
.
module Newmodule
def here
puts "here"
end
end
World(Newmodule)
However, when I then try to use the 'here' method from my steps definition, I just get:
undefined local variable or method `here' for # (NameError)
Any idea what I am doing wrong?
The module needs to be located in features, otherwise it won't be added into World. Cucumber does not look outside of features for anything unless you specifically tell it to.
Put this code either in features/support or features/step_definitions
I'm doing Michael Hart's tutorial and I get the error:
rails_projects/sample_app/app/controllers/application_controller.rb:3:in `<class:ApplicationController>': uninitialized constant ApplicationController::SessionsHelper (NameError)
Here is my application_controller.rb file:
class ApplicationController < ActionController::Base
protect_from_forgery
include SessionsHelper
# Force signout to prevent CSRF attacks
def handle_unverified_request
sign_out
super
end
end
You should have a file in app/helpers named "sessions_helper.rb". Inside of that you should at least have code like:
module SessionsHelper
end
I hope that helps.
Not sure if you got the answer yet, but I was able to comment the sessionhelper line out and get mine to work. I don't know if this has any far-reaching ramifications, but it help me circumvent the issue for now.
Where did you define SessionHelper? If it's at the top level module, try this:
include ::SessionHelper
Change include SessionsHelper to include SessionHelper
remove S
I had this same issue. Make sure you have run the migration once deployed to heroku:
heroku run rake db:migrate
I have a module as following,
main.rb:
module Main
include Dad::Mam
end
and
in dad.rb:
module Dad
module Mam
puts "Mam is saying you are very lazy..."
end
end
How can I name this file? dad.rb is right?
but when running
$ ruby main.rb
I am getting an Error like,
main.rb:2:in <module:Main>': uninitialized constant Main::Dad
(NameError) from main.rb:1:in'
I need to show the sentance inside the puts under Mam module while running ruby main.rb,
I am confused about using ruby's modules, please anyone help me and guide me..
In this case, since you're just writing a simple script, use #require_relative
require_relative 'dad'
module Main
include Dad::Mam
end
For an actual app or library, you would want to manage the load path (a global variable holding an array that tells ruby where to look for files) and then use a normal require
I've found the method set_log in the documentation, I just can't figure out the syntax to call it. Here's what I tried:
require 'ruby-aws'
Amazon::Util::Logging.set_log('my.log')
NoMethodError: undefined method `set_log' for Amazon::Util::Logging:Module
You can see that Amazon::Util::Logging is a module and set_log is a 'Public Instance method'. So you need
class NewClass
include Amazon::Util::Logging
def foo
set_log('file.txt')
log 'debug_message'
end
end
I ran into this problem when trying to deploy a Ruby-on-Rails site that uses 'aws-ruby' to heroku (I got the "Permission denied - ruby-aws.log" error).
To change the log file location from 'ruby-aws.log' to 'log/ruby-aws.log', I added the following to an initializer. Make sure this is called before you use any of the aws-ruby library. Notice the change on the "set_log..." line.
module Amazon
module Util
module Logging
def log( str )
set_log 'log/ruby-aws.log' if ##AmazonLogger.nil?
##AmazonLogger.debug str
end
end
end
end
A simpler way would be to add this line:
set_log("/dev/null")