What is going wrong here? The case of the noob not understanding initialize

Notice the initialization of both classes in each of the examples, if
the instance variable is in initialization or in the called method is
the only thing changing between these examples.

I don’t understand why I can’t begin both classes with the
initialization
set to what I want it to be, I would think that the initialization value
would be consistent for the objects entire life but it only works for
the first pass, the second time through it doesn’t work. The only way to
fix this is to not have the respective instance variable set in
initialization with either of the two classes. What is going wrong here?
I like to set variables during initialization but it clearly doesn’t
work how I would hope, I would like to understand what is going wrong
because even though I can get it to work I don’t see why it doesn’t work
in some cases.

Maybe it has to do with my poor use of instance variables :/, if this is
the case I would still like to know what is going on so I can find a way
to work around it

when I say it doesn’t work I mean the output is not correct, it gives me
random looking output the second time even though it should give the
plaintext.

Also notice that I reset @cipher. I thought that by resetting @cipher it
would make it so I essentially AM calling a new object because the
entire objects state should be reset to what it was prior to when I
called it, all of the other variables in EncryptionBackend should be
reset when it is called the second time because it is passed a new
plaintext and a new key which should replace what was there before
without needing to make a new object…so why on earth doesn’t it
work ahhh.

###############This way doesn’t work##################

class EncryptionBackend
require ‘openssl’

def initialize
@cipher = OpenSSL::Cipher::Cipher.new(“AES-256-CTR”)
end

def encrypt(key, plaintext)
puts plaintext
@cipher.encrypt
@cipher.key = key
ciphertext = @cipher.update(plaintext)
ciphertext << @cipher.final
@cipher.reset
puts ciphertext
@ciphertext = ciphertext

end
end

class EncryptMessage
require ‘openssl’

def initialize
@crypto = EncryptionBackend.new
end

def twice
@message = “whatever”
encrypt_message
encrypt_message

end

def encrypt_message
@sha256 = OpenSSL::Digest::SHA256.new
key = @sha256.digest(“whatever”)
@message = @crypto.encrypt(key, @message)
end
end

message_encrypt = EncryptMessage.new
message_encrypt.twice

###############This way does work###################

class EncryptionBackend
require ‘openssl’

def initialize
@cipher = OpenSSL::Cipher::Cipher.new(“AES-256-CTR”)
end

def encrypt(key, plaintext)
puts plaintext
@cipher.encrypt
@cipher.key = key
ciphertext = @cipher.update(plaintext)
ciphertext << @cipher.final
@cipher.reset
puts ciphertext
@ciphertext = ciphertext

end
end

class EncryptMessage
require ‘openssl’

def initialize
#nothing
end

def twice
@message = “whatever”
encrypt_message
encrypt_message

end

def encrypt_message
@crypto = EncryptionBackend.new
@sha256 = OpenSSL::Digest::SHA256.new
key = @sha256.digest(“whatever”)
@message = @crypto.encrypt(key, @message)
end
end

message_encrypt = EncryptMessage.new
message_encrypt.twice

###############this way also works though##################

class EncryptionBackend
require ‘openssl’

def initialize
#nothing
end

def encrypt(key, plaintext)
@cipher = OpenSSL::Cipher::Cipher.new(“AES-256-CTR”)
puts plaintext
@cipher.encrypt
@cipher.key = key
ciphertext = @cipher.update(plaintext)
ciphertext << @cipher.final
@cipher.reset
puts ciphertext
@ciphertext = ciphertext

end
end

class EncryptMessage
require ‘openssl’

def initialize
@crypto = EncryptionBackend.new
end

def twice
@message = “whatever”
encrypt_message
encrypt_message

end

def encrypt_message
@sha256 = OpenSSL::Digest::SHA256.new
key = @sha256.digest(“whatever”)
@message = @crypto.encrypt(key, @message)
end
end

message_encrypt = EncryptMessage.new
message_encrypt.twice

Hi,

What’s your Ruby version? If you actually get different output for the
three variants (which you shouldn’t), then this might be a bug in the
OpenSSL class.

You should note, however, that your code will do the following: It takes
the string “whatever” as the plaintext, encrypts it, then takes the
encrypted string as the plaintext and encrypts it again.

