Replace class and variables names in code snippet - ruby

I would like to insert some gist-s of my code in CV. In order not to give idea what this code is about I want to replace all classes, methods and variables names with some random strings automatically (using some script or online creator?), so that I can show "how I write" but I don't show real functionality.
class User
def initialize(email)
#email = email
#is_admin = false
end
def give_admin
self.update(is_admin: true)
end
[...]
end
I would like to change into:
class Class1
def method_1(var1)
#var1 = var1
#var2 = false
end
def method_2
self.update(var2: true)
end
[...]
end
or maybe someone know better way to show somebody else "how does my code looks like but without showing him functionality"?
Thanks in advance

To answer your question:
You might want to use a Ruby source code uglifier/minifier (for example: ruby2ruby).
BUT (and that's all caps "but")
Don't do it! When someone is looking at your code, s/he does not want to see some random ruby code. The name of the class, the method names, etc. are very important in evaluating code. Who cares about the class names you have written in the past? Most probably, there are gazillion of other developers that have named their classes using exactly the same names as your showcase classes. So, post probably no one would care. Just give the exact classes you wrote, remove some private things that they may contain and share them.
If you really don't want to share some classes that you are really proud of, then write another (new) classes and showcase all your skills in there!
PS. If someone wants to evaluate your code without knowing the class and method names, then grab your code and run like hell! You probably better off without them! :) You will not learn much from that team lead. Or, if you do, you will learn the wrong things.

Related

Where is Ruby code, generated via metaprogramming, stored, and is it viewable/printable?

I've just started learning about metaprogramming in Ruby, and found myself wondering if it was possible to view (in someway) the code that had been generated. I want to, as a coding exercise, write a short method that will generate a Ruby file containing either a few method definitions or, ideally, an entire class or module definition.
I was thinking that perhaps just building up a string representation of the file and then merely writing it out might be a way to accomplish that, but that way doesn't really necessitate the use of metaprogramming, and since my goal is a metaprogramming exercise, I would like to figure out a way to incorporate it into that process or else do it another way.
I guess, if I was to take the string-building approach, I would like to start with something like
klass_string = "class GeneratedClass\n\t<BODY>\nend"
and then somehow save the output of something like this
define_method( :initialize ) do
instance_variable_set("#var", "some_value")
end
in a string that could replace '' in klass_string and then written out to a file. I know I could just put the above code snippet directly into the string, and it would workout fine, but I would like to have the output in a more standard format, as if it'd been written by hand and not generated:
class GeneratedClass
def initialize
#var = 'some_value'
end
end
Could someone point me in the right direction?
I agree with your comment that this question isn't really about metaprogramming so much as dynamic code generation / execution and introspection. Those are interesting topics, but not really metaprogramming. In particular your question about outputting ruby code to strings is about introspection, where as your string injection question is about dynamic code (just to try give you the words to google about what you're interested in).
Since your question is general and really around introspection and dynamic code, I'm going to reference you to some canonical and useful projects that can help you learn more..
ParseTree & Ruby Parser and Sourcify
Ruby Parser is a pure ruby implementation of ParseTree, so I'd recommend starting there to learn how to examine and "stringify" Ruby code. Play around with all of those, and in particular learn how they examine code in Ruby to generate their results. You'll learn a ton about how things work under the hood. Eric Hodel among others is real smart about this stuff.. Be warned though, this is really advanced stuff, but if that's where you want to build expertise, hopefully those references will help!

Any reason I should not be using send like this?

I am trying to keep my classes encapsulated as much as possible. Any reason that I should not use the send method like this?
class MyClass
def self.join_two_strings(first, second)
new.send(:join_two_strings, first, second)
end
def join_two_strings(first, second)
first + second
end
private :join_two_strings
end
Since #join_two_strings doesn't actually need any instance state, it should just be a class method.
class MyClass
def self.join_two_strings(first, second)
first + second
end
end
Yes, there is reason not to do that. It is because it is verbose. To achieve what you want, you should code like in Chris Heald's answer. (Chris Heald suggests what you should do, but does not answer your question).
To call the problem with your use of #send even more precisely, it is not verbosity, but obscuring of the design intent. Sometimes verbosity (such as using full words, rather than abbreviations) serves to reveal the design intent and shorten the time reader needs to understand your code. With your code example, the reader does not believe that what you want to achieve is mere joining of 2 strings, they keep searching for deeper meaning, before conceding that it is just a complicated method to do a simple thing (and possibly refactoring your code as Chris did). As for #send itself, do not fear it, do not fear to use it. Though #send should not be used as a tool to arbitrarily disrespect privacy of methods, on the other hand, Ruby methods are messages and you don't have to worry to be explicit about it, where there is a reason for it.

How do I write a Date transform method?

