TDD in Ruby Course

Tuesday, February 02, 2016

thoughts on sandi metz presentation

Returning nil in the absence of some object means the type changes. Not all of them are ducks. One of them is going to be NilClass. This will not be able to respond to the message sent by the client.

This problem is because the return type from a method is not uniform. If it always returns an object that can respond to a certain message sent by a client, then the program will not crash.

In Java, we can declare interface. Since the interface is implicit in Ruby and it allows returning different types of objects, this leads to problems.

What are the components of an interface?
How can we write code to express the interace ?
Seems like the code will be implicit when it has to express the uniformity or the protocol.
What is a protocol?
What is an interface?

Monday, February 01, 2016

Dave Thomas Presentation Notes

Class names are constant. Why?
Classes are objects.
Class name can be assigned to a variable and used to create an instance.

irb
2.2.4 :001 > String.name
 => "String"
2.2.4 :002 > Class.name
 => "Class"
2.2.4 :003 > BasicObject.name
 => "BasicObject"
2.2.4 :004 > self.name
NoMethodError: undefined method `name' for main:Object
    from (irb):4
    from /Users/bparanj/.rvm/rubies/ruby-2.2.4/bin/irb:11:in `
'
2.2.4 :005 > self.to_s
 => "main"

 String.to_s
 => "String"
2.2.4 :007 > Class.to_s
 => "Class"
2.2.4 :008 > BasicObject.to_s
 => "BasicObject"


Instance variables are stored in current instance.


In the middle of the class, the code is running.
Every method call has a receiver.


puts does not have explicit receiver.
Default object, is always the self (the current object)
We did not create any object. We ask main :
What is the class that is used to create an instance of main?


Methods are not objects. It can be converted to an object.
puts can be converted into an object and we can call puts.

What is the current object?

Example.

No compilation phase.
Definitions are active.
There is always a receiver.

Class definitions is executable.
Everything gets executed.


Instead of doing:

Calling an utility method:

Encryptor.encrypt('secret')

vs

'secret'.encrypt

Sending a message

module Some

end

Some.new

vs

Module.new

class Object


  def to_s
    'main'
  end
end


class Person

  puts self
  puts self.class

end

class Person

  def self.talk
  end

end


class Person

  def self.talk
  end

  Person.talk
end



class Person

  def self.talk
  end

  self.talk

end


class Person

  def self.talk
  end

  talk

end


class Person

  def self.talk
  end

end

Person.talk


class Dumbass < Person

  talk

end

Notes from Smalltalk Presentation by Dan

The real power is in the messaging. The message name represents what and the implementation is hidden behind the method.

Break complex problem down into:

As few parts as possible as independent as possible.
Easier to learn because fewer components.
Productive because the components are re-usable.

Simplicity and Generality

Analysis

Small number of independent parts

Synthesis

Easy to learn
Productive
Maintainable (Built with fewer components)

factorial
self <= 1
  ifTrue: []
 
 
self = 0 ifTrue: [^ 1].
self > 0 ifTrue: [^ self * (self - 1) factorial].
self error: 'Not valid for negative integers'


recFact
self < 0
     ifTrue : [^0]
     ifFalse: [
         self = 0
             ifTrue : [^1]
             ifFalse: [^self * (self -1) recFact]
              ]


Instead of :

loop do
 p 'This will print forever'
end

[ code ] repeat

Ruby Equivalent

(Block Object).repeat

Ignore knowledge about objects. Focus on messages.


Smalltalk

Wednesday, January 27, 2016

Installing Scheme 9.2 on Mac OS 10.10.5

1. Download 64-bit installer mit-scheme-9.2-x86-64.dmg
2. Install Scheme.
3. sudo ln -s /Applications/MIT\:GNU\ Scheme.app/Contents/Resources /usr/local/lib/mit-scheme-x86-64
4. sudo ln -s /usr/local/lib/mit-scheme-x86-64/mit-scheme /usr/local/bin/scheme
5. Type scheme on the terminal.

undefined method `want=' for nil:NilClass (NoMethodError)

In Rails 4.2, you can define your own application specific custom variables in development.rb, test.rb and so on. If you define this:

  config.x.whatever.value.want = 42

It throws the error : undefined method `want=' for nil:NilClass (NoMethodError)

It seems to work only for two levels, so, this will work:

  config.x.whatever.value = 42

You can access the value like this:

Rails.configuration.x.whatever.value

You need to define the custom values by using 'config.x'.

Thursday, January 21, 2016

Error in The Well Grounded Rubyist Book

David Black says "The only circumstances under which you can omit the receiver are precisely the circumstance in which it's ok to call a private method."

 This is not true because we can omit the receiver when we call the class method declared in the superclass. ActiveRecord has_many declaration is an example.

Tuesday, January 19, 2016

Looking for Ruby Book Reviewers

I am looking for technical reviewers to review Essential Ruby Kindle book. I will mention your name and give a link to your site or blog  in the book. If you are interested, please contact me at bparanj at gmail dot com or RubyPlus contact form.

Sunday, January 17, 2016

Tuesday, January 12, 2016

How to find out if a name is reserved in Rails 4.2.5