So your output will be something like

whatever (first plaintext)
ABC (encryped “whatever”)
ABC (second plaintext = encrypted “whatever”)
XYZ (encrypted ABC)

If that’s not what you want, then you have to change your code. This
might be a good idea, anyway. You seem to be confused about when to use
instance variables, because most of them simply don’t make any sense.

In the first class, you create the instance variable @ciphertext in the
encrypt method, but you use it nowhere. Then what do you need it for? In
the second class, you have the @sha256 variable, but you overwrite it on
every method call. This makes no sense. A local variable is what you
want.

Use instance variables only if you actually want to store a value
persistently inside the object. Do not use them to pass values to
methods or whatever.

How do I iterate through a Class so that I can perform some action on
each object? For example…

MyClass.each do {|obj| DO SOME STUFF}

It looks like I have to create the .each method in my class. I tried
something like what’s mentioned here…
http://stackoverflow.com/questions/2080007/how-do-i-add-each-method-to-ruby-object-or-should-i-extend-array

…but haven’t gotten it to work.

Matt

do you want to find all objects that belong to that class? you need to
use ObjectSpace for that:

ObjectSpace.each_object(classname) {|obj| do something}

the .each method in your class is for individual objects to provide
internal iterators (e.g. if you’re implementing a collection class)

martin

Matt M. wrote in post #1061049:

How do I iterate through a Class so that I can perform some action on
each object? For example…

Please create your own thread. This has nothing to do with this topic.

Yup that worked…

Thanks,
Matt

----- Original Message -----
From: “Martin DeMello” [email protected]
To: “ruby-talk ML” [email protected]
Sent: Wednesday, May 16, 2012 4:25:08 PM
Subject: Re: How to Iterate Through a Class

do you want to find all objects that belong to that class? you need to
use ObjectSpace for that:

ObjectSpace.each_object(classname) {|obj| do something}

the .each method in your class is for individual objects to provide
internal iterators (e.g. if you’re implementing a collection class)

martin

I used an instance variable for @ciphertext because I was getting it
with @crypt.instance_variable_get("@ciphertext") but then I realized I
can do it in a much nicer way.

Yes I can confirm that the way I originally said does not work doesn’t
work, I am using ruby 1.9.3p125 on Ubuntu 64 bit

the first way outputs this

whatever
�a�xtT��
�a�xtT��
�G��E

the other two ways both output this, which is what I expect (note that
counter mode is used and the key is the same for both passes, so the
second pass decrypts what the first pass encrypts)

whatever
�a�xtT��
�a�xtT��
whatever

can you please confirm that each version works correctly for you on your
version of ruby, simply by copy pasting it ? Particularly interested in
the version I have listed as not working.

edit: also in my full program I set @sha256 in initialize and then reset
it through a lot of methods, but in this case a local variable would
certainly be best

irb(main):001:0> require ‘openssl’
=> true
irb(main):002:0> message = “whatever”
=> “whatever”
irb(main):003:0> @sha256 = OpenSSL::Digest::SHA256.new
=> #<OpenSSL::Digest::SHA256:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855>
irb(main):004:0> @cipher = OpenSSL::Cipher::Cipher.new(“AES-256-CTR”)
=> #OpenSSL::Cipher::Cipher:0x00000002467830
irb(main):005:0> 2.times do
irb(main):006:1* key = @sha256.digest(“whatever”)
irb(main):007:1> @sha256.reset
irb(main):008:1> @cipher.encrypt
irb(main):009:1> @cipher.key = key
irb(main):010:1> ciphertext = @cipher.update(message)
irb(main):011:1> ciphertext << @cipher.final
irb(main):012:1> @cipher.reset
irb(main):013:1> puts ciphertext
irb(main):014:1> end
�a�xtT��
9]K���/
=> 2

okay the problem is that .reset is not actually reseting the ciphers
state as shown here:

require ‘openssl’

message = “whatever”
@sha256 = OpenSSL::Digest::SHA256.new
@cipher = OpenSSL::Cipher::Cipher.new(“AES-256-CTR”)

