In my lib folder I have billede.rb:
class Billede
require 'RMagick'
#some code that creates a watermark for a image
image.write(out)
end
How do I call/activate the class? Is the only way to change it to a Rake task?
You can't call a class directly. You have to call a method on that class. For example:
class Billede
def self.foobar
# some kind of code here...
end
end
Then you can call it via Billede.foobar
Perhaps you should read some documentation on basic ruby syntax before trying to do more complex things (such as manipulating images w/ Rmagick).
Code 'inside a class' is run just like any other code. If you have a Ruby file like this:
puts "Hello from #{self}"
class Foo
puts "Hello from #{self}"
end
and you run the file (either via ruby foo.rb on the command line or require "./foo" or load "foo.rb" in a script) it then you will see the output:
Hello from main
Hello from Foo
If you want to load a utility that 'does something' that you can then invoke from a REPL like IRB or the Rails console, then do this:
module MyStuff
def self.do_it
# your code here
end
end
You can require "./mystuff" to load the code, and when you're ready to run it type MyStuff.do_it
And, as you may guess, you can also create methods that accept arguments.
If you want to define a file that can be included in others (with no immediate side effects) but which also "does its thing" whenever the file is run by itself, you can do this:
module MyStuff
def self.run!
# Go
end
end
MyStuff.run! if __FILE__==$0
Now if you require or load this file the run! method won't be invoked, but if you type ruby mystuff.rb from the command line it will.
# in /lib/billede.rb
class Billede
def self.do_something(arg)
# ...
end
def do_anotherthing(arg)
# ...
end
end
# inside a model or controller
require 'billede'
Billede::do_something("arg")
# or
billede_instance = Billede.new
billede_instance.do_anotherthing("arg")
Related
I have a simple file called helper.rb that looks like this:
module MyHelper
def initialize_helper
puts "Initialized"
end
initialize_helper()
end
And another simple file like this:
require_relative 'helper.rb'
include MyHelper
puts "Done"
But when I run this second file, it results in this error:
helper.rb:6:in `<module:MyHelper>': undefined method `initialize_helper' for MyHelper:Module (NoMethodError)
Why can't Ruby find this initializeHelper method defined directly above where I'm calling it???
Try
def self.initialize_helper
puts "Initialized"
end
Without the self., you're declaring an instance method intended to be called on objects, not the module itself. So, for instance, your original code is intended to be used like
module MyHelper
def initialize_helper
puts "Initialized"
end
end
class Foo
include MyHelper
end
Foo.new.initialize_helper
But if you want to call it on the module, you need to have self. in front of it to make it a method on the module itself.
I have a file SomethingClass.rb which looks as follows:
class SomethingClass
def initialize
puts "Hello World"
end
end
I would like to require the file SomethingClass.rb, and make SomethingClass part of the module SomethingModule without changing the file.
Also, I would like to avoid making SomethingClass part of the namespace outside of that module at all. In other words, I want to require the file and the rest of my application should not change apart from the fact that SomethingModule will be defined.
This does not work (I assume because require is executed in Kernel scope):
module SomethingModule
require './SomethingClass.rb'
end
Is this possible in Ruby?
Without changing your class file, from what I've gathered, there are only kind of hacky ways to do this - see Load Ruby gem into a user-defined namespace and How to undefine class in Ruby?.
However I think if you allow yourself to modify the class file, it is a little easier. Probably the simplest thing to do would be to set the original class name to something that will surely have no name conflict, e.g.:
class PrivateSomethingClass
def initialize
puts "Hello World"
end
end
module SomethingModule
SomethingClass = PrivateSomethingClass
end
Now you have SomethingModule::SomethingClass defined but not SomethingClass on the global namespace.
Another way to do it would be to use a factory method and anonymous class:
class SomethingClassFactory
def self.build
Class.new do
def initialize
"hello world"
end
end
end
end
module SomethingModule
SomethingClass = SomethingClassFactory.build
end
I tried running my code in a Ruby script from my terminal. Nothing happens when I run
ruby Main.rb.
# Main.rb
module Main
class MyClass
def initialize
puts "Hello World"
end
end
end
You need to instantiate your class first, as your puts command will not execute until you invoke MyClass#new. For example:
module Main
class MyClass
def initialize
puts "Hello World"
end
end
end
Main::MyClass.new
Hello World
=> #<Main::MyClass:0x007f9d92144308>
Because it's loading the Module and then doing nothing with it. It never gets instantiated (initialized), only defined.
You define the module like so:
module Main
class MyClass
def initialize
puts "Hello World"
end
end
end
And then initialize it by making a new MyClass object. (On the end of the same file)
test = Main::MyClass.new
Hello World
=> #<Main::MyClass:0x2979b88>
You can handle this in an even better way by only doing this when you run the file directly, not when it's loaded from another ruby file.
if __FILE__ == $0
test = Main::MyClass.new
puts test
end
This way you can do whatever you like when the code is run directly, for example, testing, but just load the module silently every other time.
When running the file directly, it will work as above, but when running this in IRB, you'll only see the following:
=> nil
Having the following files:
# ./app.rb
require_relative 'container'
require_relative 'contained'
# ./container.rb
class Foo
def initialize &block
puts block.call
end
end
# ./contained.rb
Foo.new do
"Hello, world!"
end
We can test and see everything's okay from a console:
$ ruby ./app.rb
Hello, world!
But I would like to simplify contained.rb by removing Foo.new do and end, keeping just the content of the block, by modifying app.rb.
In this quest, I came to this result:
# ./app.rb
require_relative 'container'
require_relative 'contained'
Foo.new do
eval File.open('contained.rb').read
end
# ./container.rb
class Foo
def initialize &block
puts block.call
end
end
# ./contained.rb
"Hello, world!"
With the same result:
$ ruby ./app.rb
Hello, world!
However I am not very proud of this code, mostly because of the eval method. Is there a best practice in this kind of case? What would you do?
Thanks for sharing your light.
The fact that you want to read from a separate file must be that you want to separate it from the main code and you want to occasionally change it. That category of things belongs to what would be called configuration. It is common these days to write that as a YAML file and read into Ruby using a yaml library.
I have a hierarchy like
ABC(Folder) ----> abc.rb, def.rb
DEF(Folder) ----> a1.rb, b1.rb
GHI(Folder) ----> x1.rb, y1.rb
I want to inherit/include def.rb, which is a module into abc.rb and then a1 should inherit abc.rb and should be able to access all methods defined in def.rb.
Right now, I am including def.rb in every script file, but I don't want to do this. I just want to inherit vertically.
It's hard to deal with ABC-like naming system )
If you want to include 10 modules in each of your classes, you can do it this way. Let's imagine you have modules ModuleTest::Files and ModuleTest::Network:
in module_test/network.rb
module ModuleTest
module Network
def network
puts 'hello from ModuleTest::Network#network'
end
end
end
in module_test/files.rb
module ModuleTest
module Files
def files
puts 'hello from ModuleTest::Files#files'
end
end
end
You can make some ModuleTest::Base class like this:
require 'module_test/files'
require 'module_test/network'
module ModuleTest
class Base
include Files
include Network
end
end
This class includes all the functionality you have, so inherit your classes from it:
require 'module_test/base'
class Foo < ModuleTest::Base
end
foo = Foo.new
foo.network
foo.files
Output:
>ruby -I. foo.rb
hello from ModuleTest::Network#network
hello from ModuleTest::Files#files
Let my first point out that I suspect that I'm misinterpreting your question, because I can't see why you'd want to do this. So if that's the case, please point it out and I'll delete this.
The process you describe works (at least for me in Ruby 1.9.3).
module Def
def method_from_def
puts "Method from Def"
end
end
class Abc
include Abc
end
class X < Abc
end
X.new.method_from_def #=> "Method from Def"
You might need to be a little specific in your require statements, but if you're already able to 'include' the script you've already got that down. (Unless by 'include' you mean copy and paste it into the source file.)