def things_n_stuff

Adventures in Code

Ruby Inheritance Quiz Answer

Answer Below

The Miniquiz question was, given:

1
2
3
4
5
6
7
8
9
10
11
class Thing < AbstractThing
  include SomeActions
  include OtherActions
  include MoreActions
  extend Existence

  def be
    puts "thing LIVES"
  end

end

If AbstractThing, SomeActions, OtherAction, MoreActions, and Existence all implement a method definition for explode, and we execute the following:

1
2
3
my_brain = Thing.new
my_brain.explode
#=> ...

Where does the method explode get called?

Answer: MoreActions

Demo below

Why? Basic version

When an object has a method called on it, ruby looks to see if that object’s class defines an implementation of that method, and if not looks in that class’s super class, and then that class’s super class, until it reaches Basic Object. (…at which point the process begins again, this time searching for method_missing.)

include-ing a module into a class makes the module’s methods available to all instances of that class, and extend-ing a module into a class makes the module’s available to just that class, as class methods.

In this case, my_brain is an instance of the Thing class, which makes explode an instance method. Therefore, the winning implementation doesn’t come from Existence

It’s possible to both include and extend objects using modules, both instances and classes. It’s really interesting and a bit weird, and seems quite useful to understand. Stay tuned.

Why? Slightly less basic version

The method will be executed as soon as it’s method definition is found. In terms of the class’s methods, included modules, and parent classes, the order of places to look, (the lookup path,) is:

  • first in the methods of the class to which the instance belongs
  • then in each the modules included in that class, in reverse order of inclusion
  • then in the class’ superclasses, their modules, that classes superclass, its modules etc…
  • (There’s more to it, but that’s as far as I need at the moment.)

In the question prompt, my_brain is an instance of the Thing class. And MoreActions is the last module included into the Thing class. Therefore, provided that Thing class doesn’t define an explode method, MoreActions is the next place ruby would search, and the if it finds it there it will execute MoreActions’s explode method irrespective of any implementation in the earlier included methods or the parent classes.

Demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class AbstractThing
  def explode
    'BOOM from AbstractThing'
  end
end

module SomeActions
  def explode
    'BOOM from SomeActions'
  end
end

module OtherActions
  def explode
    'BOOM from OtherActions'
  end
end

module MoreActions
  def explode
    'BOOM from MoreActions'
  end
end

module Existence
  def explode
    'BOOM from Existence'
  end
end

class Thing < AbstractThing
  include SomeActions
  include OtherActions
  include MoreActions
  extend Existence

  def be
    puts "thing LIVES"
  end
end



> my_brain = Thing.new
#=> #<Thing:0x007faa029145c0>
> my_brain.explode
#=> "BOOM from MoreActions"

I’m going to turn on commenting soon so you wonderful people can tell me what I’ve made mistakes on. For everything that’s correct, massive credit due to Dave Thomas’ and Sandi Metz’s books.


Ruby Inheritance Quiz - Beginner/Intermediate

Miniquiz. Given:

1
2
3
4
5
6
7
8
9
10
11
class Thing < AbstractThing
  include SomeActions
  include OtherActions
  include MoreActions
  extend Existence

  def be
    puts "thing LIVES"
  end

end

If AbstractThing, SomeActions, OtherAction, MoreActions, and Existence all implement a method definition for explode, and we execute the following:

1
2
3
my_brain = Thing.new
my_brain.explode
#=> ...

Where does the method explode get called?

Answer will be posted: 10/16

Symbolic Links, Unix

There’s 2 types: soft links and hard links.

What they are:

Soft links tell the system to open the target of the link, ie the thing for which you’re creating a link. It’s just a reference to the original file. It’s a bit like how an alias operates in a GUI, and points the system to the right location to use the original.

Hard links point directly to a physical piece of data, to the file itself. (Whereas the soft link is a reference to the name of the file, the hard link is another name for the data itself.) Methinks that by the time you’ll be needing to make hard links you’ll probably know what, why, and how. So I’ll just talk about soft sym links.

How:

The syntax is: ln -s [file] [symlink_name], where both quantities are file names or full paths plus file name.

Demo:

Making a file and a link to it:

1
2
3
4
5
6
7
8
9
10
> echo 'puts "hi from the linked file"' > target_of_link.rb
> ruby target_of_link.rb
#=> puts "hi from the linked file"