2.times do
key = @sha256.digest(“whatever”)
@sha256.reset
@cipher.encrypt
@cipher.key = key
ciphertext = @cipher.update(message)
ciphertext << @cipher.final
@cipher.reset
puts ciphertext
end

#> �a�xtT��
#> 9]K���/

would love if someone can confirm this bug and please get it fixed ASAP
thanks :slight_smile:

roob noob wrote in post #1061056:

I used an instance variable for @ciphertext because I was getting it
with @crypt.instance_variable_get("@ciphertext") but then I realized I
can do it in a much nicer way.

The method should simply return the encrypted string and do nothing
else. Like I said earlier: Don’t misuse instance variables to pass
values around. This is not only ugly and cumbersome but also prone to
error, because the method then becomes dependend on some outer
variables. What if the value is accidently changed by another method?
This will break your code, and you’ll have a hard time finding the
reason.

We’ve already discussed this in an earlier thread:
http://www.ruby-forum.com/topic/4246662#new

I don’t know how you’ve come to adept this programming style, but you
should get rid of it right away. This also applies to the
“instance_variable_get”. While this does work, it’s very bad style and
more of a hack. Outer objects are supposed to use the getters and
setters and not fumble with the actual variables inside the object.

can you please confirm that each version works correctly for you on your
version of ruby, simply by copy pasting it ? Particularly interested in
the version I have listed as not working.

Sorry, I can’t help you with that, because I can’t get the CTR mode
working.

edit: also in my full program I set @sha256 in initialize and then reset
it through a lot of methods, but in this case a local variable would
certainly be best

Well, a local variable is not only “better” in this case. It’s the only
right way to do this. Using an instance variable doesn’t make any sense,
because you don’t want the SHA256 object to be a property of the object.

roob noob wrote in post #1061072:

use OFB instead of CTR please you need the cutting edge version of
OpenSSL for CTR to work

OFB gives me the right output for all three variants:

whatever
�a�xtT��
�a�xtT��
whatever

the method is always dependent on outer variables regardless of if
they are passed with @ or with ().

No, without the instance variables, the method will always return the
same value for the same arguments. Its behaviour doesn’t depend on outer
variables.

Compare these two methods:

$z = 10
def add(x, y)
x + y
end
def add2(x, y)
x + y + $z
end

The first method doesn’t use instance variables. add(1, 1) will always
return 2, no matter how the outer world looks like. But add2(1, 1) may
yield different results, depending on the value of $z.

Another important difference is that “() methods” have a clean
interface: all input comes from the arguments, and all output is in the
return value. There are no “magical” values from the outside involved.
This is much easier to track and test, especially if you haven’t written
the code yourself.

I do agree that
.instance_variable_get() is ugly though and I am going through my code
and removing it where possible, making the called methods end on what I
want to get from them. In some cases I need to get multiple instance
variables though, maybe I should split it up into many smaller methods
in these cases? How else am I supposed to get multiple instance
variables from a method in one class to a method in another class?

Methods can also return hashes or arrays. This way you can pass multiple
values.

For example:

this methods calculates the minimum, maximum and average

of a list of numbers

def min_max_avg(values)
{
min: values.min,
max: values.max,
avg: values.reduce(:+).to_f/values.length
}
end

I can’t use () in these cases without greatly decreasing the flexibility
of my code, since () assumes that I have a class/method to send the
resulting variables to and .instance_variable_get() only assumes that I
have the variables to get. What if in some cases I want the resulting
variables to go one place and in other cases I want them to go somewhere
else? “Pulling” from the calling method with .instance_variable_get
makes more sense than “pushing” from the called method with () in these
cases.

I do understand the purpose of this idea, and it may even be technically
efficient. But it’s still bad style, because how the methods works is
obscure. Imagine you’re a programmer using this code from somebody else.
What do you find easier to use:

“encrypt(message) returns the AES-256 encryption of message”

or

“Set the @message variable in an instance of Encrypt and call the
encrypt() method. After this, get the result from the @ciphertext
variable. Be careful not to change the variables in between.”

By the way, you shouldn’t use “instance_variable_get” at all. This is
simply the wrong method for your purpose. Define getter methods for the
variables (via attr_reader) and call them.