One of the articles that gets lot of traffic is : Reserved Words in Rails. If you do not use the generator to generate the code in your Rails project, you could potentially have class collision during runtime of your application. Here are the steps I followed:

1. I browsed the railties gem and searched for 'reserved by Ruby on Rails' to find where in the source code the check is done.
2. It is defined in the class rails/generators/base.rb in class_collisions(*class_names) protected method.
3. I went to the rails console to figure out how to use this method:

> require 'rails/generators/base'
NameError: uninitialized constant Rails::Generators::Actions
from /Users/bparanj/.rvm/gems/railties-4.2.5/lib/rails/generators/base.rb:17:in `'
pry(main)> require 'rails/generators/actions'
=> true
 pry(main)> require 'rails/generators/base'
=> true
 pry(main)> g = Rails::Generators::Base.new
=> # @_initializer=[[], {}, {}],
 @_invocations={},
 @after_bundle_callbacks=[],
 @args=[],
 @behavior=:invoke,
 @destination_stack=["/Volumes/Work/dev/ewok"],
 @in_group=nil,
 @options={},
 @shell=#, @mute=false, @padding=0>>
 pry(main)> g.send(:class_collisions, 'ActiveRecord')
Rails::Generators::Error: The name 'ActiveRecord' is either already used in your application or reserved by Ruby on Rails. Please choose an alternative and run this generator again.
pry(main)> g.send(:class_collisions, 'type')
=> ["type"]
pry(main)> g.send(:class_collisions, 'ActiveRecord', 'ActiveJob')
Rails::Generators::Error: The name 'ActiveRecord' is either already used in your application or reserved by Ruby on Rails. Please choose an alternative and run this generator again.



Methods Live in Class

$ irb
2.2.4 :001 > s = 'hi'
 => "hi"
2.2.4 :002 > s.methods
 => [:<=>, :==, :===, :eql?, :hash, :casecmp, :+, :*, :%, :[], :[]=, :insert, :length, :size, :bytesize, :empty?, :=~, :match, :succ, :succ!, :next, :next!, :upto, :index, :rindex, :replace, :clear, :chr, :getbyte, :setbyte, :byteslice, :scrub, :scrub!, :freeze, :to_i, :to_f, :to_s, :to_str, :inspect, :dump, :upcase, :downcase, :capitalize, :swapcase, :upcase!, :downcase!, :capitalize!, :swapcase!, :hex, :oct, :split, :lines, :bytes, :chars, :codepoints, :reverse, :reverse!, :concat, :<<, :prepend, :crypt, :intern, :to_sym, :ord, :include?, :start_with?, :end_with?, :scan, :ljust, :rjust, :center, :sub, :gsub, :chop, :chomp, :strip, :lstrip, :rstrip, :sub!, :gsub!, :chop!, :chomp!, :strip!, :lstrip!, :rstrip!, :tr, :tr_s, :delete, :squeeze, :count, :tr!, :tr_s!, :delete!, :squeeze!, :each_line, :each_byte, :each_char, :each_codepoint, :sum, :slice, :slice!, :partition, :rpartition, :encoding, :force_encoding, :b, :valid_encoding?, :ascii_only?, :unpack, :encode, :encode!, :to_r, :to_c, :unicode_normalize, :unicode_normalize!, :unicode_normalized?, :>, :>=, :<, :<=, :between?, :nil?, :!~, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :singleton_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]
2.2.4 :003 > s.instance_methods
NoMethodError: undefined method `instance_methods' for "hi":String
    from (irb):3
    from /Users/bparanj/.rvm/rubies/ruby-2.2.4/bin/irb:11:in `
'
2.2.4 :004 > String.instance_methods
 => [:<=>, :==, :===, :eql?, :hash, :casecmp, :+, :*, :%, :[], :[]=, :insert, :length, :size, :bytesize, :empty?, :=~, :match, :succ, :succ!, :next, :next!, :upto, :index, :rindex, :replace, :clear, :chr, :getbyte, :setbyte, :byteslice, :scrub, :scrub!, :freeze, :to_i, :to_f, :to_s, :to_str, :inspect, :dump, :upcase, :downcase, :capitalize, :swapcase, :upcase!, :downcase!, :capitalize!, :swapcase!, :hex, :oct, :split, :lines, :bytes, :chars, :codepoints, :reverse, :reverse!, :concat, :<<, :prepend, :crypt, :intern, :to_sym, :ord, :include?, :start_with?, :end_with?, :scan, :ljust, :rjust, :center, :sub, :gsub, :chop, :chomp, :strip, :lstrip, :rstrip, :sub!, :gsub!, :chop!, :chomp!, :strip!, :lstrip!, :rstrip!, :tr, :tr_s, :delete, :squeeze, :count, :tr!, :tr_s!, :delete!, :squeeze!, :each_line, :each_byte, :each_char, :each_codepoint, :sum, :slice, :slice!, :partition, :rpartition, :encoding, :force_encoding, :b, :valid_encoding?, :ascii_only?, :unpack, :encode, :encode!, :to_r, :to_c, :unicode_normalize, :unicode_normalize!, :unicode_normalized?, :>, :>=, :<, :<=, :between?, :nil?, :!~, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :singleton_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]