| | 1 | {{{ |
| | 2 | #!ruby |
| | 3 | #!/usr/bin/env ruby |
| | 4 | |
| | 5 | $SAFE = 4 # set the security value at the highest prior unless we need more freedom |
| | 6 | require 'a' # will load a.rb, only one time |
| | 7 | load 'a.rb' # will load a.rb, every time called this line |
| | 8 | |
| | 9 | # |
| | 10 | # Structure |
| | 11 | # |
| | 12 | |
| | 13 | # Classes: |
| | 14 | class Animal |
| | 15 | # this sets a public id/varible that can be used for our objects, |
| | 16 | # independently of being or not declared in the class, we can already use them |
| | 17 | attr_accessor :lenght, :color # both read and write |
| | 18 | attr_reader :lenght, :color # read-only |
| | 19 | attr_writer :lenght, :color # write-only (setter) |
| | 20 | |
| | 21 | # this method will be called when creating a new object, it requires |
| | 22 | # arguments if we state them |
| | 23 | def initialize(given_name="Unknown", given_age) |
| | 24 | |
| | 25 | # the funny here is that if you call "dog = Animal.new(5)", it will |
| | 26 | # understand that you are passing the second parameter and set Unknown |
| | 27 | # to name automatically |
| | 28 | @name = given_name # create variables for the objects that we can use, |
| | 29 | # from the given arguments |
| | 30 | @age = given_age |
| | 31 | |
| | 32 | # variables with @@ instead of @ are accessible only for classes as a |
| | 33 | # whole, not by the instance of the objects, useful for store |
| | 34 | # information relevant to all objects of the same class |
| | 35 | if defined?(@@number_of_squares) |
| | 36 | # variable already exists for all objects when the first one is created |
| | 37 | @@number_of_squares += 1 |
| | 38 | else |
| | 39 | # create the variable first time when the first object is created |
| | 40 | @@number_of_squares = 1 |
| | 41 | end |
| | 42 | end |
| | 43 | |
| | 44 | def self.count |
| | 45 | @@number_of_squares # will return the number of objects when Animal.count is called |
| | 46 | end |
| | 47 | |
| | 48 | # this is a simple method, used to perform actions to objects (like a function) |
| | 49 | def name |
| | 50 | # when calling "dog.name" will return "lassie" for example, "return" is optional |
| | 51 | return @name |
| | 52 | end |
| | 53 | |
| | 54 | # if you want to set the age in another moment than when initialized, you |
| | 55 | # need to use this setter function |
| | 56 | def age=(new_age) |
| | 57 | # new_age is the parameter given to the call, like "dog.age = 10", |
| | 58 | # adding = in the name of the method means that the method is used for |
| | 59 | # assign values |
| | 60 | @age = new_age |
| | 61 | end |
| | 62 | |
| | 63 | def some_error_handled_case |
| | 64 | # raise an error type with a message if a specific case |
| | 65 | raise ArgumentError, "Age is too young" if @age < 2 |
| | 66 | end |
| | 67 | |
| | 68 | # using self here is only accessible when calling the class, instead the |
| | 69 | # object, like: Animal.show_name |
| | 70 | def self.show_name # self acts like an alias to Animal, so: def Animal.show_name ... |
| | 71 | puts self # when called, will print "Animal" (class name) |
| | 72 | end |
| | 73 | |
| | 74 | # create an alias to whatever thing to another name |
| | 75 | alias show_name list_name |
| | 76 | |
| | 77 | |
| | 78 | private |
| | 79 | # things from here only accessible from the object itself (instances) |
| | 80 | # calls: method of an object can call its private methods (inside's class code) |
| | 81 | # cannot call: dog.method_private |
| | 82 | # note: using 'send' you can do it, it invokes methods by name: dog.send(:method_private) |
| | 83 | def privated_area |
| | 84 | puts "I will only be shown when another method of this class/object calls this private method" |
| | 85 | end |
| | 86 | |
| | 87 | protected |
| | 88 | # same as private, but callable from different objects of the same class |
| | 89 | # allowing to communicate between them, like for do comparisons between objects |
| | 90 | def age_difference_with(other_person) |
| | 91 | (self.age - other_person.age).abs |
| | 92 | end |
| | 93 | # example: fred = Person.new(34) ; chris = Person.new(25) ; puts chris.age_difference_with(fred) |
| | 94 | |
| | 95 | def compare(c) |
| | 96 | if c.age > age |
| | 97 | "The other object's age is bigger." |
| | 98 | else |
| | 99 | "The other object's age is the same or smaller." |
| | 100 | end |
| | 101 | # example: chris = Person.new(25) ; marcos = Person.new(34) ; puts chris.compare_age(marcos) |
| | 102 | end |
| | 103 | |
| | 104 | # back to the elements of code which are public |
| | 105 | public |
| | 106 | def summary |
| | 107 | puts "I can be called normally" |
| | 108 | end |
| | 109 | |
| | 110 | private :method1, :method2 # we can also define them on this way |
| | 111 | end |
| | 112 | |
| | 113 | # Inheritance: |
| | 114 | # create a superclass called Doctro from the Person's class (inheritance) |
| | 115 | class Doctor < Person |
| | 116 | # we have already defined the method "name" in the Person's class, so we extend it: |
| | 117 | def name |
| | 118 | # when we call .name method from a Doctor's object, will append like: "Dr. Name" |
| | 119 | # "super" walks in inheritance of the same methods in their parents |
| | 120 | "Dr. " + super |
| | 121 | end |
| | 122 | end |
| | 123 | |
| | 124 | somebody = Person.new("John") |
| | 125 | puts somebody.name # John |
| | 126 | who = Doctor.new("James") |
| | 127 | puts who.name # Dr. James |
| | 128 | puts who.instance_variables # @name |
| | 129 | |
| | 130 | |
| | 131 | |
| | 132 | # |
| | 133 | # Polymorfism: |
| | 134 | # - calling the method "talk" in Dogs or Cats they do different things, but |
| | 135 | # you can use it in the same way this is very useful when you need to do the |
| | 136 | # same action for different objects, for a example a loop of talking animals |
| | 137 | # |
| | 138 | class Dog < Animal |
| | 139 | def talk |
| | 140 | puts "Woof!" |
| | 141 | end |
| | 142 | end |
| | 143 | |
| | 144 | class Cat < Animal |
| | 145 | def talk |
| | 146 | puts "Meeew" |
| | 147 | end |
| | 148 | end |
| | 149 | |
| | 150 | |
| | 151 | |
| | 152 | # |
| | 153 | # Nested classes: |
| | 154 | # - useful for improve structure/grouping/dependency |
| | 155 | # |
| | 156 | class Drawing |
| | 157 | class Line |
| | 158 | end |
| | 159 | |
| | 160 | class Circle |
| | 161 | end |
| | 162 | |
| | 163 | # you can call circle subclasses directly from Drawing too on this way: |
| | 164 | def Drawing.give_me_a_circle |
| | 165 | Circle.new |
| | 166 | end |
| | 167 | end |
| | 168 | |
| | 169 | # the way to call a class inside another class is by using :: |
| | 170 | # trying to use directly Circle will fail, so: |
| | 171 | my_circle = Drawing::Circle.new |
| | 172 | |
| | 173 | # |
| | 174 | # Extensions |
| | 175 | # - already-defined classes (any of them) can be extended or replaced for |
| | 176 | # example to the Fixnum objects we can use .minutes to translate a number to |
| | 177 | # minutes |
| | 178 | class Fixnum |
| | 179 | # we can extend any class with improvings or modifications |
| | 180 | def minutes |
| | 181 | self * 60 |
| | 182 | end |
| | 183 | end |
| | 184 | # and so we can use now: |
| | 185 | puts 5.minutes # 300 |
| | 186 | |
| | 187 | |
| | 188 | # |
| | 189 | # Modules |
| | 190 | # |
| | 191 | # They allows to separate things to avoid clashes, similar to classes, but |
| | 192 | # they doesn't allows you to instantiate objects, their methods can be |
| | 193 | # directly used without the need to create objects, they are more like |
| | 194 | # functions that just processes things, let's say toolboxes of features |
| | 195 | |
| | 196 | module Country |
| | 197 | class Ruler |
| | 198 | attr_accessor :name |
| | 199 | end |
| | 200 | |
| | 201 | def hello |
| | 202 | puts "I can say hello without the need to create an object" |
| | 203 | end |
| | 204 | end |
| | 205 | |
| | 206 | module Toolbox |
| | 207 | class Ruler |
| | 208 | attr_accessor :lenght |
| | 209 | end |
| | 210 | |
| | 211 | # Mix-in: this will print the name of the class which loaded this module |
| | 212 | # useful for introducing methods in other's classes |
| | 213 | # |
| | 214 | # basically is a method defined outside of any class form, so when |
| | 215 | # integrating a module inside an external class it will simply work on it |
| | 216 | def class_name |
| | 217 | self.class.to_s |
| | 218 | end |
| | 219 | end |
| | 220 | |
| | 221 | # direct call of the module with its contents |
| | 222 | a = Toolbox::Ruler.new |
| | 223 | a.lenght = 50 |
| | 224 | b = Country::Ruler.new |
| | 225 | b.name = "Ghengis Khan" |
| | 226 | |
| | 227 | # get the module features and directly use it |
| | 228 | include Country |
| | 229 | governor = Ruler.new |
| | 230 | |
| | 231 | # you can use the method hello from the module Country, without the need to |
| | 232 | # create or use of objects |
| | 233 | hello |
| | 234 | |
| | 235 | # |
| | 236 | # Flow examples |
| | 237 | # |
| | 238 | |
| | 239 | # loops |
| | 240 | loop do |
| | 241 | i += 1 |
| | 242 | break if i > 100 # break da loop |
| | 243 | end |
| | 244 | |
| | 245 | while (i == 10) |
| | 246 | puts "i = 10" |
| | 247 | end |
| | 248 | |
| | 249 | until (i > 10) |
| | 250 | puts "i finally reached 10" |
| | 251 | end |
| | 252 | |
| | 253 | |
| | 254 | # if |
| | 255 | if 2 == 1 |
| | 256 | puts "universe is broken" |
| | 257 | end |
| | 258 | |
| | 259 | unless 2 == 2 |
| | 260 | puts "universe is broken" |
| | 261 | end |
| | 262 | |
| | 263 | # case |
| | 264 | fruit = "orange" |
| | 265 | case fruit |
| | 266 | when "orange" |
| | 267 | color = "orange" |
| | 268 | when "apple" |
| | 269 | color = "green" |
| | 270 | else |
| | 271 | color "unknown" |
| | 272 | end |
| | 273 | |
| | 274 | # ternary operator |
| | 275 | puts x > 10 ? "higher than 10" : "lower or equal to 10" |
| | 276 | |
| | 277 | |
| | 278 | |
| | 279 | # |
| | 280 | # Structures: |
| | 281 | # it is an easy and fast way to define attributes and hold data, same as to |
| | 282 | # create an entire class with defined initializators (but without require |
| | 283 | # strictly to set all the parameters) |
| | 284 | Person = Struct.new(:name, :gender, :age) |
| | 285 | fred = Person.new("Fred", "male", 50) |
| | 286 | |
| | 287 | |
| | 288 | |
| | 289 | # variable substitution ways: |
| | 290 | foo = "12345678901234567890" |
| | 291 | # puts the first 10 chars in different ways: |
| | 292 | puts foo[1,10] |
| | 293 | puts foo[0..9] |
| | 294 | puts foo.slice(0,10) |
| | 295 | puts foo.match("^..........").to_s |
| | 296 | |
| | 297 | |
| | 298 | # Arrays: |
| | 299 | a = [1, 2, 3, "four"] |
| | 300 | a << 5 |
| | 301 | a.push 6 |
| | 302 | puts a.empty? # false |
| | 303 | puts a.include?("four") # true |
| | 304 | |
| | 305 | # Hashes (associative arrays) |
| | 306 | dictionary = { 'cat' => 'feline animal', |
| | 307 | 'dog' => 'canine animal', |
| | 308 | 'tags' => ['books', |
| | 309 | 'libraries', |
| | 310 | 'knowledge'] } |
| | 311 | puts dictionary['cat'] # shows description |
| | 312 | puts dictionary['tags'].first # shows the first array element for the subarray tags |
| | 313 | dictionary.delete("cat") |
| | 314 | dictionary.delete_if { |key, value| value =~ /feline/ } |
| | 315 | |
| | 316 | |
| | 317 | # Code blocks |
| | 318 | def each_vowel |
| | 319 | %w{a e i o u}.each { |vowel| yield vowel } |
| | 320 | end |
| | 321 | |
| | 322 | each_vowel { |v| puts v + " is a vowel" } |
| | 323 | # the delimiter of "each" can be modified passing an argument like .each(',') or |
| | 324 | # changing the input delimiter variable $/ |
| | 325 | |
| | 326 | |
| | 327 | |
| | 328 | # |
| | 329 | # Errors handling |
| | 330 | # |
| | 331 | class GetWeb |
| | 332 | begin |
| | 333 | # block of code where can happen errors |
| | 334 | a = (10 / 0) # if this doesn't works... |
| | 335 | rescue => e |
| | 336 | a = 10 # let's still use the original value in failed cases, instead of exit/error |
| | 337 | puts "class of exception is: " + e.class.to_s |
| | 338 | end |
| | 339 | end |
| | 340 | |
| | 341 | # another example: |
| | 342 | data = "" |
| | 343 | begin |
| | 344 | #<..code to retrieve the contents of a Web page..> |
| | 345 | #data = <..content of Web page..> |
| | 346 | rescue ZeroDivisionError |
| | 347 | #... code to rescue the zero division exception here ... |
| | 348 | rescue YourOwnException |
| | 349 | #... code to rescue a different type of exception here ... |
| | 350 | rescue |
| | 351 | puts "The Web page could not be loaded! Using default data instead." |
| | 352 | #data = <..load data from local file..> |
| | 353 | end |
| | 354 | puts data |
| | 355 | |
| | 356 | |
| | 357 | # If you want to run a script in debug mode, "ruby -r debug script.rb", use |
| | 358 | # step, break, watch, cont, etc... |
| | 359 | |
| | 360 | |
| | 361 | |
| | 362 | # Catch & Throw: |
| | 363 | # note: catch & throw is useless and confusing, avoid it |
| | 364 | # catch & throw works in a similar way as rescue/raise, but using symbols rather than exceptions |
| | 365 | catch(:finish) do |
| | 366 | 1000.times do |
| | 367 | x = rand(1000) |
| | 368 | # we will exit the loop "catch" containing the symbol :finish if we got this case |
| | 369 | throw :finish if x == 123 |
| | 370 | end |
| | 371 | |
| | 372 | puts "Generated 1000 random numbers withoutgenerating 123!" |
| | 373 | end |
| | 374 | |
| | 375 | # another catch & throw example |
| | 376 | def routine(n) |
| | 377 | puts n # final result will produce: 3 2 1 0 |
| | 378 | throw :done if n <= 0 # exit inifite nested loop if case happens |
| | 379 | routine(n-1) # nested itself, infinitely |
| | 380 | end |
| | 381 | |
| | 382 | catch(:done) { routine(3) } |
| | 383 | |
| | 384 | |
| | 385 | # |
| | 386 | # Dynamic Code Execution |
| | 387 | # |
| | 388 | |
| | 389 | # executes the code created dynamically |
| | 390 | eval "puts 2 + 2" |
| | 391 | |
| | 392 | # similar: |
| | 393 | my_number = 15 |
| | 394 | my_code = %Q{#{my_number} * 2} |
| | 395 | puts eval(my_code) |
| | 396 | |
| | 397 | # String interpolation makes the eval methods powerful tools for generating |
| | 398 | # different features on the fly. This ability is a power unseen in the majority |
| | 399 | # of programming languages |
| | 400 | # - this method adds an accessor to another class, |
| | 401 | # dynamically using class_eval and interpolating a name given externally |
| | 402 | def add_accessor_to_person(accessor_name) |
| | 403 | Person.class_eval %Q{ |
| | 404 | attr_accessor :#{accessor_name} |
| | 405 | } |
| | 406 | end |
| | 407 | |
| | 408 | # It’s possible to take the previous example a lot further and add an |
| | 409 | # add_accessor method to every class by putting your class_eval cleverness in a |
| | 410 | # new method, defined within the Class class (from which all other classes descend): |
| | 411 | class Class |
| | 412 | def add_accessor(accessor_name) |
| | 413 | self.class_eval %Q{ |
| | 414 | attr_accessor :#{accessor_name} |
| | 415 | } |
| | 416 | end |
| | 417 | end |
| | 418 | |
| | 419 | # You can eval code in instances of objects too: |
| | 420 | class MyClass |
| | 421 | def initialize |
| | 422 | @my_variable = 'Hello, world!' |
| | 423 | end |
| | 424 | end |
| | 425 | |
| | 426 | obj = MyClass.new |
| | 427 | obj.instance_eval { puts @my_variable } # add extra code to an existing object and execute it |
| | 428 | |
| | 429 | # In the same way you can define methods for existing objects |
| | 430 | obj.instance_eval do def new_method ; puts 'born new method in an alive object' ; end ; end |
| | 431 | # better way to define a method for an existing object, if you dont want to use |
| | 432 | # dynamic code execution of eval |
| | 433 | obj.new_method do def new_method ; puts 'born new method in an alive object' ; end ; end |
| | 434 | |
| | 435 | |
| | 436 | |
| | 437 | # example of an "attr_accessor" equivalent writed in dynamic code, which will work in the same way: |
| | 438 | class Class |
| | 439 | def add_accessor(accessor_name) |
| | 440 | self.class_eval %Q{ |
| | 441 | def #{accessor_name} |
| | 442 | @#{accessor_name} |
| | 443 | end |
| | 444 | def #{accessor_name}=(value) |
| | 445 | @#{accessor_name} = value |
| | 446 | end |
| | 447 | } |
| | 448 | end |
| | 449 | end |
| | 450 | |
| | 451 | # You can use this technique to create a multitude of different “code |
| | 452 | # generators” and methods that can act as a “macro” language to perform things |
| | 453 | # in Ruby that are otherwise lengthy to type out. |
| | 454 | |
| | 455 | |
| | 456 | |
| | 457 | # |
| | 458 | # Forks & Processes |
| | 459 | # |
| | 460 | |
| | 461 | # process-ID is returned in the parent but 'nil' in the child, use this to |
| | 462 | # determine which process a script is in |
| | 463 | if fork.nil? |
| | 464 | exec "ruby other-file.rb" |
| | 465 | end |
| | 466 | |
| | 467 | # fork a child and wait for it |
| | 468 | child = fork do |
| | 469 | sleep 3 |
| | 470 | puts "Child says 'hi'!" |
| | 471 | end |
| | 472 | puts "Waiting for the child process..." |
| | 473 | Process.wait child |
| | 474 | puts "All done!" |
| | 475 | |
| | 476 | |
| | 477 | |
| | 478 | |
| | 479 | |
| | 480 | |
| | 481 | |
| | 482 | |
| | 483 | # |
| | 484 | # Unit Testing |
| | 485 | # |
| | 486 | # - default in stdlib is Minitest, but there's also: rspec, minitest, |
| | 487 | # test/unit, minispec, bacon, testrocket... rspec is also very used |
| | 488 | |
| | 489 | # create a method for test it later |
| | 490 | class String |
| | 491 | def titleize |
| | 492 | # we want to use this method for print results like: "This Is A Test" |
| | 493 | self.capitalize |
| | 494 | # and we will end later in improving the code like these next commented |
| | 495 | # lines, because we haven see that the previous test failed in some cases |
| | 496 | #self.gsub(/\b\w/) {|letter| letter.upcase } |
| | 497 | #self.gsub(/\s\w/) {|letter| letter.upcase } |
| | 498 | #self.gsub(/(\A|\s)\w/) {|letter| letter.upcase } |
| | 499 | end |
| | 500 | end |
| | 501 | |
| | 502 | puts "this is a test".titleize # this will print "This is a test", but we don't want this result, so for avoid bugs: |
| | 503 | |
| | 504 | # method 1 for testing (manual testing) |
| | 505 | # let's add some "assertion" checkers |
| | 506 | # |
| | 507 | # if our method doesn't give us what we exactly expect, fail |
| | 508 | raise "Fail 1" unless "this is a test".titleize == "This Is A Test" |
| | 509 | # what happens with numbers? let's add this because this is what we expect in any case |
| | 510 | raise "Fail 2" unless "another test 1234".titleize == "Another Test 1234" |
| | 511 | # and with other chars like ' ? |
| | 512 | raise "Fail 2" unless "We're testing titleize".titleize == "We're Testing Titleize" |
| | 513 | |
| | 514 | # method 2 for testing |
| | 515 | require 'test/unit' |
| | 516 | # there's also "Minitest" (included in stdlib) and "Bacon" for unit testing |
| | 517 | class TestTitleize < Test::Unit::TestCase |
| | 518 | def test_basic |
| | 519 | assert_equal("This Is A Test", "this is a test".titleize) |
| | 520 | assert_equal("Another Test 1234", "another test 1234".titleize) |
| | 521 | assert_equal("We're Testing", "we're testing".titleize) |
| | 522 | end |
| | 523 | end |
| | 524 | |
| | 525 | # method 3 for testing: use Minitest instead, seems like more easier and fast to use option |
| | 526 | module DataStore::AdapterSpec |
| | 527 | it "returns nil for an invalid key" do |
| | 528 | @adapter.get(:invalid).must_equal nil |
| | 529 | end |
| | 530 | |
| | 531 | it "can set a value" do |
| | 532 | @adapter.set(:foo, 42) |
| | 533 | @adapter.get(:foo).must_equal 42 |
| | 534 | end |
| | 535 | end |
| | 536 | # from: http://wojtekmach.pl/blog/2013/07/17/sharing-examples-in-minitest/ |
| | 537 | # more: http://blog.arvidandersson.se/2012/03/28/minimalicous-testing-in-ruby-1-9 |
| | 538 | |
| | 539 | |
| | 540 | |
| | 541 | # |
| | 542 | # Misc |
| | 543 | # |
| | 544 | # run when finish |
| | 545 | at_exit { puts "#{Dir.pwd}" } # enqueue a job for when the application has finished to run |
| | 546 | # trap |
| | 547 | trap("SIGINT") do |
| | 548 | puts "signal INT trapped!, what we should do?" |
| | 549 | end |
| | 550 | |
| | 551 | |
| | 552 | # Using Files |
| | 553 | puts "It exists" if File.exist?("text.txt") |
| | 554 | |
| | 555 | File.open("text.txt") { |f| puts f.gets } # show file contents (cat) |
| | 556 | |
| | 557 | f = File.new("text.txt", "r") |
| | 558 | puts f.gets |
| | 559 | f.close |
| | 560 | |
| | 561 | data = File.read("text.txt") |
| | 562 | array_of_lines = File.readlines("text.txt") |
| | 563 | |
| | 564 | f = File.open("text.txt") |
| | 565 | puts f.gets |
| | 566 | puts "position in file is: " + f.pos |
| | 567 | f.pos = 8 |
| | 568 | puts "position in file has moved to: " + f.pos |
| | 569 | |
| | 570 | # by using File.open in a block, is not needed to close the file when finish |
| | 571 | File.open("text.txt", "w") do |entry| entry.puts "Hi" end |
| | 572 | # note that the next line is invalid, if you put a space before ( then is not an argument list what you pass to it |
| | 573 | #File.open ("text.txt", "w") do |entry| entry.puts "Hi" end |
| | 574 | |
| | 575 | # appending |
| | 576 | f = File.open "text.txt", "a" |
| | 577 | f.puts Time.now |
| | 578 | f.close |
| | 579 | |
| | 580 | # See the modified time of a file |
| | 581 | f = File.mtime "text.txt" |
| | 582 | puts f.hour # since the object returned (f) is a Time object, we can treat him as it |
| | 583 | |
| | 584 | |
| | 585 | # |
| | 586 | # Docs |
| | 587 | # |
| | 588 | # In documentations, "Array#sample" means the instance method of a class |
| | 589 | |
| | 590 | #= RDoc Example |
| | 591 | # |
| | 592 | #== This is a heading |
| | 593 | # |
| | 594 | #* First item in an outer list |
| | 595 | # * First item in an inner list |
| | 596 | # * Second item in an inner list |
| | 597 | #* Second item in an outer list |
| | 598 | # * Only item in this inner list |
| | 599 | # |
| | 600 | #== This is a second heading |
| | 601 | # |
| | 602 | #Visit www.rubyinside.com |
| | 603 | # |
| | 604 | #== Test of text formatting features |
| | 605 | # |
| | 606 | #Want to see *bold* or _italic_ text? You can even embed |
| | 607 | #+text that looks like code+ by surrounding it with plus |
| | 608 | #symbols. Indented code will be automatically formatted: |
| | 609 | # |
| | 610 | # class MyClass |
| | 611 | # def method_name |
| | 612 | # puts "test" |
| | 613 | # end |
| | 614 | # end |
| | 615 | # |
| | 616 | #-- |
| | 617 | # This section is hidden from RDoc and could contain developer |
| | 618 | # notes, private messages between developers, etc. |
| | 619 | #++ |
| | 620 | # RDoc begins processing again here after the ++. |
| | 621 | # |
| | 622 | |
| | 623 | # run "rdoc file.rb" to generate the documentation |
| | 624 | # by adding in a class or element "#:nodoc: all" there's no docs generated (for |
| | 625 | # the entire class) |
| | 626 | |
| | 627 | |
| | 628 | |
| | 629 | # |
| | 630 | # Debug |
| | 631 | # |
| | 632 | # - ruby -d foo.rb: see page 190 of "begining ruby" which has some basic demo |
| | 633 | |
| | 634 | |
| | 635 | # SAFE levels |
| | 636 | # |
| | 637 | # Value of $SAFE Description |
| | 638 | # 0 No restrictions. This is the default safe level. |
| | 639 | # 1 Potentially unsafe methods can’t use tainted data. Also, the current |
| | 640 | # directory is not added to Ruby’s search path for loading libraries. |
| | 641 | # 2 The restrictions of safe level 1, plus Ruby won’t load any external |
| | 642 | # program files from globally writable locations in the filesystem. This is to |
| | 643 | # prevent attacks where hackers upload malicious code and manipulate existing |
| | 644 | # programs to load them. Some potentially dangerous methods are also |
| | 645 | # deactivated, such as File#chmod, Kernel#fork, and Process::setpriority. |
| | 646 | # 3 The restrictions of level 2, plus newly created objects within the |
| | 647 | # program are considered tainted automatically. You also cannot untaint objects. |
| | 648 | # 4 The restrictions of level 3, plus nontainted objects created prior to |
| | 649 | # the safe level being set cannot be modified. You can use this to set up an |
| | 650 | # execution environ- ment in a lower safe mode, and then provide a way to |
| | 651 | # continue execution while protecting the original objects and environment. |
| | 652 | |
| | 653 | |
| | 654 | |
| | 655 | |
| | 656 | |
| | 657 | # |
| | 658 | # MORE: |
| | 659 | # |
| | 660 | # regex: |
| | 661 | # Try regular expressions in realtime! http://rubular.com/ |
| | 662 | # |
| | 663 | # references: |
| | 664 | # http://www.zenspider.com/Languages/Ruby/QuickRef.html |
| | 665 | # http://www.tutorialspoint.com/ruby/ruby_quick_guide.htm |
| | 666 | # "Begining Ruby - book": useful classes and methods, errors, regex, variables, etc... from pag. 575 |
| | 667 | # |
| | 668 | # standard lib: |
| | 669 | # http://www.ruby-doc.org/stdlib-2.1.0/ |
| | 670 | |
| | 671 | }}} |
| | 672 | |