use OFB instead of CTR please you need the cutting edge version of
OpenSSL for CTR to work

the method is always dependent on outer variables regardless of if
they are passed with @ or with (). I do agree that
.instance_variable_get() is ugly though and I am going through my code
and removing it where possible, making the called methods end on what I
want to get from them. In some cases I need to get multiple instance
variables though, maybe I should split it up into many smaller methods
in these cases? How else am I supposed to get multiple instance
variables from a method in one class to a method in another class?

I can’t use () in these cases without greatly decreasing the flexibility
of my code, since () assumes that I have a class/method to send the
resulting variables to and .instance_variable_get() only assumes that I
have the variables to get. What if in some cases I want the resulting
variables to go one place and in other cases I want them to go somewhere
else? “Pulling” from the calling method with .instance_variable_get
makes more sense than “pushing” from the called method with () in these
cases.

I am still a noob. :<

I guess I could do this though, to make it a more fair comparison.

class AddNumbersAndLetters

def get_input
  input = gets.chop
  add_numbers(input)
end

 def add_numbers(input)
   input += "123"
   add_letters(input)
 end

 def add_letters(input)
    input += "abc"
 end

end

However now I still am stuck on how to add numbers and then letters and
then numbers and then letters again. With @ it allows me to jump all
over the class to as many methods I want in whichever order I want, from
a ‘controller’ method (get_input in this case).

class AddNumbersAndLetters

def get_input
  @input = gets.chop
  add_numbers
  add_letters
  add_numbers
  add_numbers
  add_letters
end

 def add_numbers
   @input += "123"
 end

 def add_letters
    @input += "abc"
 end

end

How can I do that while passing with ()? It seems like () only has
‘downward movement’ but @ lets me move all over the place.

Honestly I see very little difference between

"
message = “whatever”
encrypt(message) #returns the AES-256 encryption of message
"

and

"
@message
encrypt #returns the AES-256 encryption of @message
"

except that with an instance variable I can pass the value seamlessly to
where it needs to go without sending it down the call chain and keeping
track of a bunch of variables and changes to the variable.

class AddNumbersAndLetters

def get_input
  input = gets.chop
  add_numbers(input)
end

 def add_numbers(input)
   numbers_added = input + "123"
   add_letters(numbers_added)
 end

 def add_letters(input)
    letters_added = input + "abc"
 end

end

does not look as nice to me as

class AddNumbersAndLetters

def get_input
  @input = gets.chop
  add_numbers
  add_letters
end

 def add_numbers
   @input += "123"
 end

 def add_letters
    @input += "abc"
 end

end

Look how much more stuff you need to keep in your head and keep track of
with the first method versus the second method. And this is just a
simple example. If there are a lot more methods involved I would
need to keep passing input down the call chain with ().

Imagine if I want to add numbers and then add letters and then add
numbers again and then add letters again, which just becomes a mess
passing with () but with @ it is as simply as doing this

add_numbers
add_letters
add_numbers
add_letters

However, enough Rubyists have told me to avoid using instance variables
in this way that I will take your advice. I don’t personally think it is
intuitive to use (), or that it makes it easier though.

The only way I see the first way as having an advantage is if I want to
add numbers or letters to something that is in another class, but my
classes tend to be very purpose specific, this code isn’t a good
example, but in many of my classes I will ALWAYS add letters and then
numbers to the input in the same order, and the input will ALWAYS come
from the input method of the class.

not to mention that @input is ALWAYS @input but passing it down the
chain with () it turns into letters_added and numbers_added etc…I
guess I could work around that though and still have it make sense.

sorry for post spam, but would this be the appropriate way to do it? I
still prefer the @ way, but I want to do things right.

class AddNumbersAndLetters

 def get_input
   input = gets.chop
   input = add_numbers(input)
   input = add_letters(input)
   input = add_letters(input)
   input = add_numbers(input)
   input = add_letters(input)
 end

 def add_numbers(input)
   input += "123"
 end

 def add_letters(input)
    input += "abc"
 end

end