It's very simple. Here's what I want to do with a date that is formatted as YYYYMMDD:
month = datestring[0:2]
day = datestring[2:2]
year = datestring[4:4]
return "#{month}/#{day}/#{year}"
The problem is, and I've never understood this about Ruby, do I do:
a module?
a mixin?
something else?
I know what I want to do, I just have NO idea what kind of file or structure to put it in. And if it's a module, do I prefix the method name with the name of the module:
module DateHelper
def DateHelper.transform(datestring)
...
end
end
Why or why wouldn't I do this? Thanks a lot for helping to clear something up that's represented a mental block for me.
Instead of modules, consider using objects with composition:
class DateString
def initialize(date)
#date_string = date
end
def format
...
end
end
Now you can do:
my_date_string = DateString.new("20121203")
puts my_date_string.format # => "12/03/2012"
This answer covers the ruby-philosophical part of your question, but if you're doing a lot of date formatting, consider using a gem that already does it for you.
The code in your question is suggestive of a mixin, which is one possible way to go. It is more idiomatically written like this:
module DateHelper
def date_to_some_format(date)
...
end
end
Notice that the method is an instance method, and that it has a name that won't potentially clash with other methods in an arbitrary class. If you wanted the method available at the class-level, one way you could do this would be:
class SomeClass
class << self
include DateHelper
...
end
end
That is one way to handle class-level mixins; there are others as well.
Whether you want a mixin will depend upon the context. Does the date formatting involve code that you find repeating all over the place in unrelated classes? Is it a one-off that you will never use again? Is remembering state required? Is the date format so useful it might be made into an extension to a core library? The answer to these questions will suggest whether the code should be handled in a mixin or in some other way. (Mixins are generally implemented in Ruby with modules.) Part of really learning ruby is getting a sense of the answers to these questions in different contexts; there are few simple answers in this regard, and to a certain extent things depend upon convention, personal preference and house style.
As an aside, one way to get the date format you're looking for is this (following your input date format of YYYYMMDD):
Date.strptime("20100101", "%Y%m%d").strftime("%m/%d/%Y")
You would not necessarily chain it together in this way in your code—Brendan Benson's response provides a good approach, for example—although you might not need something fancy if you're only doing this in one place.

Gotchas for redefining methods in ruby

What are the things to be careful about while redefining methods in Ruby? Is redefining core library methods okay?
the problems IMHO are
You'll forget about the change.
You'll copy paste a snippet from the internet, which will trigger an error the altered behavior and you'll scratch your head until you get hairless patches.
Another developer will come after your and fight a bug for 3 months, until he finds it's in one of the monkey patches. He'll go to HR, get your address and and show you why not to do monkey patches.
Now, sometimes you need to monkey patch a class (even in the core library, why not). My suggestion is
Put all of your monkey-patches in ONE source folder.
The second thing you say to a new developer after "Hello my name is ..." is the location of that folder and a detailed explanation of what each monkey patch does.
I don't do much monkeypatching myself, but I've heard that rather than doing
class String
def improved_method
# teh codes
end
end
It's better to put the new method into a module, and then include the module
module ImprovedString
def improved_method
# teh codes
end
end
class String
include ImprovedString
end
it makes it easier to find where a method has been defined, and the old version still exists without having to do alias chaining.
I like the other answers. Though, I have to add that:
Sometimes you may only want to redefine methods only for certain instances. You can do this, and it makes it somehow more controlled than changing the functionality for all objects of a certain class - as long as a proper debugger is used for debugging:
class << object_instance
def method_redefinition
return "method_redefinition"
end
end
object_instance.method_redefinition => "method redefinition"
The metioned set of functionalities can also be encapsulated in a mix-in in order to avoid too much nesting and messy "code definition inside code execution":
module M
def method_redefinition
"method_redefinition"
end
end
object_instance.extend M
object_instance.method_redefinition => "method_redefinition"
You're talking about monkey patching and it's dangerous for the following reasons according to wikipedia
Carelessly written or poorly
documented monkey patches can lead to
problems:
They can lead to upgrade problems when the patch makes assumptions about
the patched object that are no longer
true; if the product you have changed
changes with a new release it may very
well break your patch. For this reason
monkey patches are often made
conditional, and only applied if
appropriate.
If two modules attempt to monkey-patch the same method, one of
them (whichever one runs last) "wins"
and the other patch has no effect,
unless monkeypatches are written with
pattern like alias_method_chain
They create a discrepancy between the original source code on disk and
the observed behaviour that can be
very confusing to anyone unaware of
the patches' existence.
Even if monkey patching isn't used,
some see a problem with the
availability of the feature, since the
ability to use monkey patching in a
programming language is incompatible
with enforcing strong encapsulation,
as required by the object-capability
model, between objects.
There's talk of a safer way of monkey
patching coming in ruby 2 called
refinements
This tiny gem might be useful if you're finding yourself running into monkey-patching issues: (https://github.com/gnovos/ctx). I originally wrote it to create more expressive DSLs by allowing alterations to the base objects without doing too much damage elsewhere, but it can probably be put to any number of uses. It gets around some of the monkey-patching issues by scoping method re-definition into arbitrary contexts that can be swapped out as needed.
If I want to redefine a method in some core class (for example, in String, etc), I use ctx_define instead of "def" and then later wrap the section of code that should use the new definition in a ctx block, like so:
class ::String
ctx_define :dsl, :+ do |other|
"#{self[0].upcase}#{self[1..-1]}#{other.capitalize}"
end
end
puts "this" + "is" + "normal" + "text" + "concatination"
# => thisisnormaltextconcatination
ctx(:dsl) { puts "this" + "is" + "special" + "text" + "concatination" }
# => ThisIsSpecialTextConcatination
I only threw it together in a few minutes, so I can't make any guarantees about how robust it is in any number of complicated situations, but it seems to work fine for simple needs. Give it a look if you're interested and see if it is of any help. :)

Best way of emulating enum in Ruby? (part two)

I'm new to Ruby so forgive me if this is something obvious..
I've made a class like so
class Element
attr_accessor :type
:type_integer
:type_string
end
(this is really just an example, not actual code)
Well, I've read Enums in Ruby and I'd prefer to go the Symbols route of having something like enumerations in other languages. I have a problem though, how can I keep my global scope clear while implementing this. What I'm wanting to be able to do is something like
e=Element.new
e.type=Element.type_integer
or something pretty simple and straight forward like that.
Symbols don't do anything to the global (or any other) scope (i.e. no variables or constants or anything else gets defined when you use symbols), so I guess the answer is: just use symbols and the global scope will be kept clear.
If you want to use e.type=Element.type_integer, while still using symbols, you could do:
class Element
def self.type_integer
:type_integer
end
end
Although I fail to see the upside vs. just using e.type = :type_integer directly.

Resources