Reserved words in ruby 2.1:
ENCODING def in self
LINE defined? module super
FILE do next then
BEGIN else nil true
END elsif not undef
alias end or unless
and ensure redo until
begin false rescue when
break for retry while
case if return yield
class
#!/usr/bin/env ruby $SAFE=4# set the security value at the highest prior unless we need more freedom require'a'# will load a.rb, only one time load'a.rb'# will load a.rb, every time called this line # # Structure # # Classes: classAnimal # this sets a public id/varible that can be used for our objects,gg # independently of being or not declared in the class, we can already use them attr_accessor:lenght,:color# both read and write attr_reader:lenght,:color# read-only attr_writer:lenght,:color# write-only (setter) # this method will be called when creating a new object, it requires # arguments if we state them definitialize(given_name="Unknown",given_age) # the funny here is that if you call "dog = Animal.new(5)", it will # understand that you are passing the second parameter and set Unknown # to name automatically @name=given_name# create variables for the objects that we can use, # from the given arguments @age=given_age # variables with @@ instead of @ are accessible only for classes as a # whole, not by the instance of the objects, useful for store # information relevant to all objects of the same class # # WARNING: there's an important side-effect behaviour important to consider: http://www.railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-ruby/ ifdefined?(@@number_of_squares) # variable already exists for all objects when the first one is created @@number_of_squares+=1 else # create the variable first time when the first object is created @@number_of_squares=1 end end defself.count @@number_of_squares# will return the number of objects when Animal.count is called end # this is a simple method, used to perform actions to objects (like a function) defname # when calling "dog.name" will return "lassie" for example, "return" is optional return@name end # if you want to set the age in another moment than when initialized, you # need to use this setter function defage=(new_age) # new_age is the parameter given to the call, like "dog.age = 10", # adding = in the name of the method means that the method is used for # assign values @age=new_age end defsome_error_handled_case # raise an error type with a message if a specific case raiseArgumentError,"Age is too young"if@age<2 end # using self here is only accessible when calling the class, instead the # object, like: Animal.show_name defself.show_name# self acts like an alias to Animal, so: def Animal.show_name ... putsself# when called, will print "Animal" (class name) end # create an alias to whatever thing to another name aliasshow_namelist_name private # things from here only accessible from the object itself (instances) # calls: method of an object can call its private methods (inside's class code) # cannot call: dog.method_private # note: using 'send' you can do it, it invokes methods by name: dog.send(:method_private) defprivated_area puts"I will only be shown when another method of this class/object calls this private method" end protected # same as private, but callable from different objects of the same class # allowing to communicate between them, like for do comparisons between objects defage_difference_with(other_person) (self.age-other_person.age).abs end # example: fred = Person.new(34) ; chris = Person.new(25) ; puts chris.age_difference_with(fred) defcompare(c) ifc.age>age "The other object's age is bigger." else "The other object's age is the same or smaller." end # example: chris = Person.new(25) ; marcos = Person.new(34) ; puts chris.compare_age(marcos) end # back to the elements of code which are public public defsummary puts"I can be called normally" end private:method1,:method2# we can also define them on this way end # Inheritance: # create a superclass called Doctor from the Person's class (inheritance) classDoctor<Person # we have already defined the method "name" in the Person's class, so we extend it: defname # when we call .name method from a Doctor's object, will append like: "Dr. Name" # "super" walks in inheritance of the same methods in their parents "Dr. "+super end end somebody=Person.new("John") putssomebody.name# John who=Doctor.new("James") putswho.name# Dr. James putswho.instance_variables# @name # # Polymorfism: # - calling the method "talk" in Dogs or Cats they do different things, but # you can use it in the same way this is very useful when you need to do the # same action for different objects, for a example a loop of talking animals # classDog<Animal deftalk puts"Woof!" end end classCat<Animal deftalk puts"Meeew" end end # # Nested classes: # - useful for improve structure/grouping/dependency # classDrawing classLine end classCircle end # you can call circle subclasses directly from Drawing too on this way: defDrawing.give_me_a_circle Circle.new end end # the way to call a class inside another class is by using :: # trying to use directly Circle will fail, so: my_circle=Drawing::Circle.new # # Extensions # - already-defined classes (any of them) can be extended or replaced for # example to the Fixnum objects we can use .minutes to translate a number to # minutes classFixnum # we can extend any class with improvings or modifications defminutes self*60 end end # and so we can use now: puts5.minutes# 300 # # Modules # # They allows to separate things to avoid clashes, similar to classes, but # they doesn't allows you to instantiate objects, their methods can be # directly used without the need to create objects, they are more like # functions that just processes things, let's say toolboxes of features moduleCountry classRuler attr_accessor:name end defhello puts"I can say hello without the need to create an object" end end moduleToolbox classRuler attr_accessor:lenght end # Mix-in: this will print the name of the class which loaded this module # useful for introducing methods in other's classes # # basically is a method defined outside of any class form, so when # integrating a module inside an external class it will simply work on it defclass_name self.class.to_s end end # direct call of the module with its contents a=Toolbox::Ruler.new a.lenght=50 b=Country::Ruler.new b.name="Ghengis Khan" # get the module features and directly use it includeCountry governor=Ruler.new # you can use the method hello from the module Country, without the need to # create or use of objects hello # # Flow examples # # loops loopdo i+=1 breakifi>100# break da loop end while(i==10) puts"i = 10" end until(i>10) puts"i finally reached 10" end # if if2==1 puts"universe is broken" end unless2==2 puts"universe is broken" end # case fruit="orange" casefruit when"orange" color="orange" when"apple" color="green" else color="unknown" end # ternary operator putsx>10?"higher than 10":"lower or equal to 10" # # Structures: # it is an easy and fast way to define attributes and hold data, same as to # create an entire class with defined initializators (but without require # strictly to set all the parameters) Person=Struct.new(:name,:gender,:age) fred=Person.new("Fred","male",50) # # variable substitution ways: # foo="12345678901234567890" # puts the first 10 chars in different ways: putsfoo[1,10] putsfoo[0..9] putsfoo.slice(0,10) putsfoo.match("^..........").to_s # # Arrays: # a=[1,2,3,"four"] a<<5# append an item a.push6# append an item putsa.empty?# false putsa.include?("four")# true # # Hashes (associative arrays) # dictionary={'cat'=>'feline animal', 'dog'=>'canine animal', 'tags'=>['books', 'libraries', 'knowledge']} putsdictionary['cat']# shows description putsdictionary['tags'].first# shows the first array element for the subarray tags dictionary.delete("cat") dictionary.delete_if{|key,value|value=~ /feline/} # # Code blocks # defeach_vowel %w{a e i o u}.each{|vowel|yieldvowel} end each_vowel{|v|putsv+" is a vowel"} # the delimiter of "each" can be modified passing an argument like .each(',') or # changing the input delimiter variable $/ # # More exactly, yield runs "in the inverse way" including its parameters, what you pass to a call to the function that includes a yield, this is a more clear example: deftest yield5 puts"method test" yield100 end test{|i|puts"You are in the block #{i}"} # so you got: # You are in the block 5 # method test # You are in the block 100 # # Errors handling # classGetWeb begin # block of code where can happen errors a=(10/0)# if this doesn't works... rescue=>e a=10# instead of just exiting we can simply assign a default behaviour and continue puts"class of exception is: "+e.class.to_s# show some debug reason of our error end end # another example: data="" begin #<..code to retrieve the contents of a Web page..> #data = <..content of Web page..> rescueZeroDivisionError #... code to rescue the zero division exception here ... rescueYourOwnException #... code to rescue a different type of exception here ... rescue puts"The Web page could not be loaded! Using default data instead." #data = <..load data from local file..> end putsdata # # Debug # # If you want to run a script in debug mode, "ruby -r debug script.rb", use # step, break, watch, cont, etc... # you can found some basic example in the book "beginning ruby" pag. 190 # Catch & Throw: # note: catch & throw is useless and confusing, avoid it # catch & throw works in a similar way as rescue/raise, but using symbols rather than exceptions catch(:finish)do 1000.timesdo x=rand(1000) # we will exit the loop "catch" containing the symbol :finish if we got this case throw:finishifx==123 end puts"Generated 1000 random numbers withoutgenerating 123!" end # another catch & throw example defroutine(n) putsn# final result will produce: 3 2 1 0 throw:doneifn<=0# exit inifite nested loop if case happens routine(n-1)# nested itself, infinitely end catch(:done){routine(3)} # # Dynamic Code Execution # # executes the code created dynamically eval"puts 2 + 2" # similar: my_number=15 my_code=%Q{#{my_number} * 2} putseval(my_code) # String interpolation makes the eval methods powerful tools for generating # different features on the fly. This ability is a power unseen in the majority # of programming languages # - this method adds an accessor to another class, # dynamically using class_eval and interpolating a name given externally defadd_accessor_to_person(accessor_name) Person.class_eval%Q{ attr_accessor :#{accessor_name} } end # It’s possible to take the previous example a lot further and add an # add_accessor method to every class by putting your class_eval cleverness in a # new method, defined within the Class class (from which all other classes descend): classClass defadd_accessor(accessor_name) self.class_eval%Q{ attr_accessor :#{accessor_name} } end end # You can eval code in instances of objects too: classMyClass definitialize @my_variable='Hello, world!' end end obj=MyClass.new obj.instance_eval{puts@my_variable}# add extra code to an existing object and execute it # In the same way you can define methods for existing objects obj.instance_evaldodefnew_method;puts'born new method in an alive object';end;end # better way to define a method for an existing object, if you dont want to use # dynamic code execution of eval obj.new_methoddodefnew_method;puts'born new method in an alive object';end;end # example of an "attr_accessor" equivalent writed in dynamic code, which will work in the same way: classClass defadd_accessor(accessor_name) self.class_eval%Q{ def #{accessor_name} @#{accessor_name} end def #{accessor_name}=(value) @#{accessor_name} = value end } end end # You can use this technique to create a multitude of different "code # generators" and methods that can act as a "macro" language to perform things # in Ruby that are otherwise lengthy to type out. # # Forks & Processes # # process-ID is returned in the parent but 'nil' in the child, use this to # determine which process a script is in iffork.nil? exec"ruby other-file.rb" end # fork a child and wait for it child=forkdo sleep3 puts"Child says 'hi'!" end puts"Waiting for the child process..." Process.waitchild puts"All done!" # # Unit Testing # # - default in stdlib is Minitest, but there's also: rspec, minitest, # test/unit, minispec, bacon, testrocket... rspec is also very used # create a method for test it later classString deftitleize # we want to use this method for print results like: "This Is A Test" self.capitalize # and we will end later in improving the code like these next commented # lines, because we haven see that the previous test failed in some cases #self.gsub(/\b\w/) {|letter| letter.upcase } #self.gsub(/\s\w/) {|letter| letter.upcase } #self.gsub(/(\A|\s)\w/) {|letter| letter.upcase } end end puts"this is a test".titleize# this will print "This is a test", but we don't want this result, so for avoid bugs: # method 1 for testing (manual testing) # let's add some "assertion" checkers # # if our method doesn't give us what we exactly expect, fail raise"Fail 1"unless"this is a test".titleize=="This Is A Test" # what happens with numbers? let's add this because this is what we expect in any case raise"Fail 2"unless"another test 1234".titleize=="Another Test 1234" # and with other chars like ' ? raise"Fail 2"unless"We're testing titleize".titleize=="We're Testing Titleize" # method 2 for testing require'test/unit' # there's also "Minitest" (included in stdlib) and "Bacon" for unit testing classTestTitleize<Test::Unit::TestCase deftest_basic assert_equal("This Is A Test","this is a test".titleize) assert_equal("Another Test 1234","another test 1234".titleize) assert_equal("We're Testing","we're testing".titleize) end end # method 3 for testing: use Minitest instead, seems like more easier and fast to use option moduleDataStore::AdapterSpec it"returns nil for an invalid key"do @adapter.get(:invalid).must_equalnil end it"can set a value"do @adapter.set(:foo,42) @adapter.get(:foo).must_equal42 end end # from: http://wojtekmach.pl/blog/2013/07/17/sharing-examples-in-minitest/ # more: http://blog.arvidandersson.se/2012/03/28/minimalicous-testing-in-ruby-1-9 # # Misc # # run when finish at_exit{puts"#{Dir.pwd}"}# enqueue a job for when the application has finished to run # trap trap("SIGINT")do puts"signal INT trapped!, what we should do?" end # Using Files puts"It exists"ifFile.exist?("text.txt") File.open("text.txt"){|f|putsf.gets}# show file contents (cat) f=File.new("text.txt","r") putsf.gets f.close data=File.read("text.txt") array_of_lines=File.readlines("text.txt") f=File.open("text.txt") putsf.gets puts"position in file is: "+f.pos f.pos=8 puts"position in file has moved to: "+f.pos f.close# close the file when finish! # by using File.open in a block, is not needed to close the file when finish File.open("text.txt","w")do|file|file.puts"Hi"end # appending f=File.open"text.txt","a" f.putsTime.now f.close # See the modified time of a file f=File.mtime"text.txt" putsf.hour# since the object returned (f) is a Time object, we can treat him as it # # Typos / Pitfails # # if you put a space before ( it is then not interpreted as arguments, ( needs to be always joint with the call File.open("text.txt","w") # if you put more than one space like here it is then interpreted as a(+b) a+b # # Documentation (generating your own) # # Similar to doxygen, just write comments using this syntax and by running # "rdoc file.rb" (or yard?) you will obtain nicely html's generated # # In documentations, "Array#sample" means the instance method of a class #= RDoc Example # #== This is a heading # #* First item in an outer list # * First item in an inner list # * Second item in an inner list #* Second item in an outer list # * Only item in this inner list # #== This is a second heading # #Visit www.rubyinside.com # #== Test of text formatting features # #Want to see *bold* or _italic_ text? You can even embed #+text that looks like code+ by surrounding it with plus #symbols. Indented code will be automatically formatted: # # class MyClass # def method_name # puts "test" # end # end # #-- # This section is hidden from RDoc and could contain developer # notes, private messages between developers, etc. #++ # RDoc begins processing again here after the ++. # # by adding in a class or element "#:nodoc: all" there's no docs generated (for # the entire class) # SAFE levels # # Value of $SAFE Description # 0 No restrictions. This is the default safe level. # 1 Potentially unsafe methods can’t use tainted data. Also, the current # directory is not added to Ruby’s search path for loading libraries. # 2 The restrictions of safe level 1, plus Ruby won’t load any external # program files from globally writable locations in the filesystem. This is to # prevent attacks where hackers upload malicious code and manipulate existing # programs to load them. Some potentially dangerous methods are also # deactivated, such as File#chmod, Kernel#fork, and Process::setpriority. # 3 The restrictions of level 2, plus newly created objects within the # program are considered tainted automatically. You also cannot untaint objects. # 4 The restrictions of level 3, plus nontainted objects created prior to # the safe level being set cannot be modified. You can use this to set up an # execution environ- ment in a lower safe mode, and then provide a way to # continue execution while protecting the original objects and environment. # # MORE: # # regex: # Try regular expressions in realtime! http://rubular.com/ # # references: # http://www.zenspider.com/Languages/Ruby/QuickRef.html # http://www.tutorialspoint.com/ruby/ruby_quick_guide.htm # "Begining Ruby - book": useful classes and methods, errors, regex, variables, etc... from pag. 575 # # standard lib: # http://www.ruby-doc.org/stdlib-2.1.0/
Last modified
12 years ago
Last modified on Nov 15, 2014, 4:04:41 PM
Note:
See TracWiki
for help on using the wiki.