This way actually looks less bad to me than I thought it would have to
be with (), before I kept thinking in terms of putting the
next_called_method() inside the previous called method but this way I
get most of the same effect I liked from using instance variables, but I
do think it hurts readability a bit to have to include the input = and
(input) part instead of just the method name. But at least now I see how
to do what I want with ().

roob noob wrote in post #1061170:

Honestly I see very little difference between

"
message = “whatever”
encrypt(message) #returns the AES-256 encryption of message
"

and

"
@message
encrypt #returns the AES-256 encryption of @message
"

The difference is that the first method works on its own. You don’t need
a certain context or specific preparations, you simply pass a string and
get the encrypted string.

On the other hand, the second method is completely dependend on the
outer world. You cannot even call it without having set the @message
variable before. And you have to make sure the value isn’t changed in
the meantime (which makes the whole program rather “unstable” and
completely unsuitable for threaded applications).

The worst thing is that these dependencies aren’t even obvious from the
code. You’d have to write a comment and explain which steps have to be
taken. Otherwise, there will be strange errors like "nil doesn’t have a

  • method".

Well, if you only write small programs for yourself and don’t plan to
publish them, this all might be acceptable. But I wouldn’t even start to
adept this programming style, because it will get in your way as soon as
your applications become bigger or you share the code with others.

This is a bit like arguing about if you can use a hammer to put a screw
in. Well, if you only got a few screws and the result doesn’t really
matter, then you can do it. It does work. But it’s the wrong way and
it isn’t suitable as a general approach.

By the way: Your programming style wouldn’t even work in most other
languages. It relies on the fact that Ruby is rather sloppy with
instance variables and allows them to be created on the fly by any
method. In more strict programming languages, every variable has to be
declared first, which would make the whole approach rather tedious.

roob noob wrote in post #1061186:

sorry for post spam, but would this be the appropriate way to do it? I
still prefer the @ way, but I want to do things right.

class AddNumbersAndLetters

 def get_input
   input = gets.chop
   input = add_numbers(input)
   input = add_letters(input)
   input = add_letters(input)
   input = add_numbers(input)
   input = add_letters(input)
 end

 def add_numbers(input)
   input += "123"
 end

 def add_letters(input)
    input += "abc"
 end

end

Yes, this makes a lot more sense. A more advanced approach would be to
only write a “rule” how the string should be built and then let the
program do the actual method chaining on its own:

input = gets.chop
transform_input = [
:add_numbers,
:add_letters,
:add_letters,
:add_numbers,
:add_letters
]
transform_input.inject input do |result, method|
send method, result
end

See
http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-inject
on how the inject method works.

By the way, you should replace the “+=” with a simple “+”. You don’t
want to reassign the input parameter but simply get the result of adding
“123” to input.

First let me thank you for all of the help you have been :). It is much
appreciated, I find that the more I learn Ruby and start to get a grasp
on the basics, the more questions I end up having that are not easily
answered by prepackaged guides, ie: I need to start asking people.

Second, how does this look? These are snippets from a class that
estimates password entropy. Before I was using instance variables for
@entropy_bits and calling methods like in my previous examples, now I am
trying to use inject I think I at least come close to doing it right. My
program does work anyway.

my apologies that the formating is not so happy with the limited screen
space provided here :confused:

def estimate_password_entropy(password)

evaluate_entropy = [
contains_dictionary_word?(password),
contains_special_character?(password),
contains_upcase_character?(password),
contains_lowcase_character?(password),
contains_number?(password),
length_estimated_entropy(password)
]

entropy_bits = evaluate_entropy.inject(:+)

end

def contains_dictionary_word?(password)
entropy_bits = 0
passed_dictionary_test = true
File.open("#{RELATIVEPATH}/data/dictionary") do |dictionary|
while line = dictionary.gets
passed_dictionary_test = false and break if
password.include?(line.chop)
end
entropy_bits = 6 if passed_dictionary_test and password.length > 4
end
return entropy_bits
end

#most other tests fit the following pattern

