How to Use Define_Method to Create Class Methods

How to define method in class that can only be called from __init__ method

You need to preface do_something(self) with a double underscore. The code is below.

class Test:
def __init__(self):
self.__do_something # Should work

def __do_something(self):
# do something

test = Test()
test.__do_something()

How do I use define_method to create class methods?

I think in Ruby 1.9 you can do this:

class A
define_singleton_method :loudly do |message|
puts message.upcase
end
end

A.loudly "my message"

# >> MY MESSAGE

How to define method of class outside of class?

The lambda way

You example can be done with lambda and =:

class X:
pass

X.add = lambda s: s.a + s.b

The def way

The def keyword won't allow you to assign directly to a class, but you can make a function, assign it, and then delete it. While this isn't what you were hoping for, it is likely the best you can do:

class X:
pass

def add(s):
return s.a + s.b

X.add = add
del add

How to define method of class outside of class?

The lambda way

You example can be done with lambda and =:

class X:
pass

X.add = lambda s: s.a + s.b

The def way

The def keyword won't allow you to assign directly to a class, but you can make a function, assign it, and then delete it. While this isn't what you were hoping for, it is likely the best you can do:

class X:
pass

def add(s):
return s.a + s.b

X.add = add
del add

define_method in a class method

When you encounter seeming conundrums such as this one, try salting your code with puts self statements:

module HashInitialized
puts "self when parsed=#{self}"
def hash_initialized(*fields)
puts "self within hash_initialized=#{self}"
define_method(:initialize) do |h|
missing = fields - h.keys
raise ArgumentError, "Not all fields set: #{missing}" if missing.any?
fields.each { |k| instance_variable_set("@#{k}", h[k]) }
end
private :initialize
end
end
#-> self when parsed=HashInitialized

class Cheese
extend HashInitialized
attr_accessor :color, :odor, :taste
hash_initialized :color, :odor, :taste
end
#-> self within hash_initialized=Cheese

As you see, self is the class Cheese, not Cheese's singleton_class. Hence, the receiver for Module#define_method is Cheese, so the method obligingly creates the instance method initialize on Cheese.

Cheese.instance_methods(false)
#=> [:color, :color=, :odor, :odor=, :taste, :taste=]

initialize is not among the instance methods created on Cheese because I modified the code slightly to make it a private method:

Cheese.private_instance_methods(false)
#=> [:initialize]

I also slightly altered the code that assigns values to the instance variables, and made the type of exception more specific.

If appropriate, you could change your argument test to:

raise ArgumentError, "Fields #{fields} and keys #{h.keys} don't match" if
(fields-h.keys).any? || (h.keys-fields).any?

You may wish to have initialize create the assessors:

module HashInitialized
def hash_initialized(*fields)
define_method(:initialize) do |h|
missing = fields - h.keys
raise ArgumentError, "Not all fields set: #{missing}" if missing.any?
fields.each do |k|
instance_variable_set("@#{k}", h[k])
self.class.singleton_class.send(:attr_accessor, k)
end
end
private :initialize
end
end

class Cheese
extend HashInitialized
hash_initialized :color, :odor, :taste
end

Cheese.new :color=>'blue', odor: 'whew!', taste: "wow!"
=> #<Cheese:0x007f97fa07d2a0 @color="blue", @odor="whew!", @taste="wow!">

Define method in class dynamically

You can override the __setattr__() method to dynamically update the _exec() method depending on the value of attribute a. Two different implementations for _exec() are provided as methods in the class, and the appropriate one is selected whenever the attribute is modified.

Also override __delattr__ in case the attribute is deleted using del.

class TestClass:
def __init__(self, a=None):
self.a = a

def _exec_a(self):
print(self.a)

def _exec_no_a(self):
print('no a')

def __setattr__(self, name, value):
# print('__setattr__():', name, value)
super().__setattr__(name, value)
if name == 'a':
if value is not None:
self._exec = self._exec_a
else:
del self.a

def __delattr__(self, name):
# print('__delattr__():', name)
super().__delattr__(name)
if name == 'a':
self._exec = self._exec_no_a

Use it like this:

>>> x = TestClass()
>>> x.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'TestClass' object has no attribute 'a'

>>> x._exec()
no a
>>> x.a = 123
>>> x._exec()
123
>>> x.a = 'hello'
>>> x._exec()
hello

>>> x.a = None
>>> x.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'TestClass' object has no attribute 'a'
>>> x._exec()
no a
>>> x.a = 500
>>> x._exec()
500
>>> del x.a
>>> x._exec()
no a
>>> x.a = True
>>> x._exec()
True

>>> x = TestClass(a='xyz')
>>> x._exec()
xyz
>>> del x.a
>>> x._exec()
no a

Can't define method in class

To address the errors. Other than you can't define a method within a method.

Syntax error on token "String", new expected

Java syntax is looking for an object declaration like String s = new String().

Result cannot be resolved to a type

Result() is not a defined as a method, so it is trying to be invoked, but can't.

Syntax error, insert ";" to complete Statement

String Result() expects to be ended by a semi-colon.

Void methods cannot return a value

Self-explanatory, you can't do any more than return; in a void method, which main is.


It would appear you meant to do this

import org.springframework.web.client.RestTemplate;

public class GetSurvey {

@Autowired
private RestTemplate restTemplate;

private static String getTemplate(String apiUrl) {
return restTemplate.getForObject(apiUrl,String.class);
}

public static void main(String[] args)
{
int SurveyID = 2107240;
String SurveyDate = "2016-01-07";
String SurveyType;
String apiurl = "https://restapi.surveygizmo.com/v4/survey/" + SurveyID + "...";
String result = getTemplate(apiurl);
}
}

Why does define_method not create a new class method in this example?

Use the Eigenclass

You can define the method as a class method using the eigenclass. For example:

module Helper
def translates(*attributes)
attributes.each do |attribute|
define_singleton_method("find_by_#{attribute}") do |value|
value
end
end
end
end


Related Topics



Leave a reply



Submit