Skip to content
Alex Mikitenko edited this page Dec 1, 2016 · 10 revisions

General notes

These courses contain two kinds of activity: on-line and off-line. On-line is our lessons. Off-line is your home tasks. The second part is optional, but I believe every home task is a key for consolidation the acquired knowledge into practice.

How to do home task

  1. Create a branch from last master named _usernamehometaskN, where username is contributor's GitHub account name, N is a number of the related lesson (the same lettering is used for further agreements).
  2. Write a simple, easy reading code with respect to most popular ruby style guide.
  3. Every task should be placed in a single file like lessonN/username_hometask.rb.
  4. Your work should contains samples which show how the script works. rspec-expectations is a preffered way to manage it.
  5. Do your work due to a home task requirements.
  6. Push it to the remote server and create Pull Request on it.
  7. When you are ready to ask about a review - assign PR to me. It doesn't necessary mean the task is completed, you may need to clarify some things without a request for the final approval.
  8. You can receive some comments from me on the PR. Please, take a look at them. If the PR is assigned to you - the ball is in your court. So, apply suggestions, push latest changes and return PR to me (assign to me).
  9. When you feel your work is done, please squash your commits into one with a simple description "Add hometaskN from username" and force-push your branch before asking final review.
  10. If all conditions above are satisfied (name policy is respected, code is clear, commits are squashed and I am the last assignee of your PR), I will merge your task to the repo. Congrats, you can be proud of yourself!

Tasks per lesson

Hometask 1

  1. Describe Foo class which provide instance method #my_instance. The method should return either :even if the receiver is an even instance of the Foo class or :odd otherwise.
  2. Create one specific Foo instance which should return :uniq as a result of #my_instance method.

Hometask 2

  1. Describe M module contains two methods.
  2. When the module is included into a class:
  • first method should become an instance method of the class, second one - a singleton method
  • output in console result of action above: a list of added instance methods (should be one) and a list of added singleton methods (should be one too).
  1. Create class Foo and include M into it.

HINT: you can use submodules in the M module.

Hometask 3

  1. Develop you own enumerator method :my_each which would duplicate a logic of the system :each method. This method cannot use any other enumerator method inside, but can manage cycles, for example.
  2. Place this method into MyEach module and include it for Array and Hash objects.

Hometask 4

  1. Developer LazyHash class which should be pretty much the same as regular Hash class, but has specific purpose to work with procs. So, it should:
  • manage only symbol keys;
  • have a method accessor for each value in the hash by key (see OpenStruct concept as example which interface do we need);
  • if the accessor points to proc value it should execute it and return result;
  • each such execution should re-associate the value given by result of the proc execution;
  • deal with #method_missing to create these dynamic accessors. Do not use #define_method or #define_singleton_method for such purpouse: it's a tack for next lesson.
  1. Add #lazy? instance method for LazyHash which should provide information is related value a proc object or another kind of object.

NOTE: this task has no reference to similary named lazy pattern

Hometask 5

Do the same what is described in task #4 with single difference: use #define_method or/and #define_singleton_method instead of #method_missing.

Hometask 6

Write mini-DSL which would provide an interface to manage Person objects. A syntax of an object description should be like:

class UserFactory
  person :nonkor do
    name 'Alex Mikitenko'
    sex :male
    age 31
  end

  person :zarina do
    name 'Zarina Mikitenko'
    sex :female
    age 22
    file 'zarina_mikitenko.yml'
  end
end

Person objects could have only attributes: name, sex, age and file. Every attribute should be allowed to be overridden. An access to them should look like:

puts Person.nonkor.inspect # => #<Person:0x007ff51a033948>
puts Person.nonkor.name # => 'Alex Mikitenko'

puts Person.zarina.sex # => :female
puts Person.zarina.age # => 22
puts Person.zarina.file # => 'zarina_mikitenko.yml'

Just after creation, an object should be serialized in a corresponding json file (see file attribute). If file attribute is not specified, symbol which is used for defining object should be used instead. In our case we would have files: nonkor.yml and zarina_mikitenko.yml.

Every attribute should be allowed to be overridden. Person object should also provide method #load! to deserialize object (restore all attributes from a corresponding json file) and #save! to serialize it (update attributes in a corresponding json file). Example:

Person.zarina.load
Person.zarina.age = 10
Person.zarina.save! # => update zarina_mikitenko.yml, her age should be stored as `10` in a result.