I'm trying to understand the folder structure I need to create to meet the below gem requirements:
I'm using this gem sidekiq-sequence and as part of it you need to create a Sequence class.. Like so:
class TestSequence < Sidekiq::Sequence::Base
step First
step Second
end
And then those workers First and Second need to be a subclass of the TestSequence class.. Like so:
class TestSequence::First
include Sidekiq::Sequence::Worker
def perform
# Perform your job
end
end
My question is, is how to create the file structure for this? Do I need to create a file AND a folder in my workers directory named TestSequence ?
Would it be:
app/workers/test_sequence.rb
app/workers/test_sequence/first.rb
Short answer is yes, I needed to create a file and a folder with the same name. The folder structure I needed was this:
app/workers/test_sequence.rb
app/workers/test_sequence/first.rb
In order for this to work:
class TestSequence < Sidekiq::Sequence::Base
step First
step Second
end
And this:
class TestSequence::First
include Sidekiq::Sequence::Worker
def perform
# Perform your job
end
end
Related
I need to call model inside rack_attack.rb file to check ip is blocklisted or not any idea how to do that?
/config/initializer/rack_atack.rb
As long as your migrations were already executed and the table for the model in question already exists, I believe you will be able to call your model from the initializer file as usual: Model.method().
If you want to check if the table exists, you could do like this:
if ActiveRecord::Base.connection.table_exists? :settings
Model.method()
end
Finally, if you want to make sure all other initializers have run before running this one, you could add the following code to your initializer:
# config/initializers/rack_attack.rb
Rails.configuration.after_initialize do
Model.method()
end
Greetings to everyone.
This question is the continuation of a previous one :
Is it possible to extend a class by using a string as a module ? - Ruby 2.7.1
So here it is. I am currently doing some tests with Ruby 2.7.1 on my FreeBSD 12.1 workstation. My objective is to find a way to load all the script within a directory. These scripts are modules with predictable names. For instance, if I got a script named mymodule.rb, it will contain a module named : Mymodule and a method : mymodule. So I can make a list of all scripts within a directory by using an Array. I can use that list to load/require all my script files easily. And with the help of some .sub, .chop or .capitalize, I can can extract what I need from each index of my array. But the result of this operation is always a String. The problem is that I cannot execute a method with a String. Previously I was having problem with extending my main class with module name from a String, but answers were given and solved this little issue. Here is my main class :
load "mymodule.rb"
class Myclass
def mymethod
var1 = "Mymodule"
extend self.class.const_get(var1)
var2 = "mymodule"
#I need something here to call the method from the module.
#puts #varmod
end
end
a = Myclass.new
a.mymethod
and here is my module :
module Mymodule
def mymodule
#varmod = "TEST"
end
end
So, I would like to know if there is a way to execute the method within Mymodule the same fashion we did with "extend self.class.const_get(var1)".
Thanks in advance for your responses !
In order to send a message with a name that is not statically known at design time, you can use the Object#public_send method:
public_send(var2)
It is not necessary to use Object#send in this case, since your methods are not private.
I think it is the send method your are looking for. The following should work:
send(var2)
I have some rb files, all with the same structure:
class RandomName < FooBar
end
The randomname is a random class name which changes in each rb file but all inherits from Foobar.
how i can load all randomclass from there rb files?
I think there are 2 parts to the solution:
How to dynamically instantiate a class
a. Using String#constantize from ActiveSupport
klass = "SomeNamespace::SomeClassName".constantize
klass.new
b. Use Module#const_get (which doesn't handle namespaces)
klass = const_get(:SomeClassName)
klass.new
How to detect a class name
A convention followed widely in ruby is to name the file after the class that it contains, so random_name.rb would contain the RandomName class. If you follow this convention, then you could do something like:
Dir["/path/to/directory/*.rb"].each do |file|
require file
file_name = File.basename(file.path, '.rb')
# using ActiveSupport for camelcase and constantize
file_name.camelcase.constantize.new
end
I think you should explain what you are trying to accomplish. The approach you are taking seems unconventional and there may be a much more effective way of reaching your goal without doing all this loading of files and dynamic instantiation of classes with random names.
Remember, just because ruby lets you do something, it doesn't mean it's a good idea to actually do it!
you can define a method called inherited in the FooBar class. look here
class FooBar
def self.inherited(subclass)
puts "New subclass: #{subclass}"
end
end
Every time a subclass is created, you will get it in the callback. Then you can do whatever you want with all those subclasses.
I have a similar requirement, passing a class name in as a string. One trick with require is that it doesn't have to be at the start, so I prefer to only load the class I need.
I used eval because it doesn't have any Rails dependencies (I'm writing pure Ruby code here).
The following relies on convention (that the Class is in a file of the same name), but if you do know the class and file, this approach has the advantage of not requiring every file in a directory and only dynamically loading the one you need at the time you need it.
klass = "classname"
begin
# Load the file containing the class from same directory I'm executing in
require_relative klass # Or pass a local directory like "lib/#{klass}"
# Use eval to convert that string to a Constant (also capitalize it first)
k = eval(klass.capitalize).new
rescue
# Do something if the convention fails and class cannot be instantiated.
end
k.foo # Go ahead and start doing things with your new class.
I'm developing two Ruby gems, one is a framework, the other is an application.
My main app's class inherits from a framework's class.
The class defined in the framework have some file loading methods that rely on _____FILE_____ so subclasses can load resources relative to their path.
What I want is for the subclasses to be able to use those methods defined in the parent without (basically) touching them. Is it possible?
The problem is with _____FILE_____, it doesn't change if the code is called from a subclass, so the loading resource methods are "stuck" in the frameworks directory, instead of trying to load from the app dirs.
I know I can redefine those methods in the subclass, but I wanted to take advantage of them being already defined in the parent.
I want the subclasses to refer to their own directory (where the subclass file is) using a method defined in the parent, that's the problem.
Or do I have to set the app directory by hand?
I'll try to make that clearer:
Is it possible to write a method like this:
# /home/usr/framework/parent.rb
class Parent
def show_my_path
puts File.dirname(__FILE__)
end
end
# /home/usr/app/app.rb
# require Parent
class App < Parent
end
App.new.show_my_path
# Can we have here /home/usr/app
# instead of /home/usr/framework ?
# What's the right way to do this?
As We know that __FILE__ will have current file name whatever it is. so you can try this -
# /home/usr/framework/parent.rb
class Parent
def show_my_path(filename)
puts File.dirname(filename)
end
end
# /home/usr/app/app.rb
# require Parent
class App < Parent
end
App.new.show_my_path(__FILE__)
What say?
__FILE__ is transform during the code read. So it can't be change. Even in a proc.
You can try to extract information with caller method maybe.
I am a starter with ruby, I searched that if someone else has asked similar question but was not able to find any. so I am asking it here.
I am trying my hand at modules in ruby.
I created a folder Project
inside Project folder, created a class One
class Project::One
include Project::Rest
end
inside Project folder, created a module Rest
module Project::Rest
def display
puts "in display"
end
end
but when I try to run the program(ruby one.rb) I get the
uninitialized constant Project (NameError)
Please help me
The problem is that you never actually define the Project constant. You have to define it before you can use it. Example:
# root.rb
module Project
end
require "project/test"
# project/test.rb
class Project::Test
end
You should then be able to run ruby root.rb. Another approach is to state the module in the namespace.
# root.rb
require "project/test"
# project/test.rb
module Project
class Test
end
end
With this example, you are able to run ruby project/test.rb as well, since the Project module is defined in that file.
And if you have multiple files defining the Project module, that's not a problem either. It won't be re-defined, it will always be the same module.
Both of these methods will define the Project module. Simply going Project::Test will not, however, define the module.
As a sidenote, Rails has a auto loader. If you're in a rails app, and use a certain folder structure, these kind of intermediate modules will be defined for you. Without Rails, though, you have to define them yourself.
The issue is that you're not nesting your classes/modules correctly. You have to declare a module with the module keyword, not merely by writing class Project::Class. Assuming you have this structure:
Project/
one.rb
rest.rb
then your files should look something like this:
# one.rb
require 'rest'
module Project
class One
include Project::Rest
end
end
# rest.rb
module Project
module Rest
def display
puts 'in display'
end
end
end
Note how the modules are nested in these examples.
If you have code in multiple files, you have to load those files before you can access what's in them. This is usually done with a require statement. I think what you want to do should look like this:
# one.rb
require 'rest'
module Project
class One
include Rest
end
end
# rest.rb
module Project
module Rest
def display
puts "in display"
end
end
end