How to access class variables in included ruby modules? - ruby

I need to know if it is possible for included ruby modules to have access to class variables. Lets say:
require 'bar'
class Foo
#i_am_important
Bar.do_stuff
end
Module Bar
def Bar.do_stuff
#i_am_important.stuff...
end
end
Is there a way to make the above working?
edit: improved example,
edit2: solved problem
I just changed my approach: Bar became a class of its own and gets "i_am_important" passed when initialized. Might not be the best solution, but works at last. Thanks for you help.

You can include module inside the class to get access like
module MyModule
##my_val = 4
end
class MyClass
include MyModule
value = ##my_val
end

Why you want to use variable across the gates of classes and module? I think there is such way:
module Bar
def do_stuff
puts im_am_important
end
end
class Foo
include Bar
def im_am_important
100
end
end
Foo.new.do_stuff # => 100

How about:
#foo.rb
#var
module My_foo
var = #var
def My_foo.my_method(var)
puts(var)
end
end
#bar.rb
require 'foo'
class Bar
extend My_foo
#important_var = "bla"
My_foo.my_method(#important_var)
end
ruby bar.rb => bla

Related

A function that injects a class level function

I write the same function repeatedly in my classes. Is there a way to declare a function once, and just reference the function declaration in each relevant class to have it become part of the class? I want to do something like:
def add_func
expand self.new_func
puts "hello"
end
end
class A
import "add_func"
end
A.new_func
# >> hello world
I'm looking to make a class method, not an instance method, but I'd be interested in knowing how to do both. What is the Ruby construct I am looking for?
You can extend the methods like this:
module SomeModule
def foo
true
end
end
class SomeClass
extend SomeModule
end
SomeClass.foo
You cann package individual methods into their own modules and extend them:
module MyModule
module NewFunc
def new_func
puts "hello"
end
end
end
class A
extend MyModule::NewFunc
end
A.new_func
With some metaprogramming / monkeypatching you could make a way to extend only certain methods of a module, but I think the approach I have shown works good enough.
If you wanted to make it so individual methods can be imported, or you can import all of them, you can do it like so:
module MyModule
module NewFunc
def new_func
puts "hello"
end
end
module NewFunc2
def new_func2
puts "hello2"
end
end
include NewFunc, NewFunc2 # this adds them to MyModule directly
end
class A
extend MyModule
end
A.new_func
A.new_func2

Module and class variable scope in ruby

I am still trying to clearly understand Module/Class/Instance variables ...
My code currently looks something like this ...
module Foo
##var1 ={}
##var2 =[]
##var3 = nil
def m1(value)
##var2 << value
end
def m2(value)
##var1[##var3]=value
end
end
class Bar
include Foo
p ##var1
end
class Bar2
include Foo
p #var1
end
I am trying to create a module that contains a class-wide configuration for how each class will behave. The configuration is stored in ##var1 and ##var2. Using this code the variables are shared across ALL classes that include the module. This is not the desire result, I want each class to have it's own behavior configuration.
I have also tried creating a single class that includes the module and also creates the variables but then the variables are not accessible by the module.
module Foo
def m1(value)
##var2 << value
end
def m2(value)
##var1[##var3]=value
end
end
class T
##var1 ={}
##var2 =[]
##var3 = nil
include foo
end
class Bar < T
p ##var1
end
class Bar2 < T
p #var1
end
I have also read that having modules with class variables is not good coding style but I cannot think of a way to achieve my functionality with this ...
Thanks in advance for any help
Firstly - class variables are evil and should be avoided (because they are also inherited by all subclasses and usually causes more harm than good.
You want to create a class instance variable (not class variable) on a class or module which is including given module. It is easy to do with included method:
module Foo
#default_settings = {}
module ClassMethods
def foo_settings
#foo_settings
end
end
def self.included(target)
target.instance_variable_set('#foo_settings', #default_settings.dup)
target.extend ClassMethods
end
end

How can I refer to a module method without referring to the entire namespace?

I have a module defined as:
module MyApp
module Utility
def Utility.my_method
I want to use that method in several other classes. But I don't want to have to call:
MyApp::Utility.my_method
I would rather just call:
Utility.my_method
Is that reasonable? I've tried include MyApp::Utility and include MyApp to no avail.
Well, just assign any alias you want, e.g.:
ShortNameGoesHere = MyApp::Utility
ShortNameGoesHere.my_method
Here is an example of mixing in my_method to a class:
#myapp.rb
module MyApp
module Utility
def my_method
"called my_method"
end
end
end
#test.rb
require './myapp'
class MyClass
include MyApp::Utility
end
if __FILE__ == $0 then
m = MyClass.new
puts m.my_method
end
It sounds like you want to maintain the namespace of the module on the mixed-in method. I have seen attempts to do so (https://stackoverflow.com/a/7575460/149212) but it seems pretty messy.
If you need my_method to be namespaced, you could simply include a module identifier in the method name:
module MyApp
module Utility
def util_my_method
"called my_method"
end
end
end

How can I modify this class to use the singleton pattern, like activemodel?

I have a httparty "model" which I use like so
myRest = RestModel.new
myRest.someGetResquest()
myRest.somePostRequest()
How would I go about changing it to work similarly to an activemodel, like so?
RestModel.someGetRequest()
RestModel.somePostRequest()
this blog post shows how to include the singleton module but its still accesses the instance like this: RestModel.instance.someGetRequest()
here is my code:
class Managementdb
include HTTParty
base_uri "http://localhost:7001/management/"
def initialise(authToken)
self.authToken = authToken
end
def login()
response = self.class.get("/testLogin")
if response.success?
self.authToken = response["authToken"]
else
# this just raises the net/http response that was raised
raise response.response
end
end
attr_accessor :authToken
...
end
Please tell me that I am doing it all wrong (show me the light)
You want to use extend rather than include, which will add the methods onto the class singleton, rather than making them available on instances.
class Managementdb
extend HTTParty
end
a longer example illustrating this:
module Bar
def hello
"Bar!"
end
end
module Baz
def hello
"Baz!"
end
end
class Foo
include Bar
extend Baz
end
Foo.hello # => "Baz!"
Foo.new.hello # => "Bar!"

How to include/require/load a file in ruby with instance variables

I would like to put a large variable definition in a separate file for the sake of getting it out of the way. I must be doing something wrong though, because my puts call isn't putting anything out.
my_class.rb:
class foobar
def initialize
require 'datafile.rb'
puts #fat_data
end
end
datafile.rb:
#fat_data = [1,2,3,4,5,6,7,8,9,10]
Can you use require this way?
You can do something like this:
my_class.rb:
class Foobar
def initialize
init_fat_data
puts #fat_data
end
end
datafile.rb:
class Foobar
private
def init_fat_data
#fat_data = [1,2,3,4,5,6,7,8,9,10]
end
end
Or, perhaps, change class Foobar in datafile.rb to module MyData and then include the module to Foobar class in my_class.rb.
If you just want to get the data out of the class definition, you could also use __END__ and DATA:
Useless Ruby Tricks: DATA and __END__

Resources