> ls target*
#=> target_of_link.rb

> ln -s target_of_link.rb link_pointing_to_the_target_file.rb
> ls *target*
#=> link_pointing_to_the_target_file.rb target_of_link.rb

Afterwards, anything called on that link will act as if called on the original, as if the link didn’t even exist

1
2
3
4
5
6
7

> ruby link_pointing_to_the_target_file.rb 
#=> hi from the linked file

> less link_pointing_to_the_target_file.rb 
#=> puts "hi from the linked file"
  link_pointing_to_the_target_file.rb (END)

Removing the sym link:

Done the same as for any other file. And rest assured, removing the symbolic link doesn’t remove the target of that link.

1
2
3
> rm link_pointing_to_the_target_file.rb 
> ls *target*
#=> target_of_link.rb
Naming:

As far as I know the name of the link doesn’t matter at all, but it’s a good idea to name it similarly to or with the same extension as the original, so future devs know how to call the file.

Moved files:

The soft symbolic link, unlike Mac OSX GUI aliases, doesn’t follow the target file if it’s moved.

Let’s start over. Make the file and sym link:

1
2
3
4
> echo 'puts "hi from the linked file"' > target_of_link.rb
> ln -s target_of_link.rb link_pointing_to_the_target_file.rb
> ls *target*
#=> link_pointing_to_the_target_file.rb target_of_link.rb

Move the target:

1
2
> mkdir new_and_exotic_location/
> mv target_of_link.rb new_and_exotic_location/

Yup, it’s there:

1
2
3
4
> ls *target*
#=> link_pointing_to_the_target_file.rb
> ls new_and_exotic_location/*target*
#=> new_and_exotic_location/target_of_link.rb

But try to execute the sym link, and the system doesn’t know what’s being referenced:

1
2
> ruby link_pointing_to_the_target_file.rb 
#=> ruby: No such file or directory -- link_pointing_to_the_target_file.rb     (LoadError)

Righto. Over and out.

Outdated RVM and OpenSSL Certificate Errors - a PSA

A small public service announcement from the wee hours of the morning.

I was getting errors trying to bundle in applications for an odd error I’d never seen before:

1
 ERROR: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

So I tried to update my gems:

1
2
3
rvm gemset update
Running gem update for all rubies and gemsets.
Only 'do' action is allowed.

I’d never seen these before and was a bit perplexed. Luckily…

Simple cause, easy solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
If you’ve installed RVM, try this:

$ rvm -v
#=> rvm 1.23.4 (stable)... 
$ rvm osx-ssl-certs status all
#=> Certificates for...
$ rvm osx-ssl-certs update all
#=> Updating certificates...
That’s all that is needed to resolve the issue if you are using RVM (you must be using RVM version 1.19.1 or newer).

For more on the issue, see a discussion at add rvm osx-ssl-certs on GitHub.


#####Staying Healthy
In a year or two, the error may reappear, when the certificate files again become outdated. To keep the certificate files current, RVM offers an option to run a cron job that updates the certificate files daily.

$ sudo rvm osx-ssl-certs cron install

Reposted in entirety from the excellent original article, which you should check out anyway. The link includes info for rbenv, macports, older rubies, and associated issues.

Ruby’s Zip Method

Always start by reading the ruby docs. The .zip method is implemented in the Array class and Enumberable module, below, here.

Basics

.zip is useful for combining collections in an ordered way. We’ll first call it with two collections, one as the message receiver and one as the message’s argument: array.zip(other_array) The order is irrelevant for now. .zip will return arrays made by combining the collections piece by piece.

So far, simple:

1
2
[1,2,3].zip(['a', 'b', 'c'])
#=> [[1, "a"], [2, "b"], [3, "c"]]

.zip can also take 2 (or more) arguments to zip into the first:

1
2
['a', 'b', 'c'].zip( [1,2,3], ['oogie', 'boogie', 'booger'] )
#=> [["a", 1, "oogie"], ["b", 2, "boogie"], ["c", 3, "booger"]]

What it’s doing

.zip walks over each of the collections, collecting one element from each and returning the resulting collected array. It then repeats that process until it’s made one pass over each element from the collections. The resulting arrays from each of these passes is collected and returned as an array of those collected arrays. I find this illustration helpful:

1
2
3
4
['FIRST-1', 'FIRST-2', 'FIRST-3'].zip( ['SECOND-1','SECOND-2','SECOND-3'], ['THIRD-1', 'THIRD-2','THIRD-3'] )
#=> [  ["FIRST-1", "SECOND-1", "THIRD-1"], 
       ["FIRST-2", "SECOND-2", "THIRD-2"],
       ["FIRST-3", "SECOND-3", "THIRD-3"]  ]

Unequal collections, returned array lengths

If the argument collection sizes are unequal, .zip places nils in the zipped up arrays:

1
2
3
4
['FIRST-1', 'FIRST-2', 'FIRST-3'].zip( ['SECOND-1'], ['THIRD-1', 'THIRD-2'] )
#=> [  ["FIRST-1", "SECOND-1", "THIRD-1"],
       ["FIRST-2", nil, "THIRD-2"],
       ["FIRST-3", nil, nil]  ]
Careful:

The number of arrays returned by .zip is determined by the length of the receiver collection. Here, the receiver ['FIRST-1', 'FIRST-2'] has a length of 2 items. Notice that the ['SECOND-3'] item doesn’t get zipped-in or included at all:

1
2
3
['FIRST-1', 'FIRST-2'].zip( ['SECOND-1','SECOND-2','SECOND-3'], ['THIRD-1'] )
#=> [  ["FIRST-1", "SECOND-1", "THIRD-1"], 
       ["FIRST-2", "SECOND-2", nil]   ]

… and here again, the receiver has a length of 1, so the zipped array has a length of 1 regardless of the length of its args. The result is an array that contains one zipped array of content collected from each collection:

1
2
['FIRST-1'].zip( ['SECOND-1','SECOND-2','SECOND-3'], ['THIRD-1', 'THIRD-2','THIRD-3', 'THIRD-4'] )
#=> [  ["FIRST-1", "SECOND-1", "THIRD-1"]  ]

Back to text

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
(from ruby core)
=== Implementation from Array
------------------------------------------------------------------------------
  ary.zip(arg, ...)                   -> new_ary
  ary.zip(arg, ...) {| arr | block }  -> nil

------------------------------------------------------------------------------

Converts any arguments to arrays, then merges elements of self with
corresponding elements from each argument. This generates a sequence of
self.size n-element arrays, where n is one more that the count of
arguments. If the size of any argument is less than enumObj.size, nil values
are supplied. If a block is given, it is invoked for each output array,
otherwise an array of arrays is returned.

  a = [ 4, 5, 6 ]
  b = [ 7, 8, 9 ]
  [1,2,3].zip(a, b)      #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
  [1,2].zip(a,b)         #=> [[1, 4, 7], [2, 5, 8]]
  a.zip([1,2],[8])       #=> [[4,1,8], [5,2,nil], [6,nil,nil]]


(from ruby core)
=== Implementation from Enumerable
------------------------------------------------------------------------------
  enum.zip(arg, ...)                   -> an_array_of_array
  enum.zip(arg, ...) {|arr| block }    -> nil

------------------------------------------------------------------------------

Takes one element from enum and merges corresponding elements from
each args.  This generates a sequence of n-element arrays, where n
is one more than the count of arguments.  The length of the resulting sequence
will be enum#size.  If the size of any argument is less than enum#size, nil
values are supplied. If a block is given, it is invoked for each output array,
otherwise an array of arrays is returned.

  a = [ 4, 5, 6 ]
  b = [ 7, 8, 9 ]

  [1,2,3].zip(a, b)      #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
  [1,2].zip(a,b)         #=> [[1, 4, 7], [2, 5, 8]]
  a.z
Extra credit

Because .zip is implemented in the Enumerable module also, you can call .zip on anything you turn into an Enumerator object (ie., anything that you call enumerable methods (to which it responds) on without a block) in the same way.

So, while:

1
2
3
4
5
6
7
8
9
10
11
12
'eyyo'.zip('ummmm')
#=>NoMethodError: undefined method `zip' for "eyyo":String

# so make 'eyyo' into an Enumerator, and it'll behave just like an array of it's elements

'eyyo'.chars.zip('ummmm')
#=>NoMethodError: undefined method `each' for "ummmm":String

# ah, but awesome ruby says the arg needs to be an enumerator object too, so:

'eyyo'.chars.zip('ummmm'.chars)
#=> [["e", "u"], ["y", "m"], ["y", "m"], ["o", "m"]]

And a last example for good measure. The following two are equivalent, and remember that both would return nil:

1
2
3
4
5
6
7
8
9
10
11
'wct'.chars.zip( 'ohh'.chars, 'wei'.chars, 'zcs'.chars, 'ak'.chars ){|x| puts x.join }
  wowza
  check
  this
#=> nil
-------
['w','c','t'].zip( ['o','h','h'],['w','e','i'],['z','c','s'], ['a','k']){|zipped_array| puts zipped_array.join}
  wowza
  check
  this
#=> nil

You’d think there’d be an unzip method too, but doesn’t seem so.

Anyway, go play!

For a different take with practical examples, testing, and source code, check out this post.

Today in ‘Awesome Rails Tidbits: Warm and Squishy Version’

This morning I was scraping and parsing data and came across this ugly string that I needed to save to the db:

1
string = "\n\t\t\t\tOh my gosh check - (out this string) 75-3\n\n\t\t\t\t453rd Prm. (random, other, 8, *&^, 'it's ugly as heck')))\n\n\t\t\t\t(other random(nested things)) followed by 33, stuff\n\n\n\t\t\t\n"

I only needed the text and punctualtion from it, but none of the line-breaks or tabs and spacing.

My ‘just make it work’ first swing at it was this inelegant mashup of regex and method chaining, removing the formating characters:

1
2
> string.gsub(/[\n+\t+\s+]/,' ').split.join(' ').strip
#=> "Oh my gosh check - (out this string) 75-3 453rd Prm. (random, other, 8, *&^, 'it's ugly as heck'))) (other random(nested things)) followed by 33, stuff"

… and shortly thereafter I discovered Rails’ beautiful squish method. From rdoc:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(from gem activesupport-4.0.0)
=== Implementation from String
------------------------------------------------------------------------------
  squish()

------------------------------------------------------------------------------

Returns the string, first removing all whitespace on both ends ofthe string,
and then changing remaining consecutive whitespacegroups into one space each.

Note that it handles both ASCII and Unicode whitespace like mongolian vowel
separator (U+180E).

  %{ Multi-line
     string }.squish                   # => "Multi-line string"
  " foo   bar    \n   \t   boo".squish # => "foo bar boo"

And like beautiful concise magic, voilà:

1
2
> string.squish
# => "Oh my gosh check - (out this string) 75-3 453rd Prm. (random, other, 8, *&^, 'it's ugly as heck'))) (other random(nested things)) followed by 33, stuff"

Clean and useful.

Ruby Versions and Gemsets for Beginners

The idea of having multiple versions of ruby and multiple gemsets for each on your system at the same time, was confusing and abstract for me when I first started messing with ruby. So I dug in a bit to learn the landscape:

Why Gems in the first place?

Gems are just handy programs and libraries of code. Made a little X that helps you do something in all of your code? Wrap it up into a neat, self contained little package with RubyGems (upcoming post) and distribute it to the rest of the amazing ruby community to use! That package is called a gem.

Some gems prove incredibly useful and receive wide adoption, to the point where they are considered a standard part of using and building with ruby, such as rake, or a framework, such as Rails and Sinatra. Rails, Sinatra, rake, jQuery, etc. are all distributed as gems.

Programming languages are constantly evolving and being improved, as are the gems. It’s impossible for developers to improve and extend programming languages and programs while maintaining perfect compatibility with every gem or application built with it. If your whole application depends on the mrhappytime gem and that gem works perfectly with ruby version 2.0.0, it’s possible that it won’t work at all with version 2.0.1. Gemsets and package managers like RVM and rbenv try to help solve this dependency trap by tying together versions of ruby and gems that already play well, and helping you organize and manage them.

Context:

A developer can have lots of rubies and gemsets on their system. First things first, everyone should know what version of ruby your currently running with ruby -v on my system:

ruby -v
ruby 1.9.3p429 (2013-05-15 revision 40747) [x86_64-darwin12.3.0]

Again, ruby lets you keep various versions of ruby and various gemsets. A few basic exploratory commands (some using rvm, clearly):

rvm list known
* lists out all the versions and types of ruby ‘out there’

rvm list rubies
* lists just the different versions of ruby installed. ruby-#.#.# is the ruby version, and the -p### is the particular build. For me:

ruby-1.9.3-p429 [ x86_64 ]
ruby-2.0.0-p195 [ x86_64 ]
ruby-2.0.0-p247 [ x86_64 ]

gem list
* shows all gems installed locally, and the available versions of each

rvm list gemsets
* shows all rubies and gemsets installed locally. the part following the @ symbol is the name of the gemset. on my system:

1
2
3
4
5
6
7
8
9
10
11
ruby-1.9.3-p429 [ x86_64 ]
ruby-1.9.3-p429@global [ x86_64 ]
ruby-1.9.3-p429@rails3.2.13 [ x86_64 ]
ruby-2.0.0-p195 [ x86_64 ]
ruby-2.0.0-p195@global [ x86_64 ]
ruby-2.0.0-p195@rails3.2.13 [ x86_64 ]
ruby-2.0.0-p195@testtestgem [ x86_64 ]
ruby-2.0.0-p247 [ x86_64 ]
ruby-2.0.0-p247@global [ x86_64 ]
ruby-2.0.0-p247@rails3.2.13 [ x86_64 ]
ruby-2.0.0-p247@rails4.0.0 [ x86_64 ]

Each gemset collection is independent of the others, so, for instance, if you have rails version 3.2.13 installed in one and switch to a new gemset you’ll have to reinstall it.

Next

create, delete…

tying a directory to a version of ruby and a gemset- why? how different than using bundle? – bundle you’ll have to reinstall the gems each time you arrive at the project, if you’re not ‘in’/using the current gemset. – using the folder thing, you can make sure that whatever version of ruby and all of the billions of gems you might be using for a project, and their specific versions are all ‘there’ whenever you cd into that directory.

what’s the difference between so why do we need the gemfile and gemsets? can’t we fix all this with bundle?

to set a version of ruby for a given director: just need a .ruby file, with the ruby version in it

```
Show the present version of ruby
$> ruby -v
#=> ruby 1.9.3p429 (2013-05-15 revision 40747) [x86_64-darwin12.3.0]

$> mkdir testtest
$> cd testtest/

# Version still the same
$> ruby -v
#=> ruby 1.9.3p429 (2013-05-15 revision 40747) [x86_64-darwin12.3.0]

# Writes the string "2.0.0" to the .ruby-version file, which is created at the time of writing. cat simply prints out the contents of the file.  you can also open it with sublime etc and see what's there or edit it.

$> echo 2.0.0 > .ruby-version 
$> cat .ruby-version
#=> 2.0.0

# version?
$> ruby -v
#=> ruby 1.9.3p429 (2013-05-15 revision 40747) [x86_64-darwin12.3.0]

# leave and return to the dir for the changes to take effect
$> cd ..
$> cd -
$> ruby -v
#=> ruby 2.0.0p195 (2013-05-14 revision 40734) [x86_64-darwin12.3.0]
```

alternative to echoing and piping is to:
rvm --ruby-version use 1.9.3
--- which automatically creates the .ruby-verson file and adds the ruby v number to it

the slightly older way of doing this is by using the .rvmrc file, but if you use the .ruby-versions file your instructions are compatible with other ruby version managers like rbenv and chubby (link: ….) you can also specify the gemset in the same file by writing in the version number plus the gem, like: 2.0.0@gemname_to_use, but that might break this compatibility. rvm suggests using a separate .ruby-gemset file gemset basics resource at rvm: http://rvm.io/gemsets/basics“`

```
if you want to use an existing gemset called @mygemset
rvm --ruby-version use 1.9.3@my_app
------- makes a .ruby-version file and the .ruby-gemset file

if you just specify the gemset, it will just use the current gemset
rvm --ruby-version use @global
if you want to create a new gemset at the same time, simply append --create to the end
$> rvm --ruby-version use @testtestgem --create
$> rvm list gemsets
…
…
#=> ruby-2.0.0-p195@testtestgem [ x86_64 ]

side note: you may have notice, that if you’ve already made one of these files, rvm will now time-stamp it and move it aside without deleting it

Again on the better late than never: gemsets are somewhat obsolete because of the awesomeness of bundle, but still “useful for binaries” – ie versions – so you can switch to a version and and start a new rails app etc.

https://rvm.io/workflow/projects#ruby-versions http://stackoverflow.com/questions/15708916/use-rvmrc-or-ruby-version-file-to-set-a-project-gemset-with-rvm

Connecting Ruby & Active Record Without Rails

Building Towards Rails

I’ve been messing with a practice app to get better at domain modeling, TDD, and the guts of Ruby and Rails. The plan was to build up an app of a few classes, give it persistence, and roll onto the web. When it came time to persist data I figured it would be easy enough to use in active record (AR) without the whole rails framework, and it is, but it can definitely be confusing.

I read and really appreciated this article on using AR in sinatra apps, and found this and and especially this very useful context. I’ll write about the initial stages of building this thing later if I’ve time.

Setup

I first built out a small flashcard application with classes for cards, decks, study sessions, and the interface. I wanted to complicate things by having cards shared between decks, mixes of cards and decks within a study session, and marking of cards with “degrees of certainty” for use with timed and spaced repetition learning techniques. That was when I knew that it was time for a database, and instead of just grabbing one and making my own ORM, I turned to active record.

Active record works just fine and dandy without rails, but it needs things to be just so. To start, get the gem and add it to your gemfile. Next, make all of your classes inherit from AR like so:

class FlashCard < ActiveRecord::Base
...
end

Then you need to require it in the right places. Initially I was requiring AR from the file containing each class, but this was messy and confusing. So instead I moved to a solution that I’d seen Avi put into the CLI playlister project, which helped clean things up: I made a separate file for the entire environment called environment.rb, and made it do all of the requiring for my min-app. The environment file requires AR, points AR to the database file to use, and then requires each of the models. Then the classes don’t have to require anything.

# environment.rb
# recursively requires all files in ./lib and down that end in .rb
Dir.glob('./lib/*').each do |folder|
  Dir.glob(folder +"/*.rb").each do |file|
    require file
  end
end

# tells AR what db file to use
ActiveRecord::Base.establish_connection(
  :adapter => 'sqlite3',
  :database => 'flash_card_app.db'
)

Again, this is lovely because it lets me simply require environment.rb in everything else and then the enviroment file requires all of the models and AR, and any model that inherits from AR will work fine. (Side note: don’t expect your classes to simply work like normal after pluggin in AR. As soon as you make a class an AR child, you need to switch over to the rails Associations paradigm, remove initialize methods, and fix your getters and setters etc.)

Migrations

Part of the beauty of AR is that it helps you alter, add to, and remove from databases in logical and controllable ways. Without the framework there’s no nifty rails g migration yada yada yada… So you write migrations by hand. I put my migrations in a db/migrations/ structure to mimic rails. Here’s my join-table migration:

#004_create_deck_study_sessions_table.rb
require_relative '../../environment'

class CreateDeckStudySessionsTable < ActiveRecord::Migration

  def up
    create_table :deck_study_sessions do |t|
      t.integer :deck_id
      t.integer :study_session_id
    end
    puts 'ran up method'
  end 

  def down
    drop_table :deck_study_sessions
    puts 'ran down method'
  end

end

It should look nearly exactly like what it would look like within the framework, except that it’s requiring that environment.rb file. Be sure to follow the AR/Rails naming conventions which I mess up all the time. For more on migrations in general and naming, check out the guide.

Applying Migrations

Requiring AR and wiring the classes and migrations is all well and good, but in order to make changes to our db we need to run the migrations. Without Rails we don’t have rake tasks for db:migrate, and my initial thought was to learn more about the way that AR applies and rolls-back migrations before diving into my own rake tasks. Seemed a bit out of scope for this little project, and perhaps one yak who’s beard I could leave alone.

Another way to run the migrations is to load everything (for me just environment.rb) into irb or pry and manually run the migrations there. It’s a bit weird but works. The argument to pass in is the method name: up, down, or change. From within irb, require environment.rb, then:

>require './db/migrations/002_create_study_sessions_table.rb'
=> true
CreateStudySessionsTable.migrate(:up)
==  CreateStudySessionsTable: migrating =======================================
-- create_table(:study_sessions)
   -> 0.0028s
==  CreateStudySessionsTable: migrated (0.0029s) ==============================
=> nil

>require './db/migrations/003_create_decks_table.rb'
=> true
CreateDecksTable.migrate(:up)
==  CreateDecksTable: migrating ===============================================
-- create_table(:decks)
   -> 0.0030s
ran up method
==  CreateDecksTable: migrated (0.0032s) ======================================
=> nil

>require './db/migrations/004_create_decks_study_sessions_table.rb'
=> true
CreateDeckStudySessionsTable.migrate(:up)
==  CreateDeckStudySessionsTable: migrating ==================================
-- create_table(:decks_study_sessions)
   -> 0.0026s
ran up method
==  CreateDeckStudySessionsTable: migrated (0.0027s) =========================
=> nil

Ugly but it works. I didn’t like running these via irb (and subsequently forgetting how I ran them), so I moved the commands to migrate into the various migration files, like so:

#004_create_deck_study_sessions_table.rb
require_relative '../../environment'

class CreateDeckStudySessionsTable < ActiveRecord::Migration

  def up
    create_table :deck_study_sessions do |t|
      t.integer :deck_id
      t.integer :study_session_id
    end
    puts 'ran up method'
  end 

  def down
    drop_table :deck_study_sessions
    puts 'ran down method'
  end

end

CreateDeckStudySessionsTable.migrate(:up)

For the moment I’m just running my migrations one at a time manually, which is definitely not the “right way” to manage them, but ok if you just want to verify that everything is connected and associated properly. (If you make a rake task or a ruby script to handle migrations, don’t forget to make sure that AR is only applying or changing the latest migration each time.)

Lastly, I wanted to be able to pass in the method to the migration when I run it from the commandline, so I changed

#004_create_deck_study_sessions_table.rb
…
CreateDeckStudySessionsTable.migrate(:up)

to

#004_create_deck_study_sessions_table.rb
…
CreateDeckStudySessionsTable.migrate(ARGV[0])

and now migrations can be run from the commandline.

1
2
3
> ruby db/migrations/004_create_deck_study_sessions_table.rb down
-- drop_table(:deck_study_sessions)
   -> 0.0013s

Again, this is an fairly manual off-label fix and not suitable if you’re building an app that you expect to live with for a while. Fine in a pinch.

Update:

Filed under better late than never: I just came across an article by Wes Bailey on running migrations without rails that makes life easier and offers a much more properly programmatic way of running migrations without the whole framework, via rake tasks. Take a look: “ActiveRecord migrations without Rails”

Parallel Assignment in Ruby

The Problem:

How do you iterate over two collections, and at the same time generate a new, third collection based on elements selected from the previous two? In other words, how do I create a list of paired things by ticking down two others?

The things that I’ve been wondering about and now love:

  1. Enumerator (new love)
  2. Enumerable (rediscovered love)
  3. Inject (constantly blows my mind)

I first came across this problem during the decoder exercise early on at the Flatiron School. I had an encoded message and a cypher, and I wanted to make a new hash by iterating over both and setting the cypher as a key and the code as its value. There are tons of workarounds but I got a bit fixated on doing it more or less in one go.

More recently I’ve been perplexed by the Enumerator class. One super cool thing it lets you do is keep track of internal position. What this means is that after you set it up, you can do:

# incomplete:

thing = ['oogie', 'boogie', 'blork']
> thing.next
=> "oogie"
> thing.next
=> "boogie"
> thing.next
=> "blork"

All that’s needed to unlock this capability is to call the collection with an enumerable method, sans block. And the only requirement is that the method includes an implementation of each, which as far as I know is every method in Enumerable. So:

> thing = ['oogie', 'boogie', 'blork'].each
=> #<Enumerator: ...>

Once you’ve made an Enumerator object, you can access this amazing ‘internal tracker’.

> thing = ['oogie', 'boogie', 'blork'].each
=> #<Enumerator: ...>
> thing.next
=> "oogie"
> thing.next
=> "boogie"
> thing.next
=> "blork"

Side note, Ruby also has the nifty to_enum method that turns anything into an object of the Enumerator class. So (1..4).each is equivalent to (1..4).to_enum, though they are different instances of the Enumerator class.

> (1..4).each.inspect
=> "#<Enumerator: 1..4:each>"
> (1..4).to_enum.inspect
=> "#<Enumerator: 1..4:each>"
> (1..4).each === (1..4).to_enum
=> false
> (1..4).each.object_id
=> 70349656520460
> (1..4).to_enum.object_id
=> 70349656484240

Next, lets add some inject to the mix.

Inject is mindblowing and has tons of uses and applications, but it basically works by taking a collection and doing something to each element in context of the previous element. A basic example is summing numbers:

> [1,2,3,4,5].inject {|sum, next_thing| sum + next_thing}
=> 15

Here inject is grabbing the first item in the array, adding the second item to it, and then using that as the new total, before continuing to add subsequent items in the same way. Interestingly, inject also lets you pass an argument before the block to use as the starting value.

> [1,2,3,4,5].inject(50) {|sum, next_thing| sum + next_thing}
=> 65

And because you can easily pass things into arrays and hashes, you can also slip in an empty one as your starter. Don’t forget to specify that you want the new collection returned.

> [1,2,3,4,5].inject({}) {|array, item| array[item] = []; array}
=> {1=>[], 2=>[], 3=>[], 4=>[], 5=>[]}

Lastly, by combining Enumerator and inject you can make one neat, succinct, clear, and logical iterator that’s (sort of) running 2 parallel iterations.

> letters = ('a'..'z').each
=> #<Enumerator: ...>
> gg = (1..26).inject({}){|hash, key| hash[key]=[letters.next]; hash}
=> {1=>["a"],
    2=>["b"],
    3=>["c"],
    4=>["d"],
    5=>["e"],
    6=>["f"],
    7=>["g"],
    8=>["h"],
    9=>["i"],
    10=>["j"],
    11=>["k"],
    12=>["l"],
    13=>["m"],
    14=>["n"],
    15=>["o"],
    16=>["p"],
    17=>["q"],
    18=>["r"],
    19=>["s"],
    20=>["t"],
    21=>["u"],
    22=>["v"],
    23=>["w"],
    24=>["x"],
    25=>["y"],
    26=>["z"]}  

Nifty eh?

After writing this I became fascinated with making a method that could take 2 collections of arrays, hashes, or ranges, and a last argument for the rate of iterating over each collection relative to the other. In the works, stay tuned.

Code Health

Code Health ≈ Coder Health

Today’s post is really just a simple resolution. Learning at the Flatiron School is really intense and awesome. This week I realized that I have let slide too many things that help keep me healthy and sane, and a decently pleasant person. No more. I moved to New York the day before class started, and it’s been difficult to build a supporting routine. Starting this weekend and for the remainder of the course I will:

  1. get sufficient sleep (almost) every night, regardless of how I’m feeling about my level of understanding about something vs what it “should be”, or how badly I want to work on a project. Sleep should only be lost for truly unique chances for work or fun. Short-term deficits are ok, long-term ones are counter-productive. I entered this week with a huge sleep deficit and a bit run down, and that’s prevented me from absorbing material the way I would’ve liked and being as productive as I should have. Strategic error!
  2. exercise a minimum of three times a week, regardless of the temperature outside or the somewhat intimidating crowds at the gym. Interval days in the park, and circuit days (somehow) in the gym or the park. (Anyone know a park with something to do dips on?)
  3. figure out a better system for feeding myself! Day and evening lunches downtown are crazy expensive. I either need to spend a few hours on the weekend cooking meals (at least lunches) for the week, or dig up better recommendations for cheap and decently healthy grub in the area.
  4. tell the other people in the class how stupidly disgustingly awesome they are, far more frequently.
  5. taper and quit my new thyroid medication. My doc gave me a new drug about 3-ish weeks ago, and I want to forestall the possibility that it’s effecting my mood, energy, focus, memory, retention, or sleeping patterns.
  6. be more social outside of class! More coffees, meals, drinks, and group work, even on projects that aren’t explicitly group-related. I really like people and really like pair-programming.
  7. be thicker-skinned about asking for help, repeatedly, even when everyone is trucking along and doing their own thing.
  8. be more reflective and appreciative of the advances that I’ve already made with code, and thinking in code. Vocalize this more with “I”s and “We”s. It’s pretty amazing really. I still suck compared to the full range of capability of programmers obviously, but have learned a ton about working in teams, myself, code, reasoning via code, and the freedom and expressiveness that certain code limitations and patterns offer. I’m definitely proud of some of the new things I’m capable of or beginning to develop, especially the softer more intangible skills. I’m really happy how addicted I am to figuring stuff out.
  9. indulge that addiction more! Allow time for more code-related ‘focused distraction’, by which I mean time-blocked dives into random processes that I don’t or semi understand. Play yeilds knowledge and wisdom!
  10. figure out some ways to contribute more to our school community. This place and these people are pretty wonderful, and I want to do more stuff for them. But it gets tricky when everyone is so self sufficient and generally awesome…

Anyway, I love you all and want to be a better coder and happier and better person for you. Yes you. I know, aww…