def contains_special_character?(password)
entropy_bits = 0
special_characters = %w{ ~ ! @ # $ % ^ & * ( ) _ - + = { [ ] | \ :
; " ’ < , > . ? / } }
special_characters.each do |special_character|
if password.include?(special_character) then entropy_bits = 1.5 and
break
end
end
return entropy_bits
end

On Thu, May 17, 2012 at 6:38 PM, roob noob [email protected] wrote:

return entropy_bits
end

Two notes:

  1. By common ruby convention, methods ending with a ? return a
    boolean, not an int

  2. This does not do what you think it does:

passed_dictionary_test = false and break if
password.include?(line.chop)

it parses as

(passed_dictionary_test = false) and (break if
password.include?(line.chop))

then (passed_dictionary_test = false) is an expression, which returns
its rhs, which is false, so the bit after the “and” is never
evaluated. The following code is illustrative - guess what it does,
then run it and see:

x = 0
passed = true
while x < 10
passed = false and break if x == 5
puts “x = #{x}, passed = #{passed}”
x += 1
end

This form of your original code works:

if password.include?(line.chop)
    passed_dictionary_test = false
    break
end

martin

roob noob wrote in post #1061229:

Second, how does this look? These are snippets from a class that
estimates password entropy. Before I was using instance variables for
@entropy_bits and calling methods like in my previous examples, now I am
trying to use inject I think I at least come close to doing it right. My
program does work anyway.

This looks good. :slight_smile:

Since you already said that the character tests follow the same pattern,
you might wanna think about writing only one generalized method. For
example, you could put the character sets and the corresponding “scores”
in an array and then let a method iterate over it. You don’t even have
to write the actual characters down but use regular expressions instead:

/\p{Lower}/

This regular expression matches any string with a lower case letter (of
any language) in it. If you only want the latin letters from a to z, you
can instead use the pattern

/[a-z]/

This narrows the test down to one line: password =~ pattern

As a complete example:

#------------------------------------------
class Entropy

the scores are just made up

CHARACTER_SCORES = {
# special characters
# = printable ASCII characters which are not alphanumeric
/[\p{ASCII}&&\p{Graph}&&\p{^Alnum}]/ => 11,
# uppercase letters
/[A-Z]/ => 22,
# lowercase letter
/[a-z]/ => 33,
# digits
/[0-9]/ => 44
}

def test_characters password
CHARACTER_SCORES.inject 0 do |sum, (pattern, score)|
password =~ pattern ? sum + score : sum
end
end

end
#------------------------------------------

By the way, most of the time you don’t need lowlevel structures like the
while statement. Ruby has a lot of iterators which do the same thing in
a lot less lines.

For example, you could rewrite the dictionary method to this:

#------------------------------------------
def contains_dictionary_word?(password)
entropy_bits = 0
passed_dictionary_test =
File.foreach("#{RELATIVEPATH}/data/dictionary").any? do |line|
password.include? line.chop
end
entropy_bits = 6 if passed_dictionary_test and password.length > 4
return entropy_bits
end
#------------------------------------------

The “while gets” is replaced with “File.foreach”. And the “break false”
is replaced with the “any?” iterator.

On last thing: You should be careful with method names. A method called
“contains_dictionary_word?” looks all like it returns either true or
false. It it returns a score instead, this may lead to confusion. So I’d
rather call it “test_dictionary” or so.

Martin DeMello wrote in post #1061234:

  1. This does not do what you think it does:

passed_dictionary_test = false and break if
password.include?(line.chop)

it parses as

(passed_dictionary_test = false) and (break if
password.include?(line.chop))

That’s not true (at least not in Ruby 1.9). The “if” modifier has lower
precedence then the “and”, so the expression is parsed as expected:

(passed_dictionary_test = false and break) if …

However, you’re right about the “and”: Since the left operand is always
false, the “break” will never be executed.

So you shouldn’t read the “and” as “do this and then that”. It rather
means “do this, and if you were successful, do that”.

then (passed_dictionary_test = false) is an expression, which returns
its rhs, which is false, so the bit after the “and” is never
evaluated. The following code is illustrative - guess what it does,
then run it and see:

x = 0
passed = true
while x < 10
passed = false and break if x == 5
puts “x = #{x}, passed = #{passed}”
x += 1
end

Have to tested it yourself? If you were right, then “passed” would
always be false. But it’s only after x has become 5.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs