Ruby modules and mixins

Tags

, , ,

Continuing on the OO theme from my last post I’ll look at Modules and Mixins.

Modules
Modules are a great way to group methods, classes and constants in your Ruby application. Modules define a namespace, think of a namespace as an area where methods and variables can safely exists where name clashes are prevented. Define your module like this:

module ModuleName

Then include the new module in your program using the require or require_relative keyword. Reference the module and method in your code like this:

ModuleName.method

You should note that a module cannot have an instance as it is not a class.

Mixins

Before moving onto Mixins you should understand that Ruby is a single inheritance language, similar to C# or Java. This means that a class can have only one parent. However, Ruby offers a neat work-around by offering mixins. Modules can’t have an instance but they can be mixed into the definition of a class. Mixins provide the functionality of a superclass without violating the single inheritance.

To use a module in a class use the keyword include after the class definition to include the module. If the module is in another file use the require keyword first and then include

module MyModule
 #code here
end
 
class MyClass
#optionally require MyModule if in another file
 include MyModule
end

Ruby includes a reference to the module when its included in the class so any change to the module affects every class that includes it.

Beware that class instance variables and mixin variables names can clash so come up with and appropriate naming scheme. Generally, a mixin that needs its own state should be its own class.

When designing your code, follow the ‘is-a’ approach to creating classes and subclasses. The ‘uses-a’ or ‘has-a’ relationship is a good area to start for mixins or dependency injection.

Advertisements

Ruby inheritance

Tags

, , ,

Ruby is a single inheritance language but the ability to leverage modules and mixins offers a method to leverage a more multi inheritance style.

Inheritance

Ruby, like other popular OO languages utilizes inheritance. To denote that there is a child/parent relationship use the ‘<'

class Child < Parent
 def some_method
 end
end

If you create a class that has no superclass Ruby automatically makes the built in class of ‘BasicObject’ as the superclass. Prior to Ruby 1.9 the equivalent to the ‘BasicObject’ was ‘Object’. Now ‘Object’ is a child class of ‘BasicObject’

If you call a method on a child class or a or any other class, Ruby will continue to look up the chain of parent objects until that method is found or it runs out of classes to look for. You can also override any superclass method by declaring that method in your child class. Don’t forget that if you subclass an existing class you become responsible for ensuring all conditions of that class being met, especially during the initialization method are met. To pass parameters to the superclass from the subclass use the keyword super. Used within a method in the subclass it will pass any of the parameters used in the method call to the method of the same name in the superclass.


def initialize (var)
  super
end

When creating a subclass it is best to think of the relationship with the superclass in terms of a ‘is_a’ relationship or is the subclass somehow derived from the superclass. An example might be: a cat is ananimal where ‘animal’ is a parent class and ‘cat’ is a subclass. Using subclassing with ‘has_a’ thinking tends to muddy the class and insert confusion into your domain model. If your subclass needs some external functionality don’t subclass from a non-related class, instead try something like dependency injection.

Ruby instance vs class variables

Tags

, ,

While I was working on a recent Ruby project I found myself a bit confused over distinction between Ruby’s instance and class variables. I am on the newer side of using Ruby and I have found that explaining concepts is a good way for me to remember something. So here goes.

Instance Variables

You can easily recognize instance variables by the ‘@’ prefixing them and as you can surmise from their name they are tied to the instance of the object they are declared in.  Their scope is related to whatever the object self is. Different objects derived from the same class will have different instance values.

class Test
 def some_method(value)
  @foo = value
 end
end
obj = Test.new
obj.some_method(5)
@foo is now 5

 
Instance variables cannot be accessed from outside of the object since instance variables are not public. However, if the developer creates accessor methods for the instance variable then access is possible. Instance variables are also nil until initialized. As a beginner using rails, instance variables will look familiar when you are displaying data in the view. @user = Users.all.

Class Variables

Class variables are recognizable from the ‘@@’ prefix of the variable name. Class variable scope is related to every instance of the class or subclass and they accessible from anywhere in the class. Think of a class variable as a global variable for that class or children of that class

class Parent
 @@class_var = 1
  def show_class_var
   puts @@class_var
  end
 end
 class Child < Super
  @@class_var = 2
 end
 
first = Parent.new
second = Child.new
 
first.show_class_var
second.show_class_var

#output
# 1
# 2

 
You might want to consider using class variables to keep track of the number instances of an object or possibly some internal configuration settings that will change based on the environment.

Practice, practice, practice

In an effort to level up my programming skills I’ve been trying out some different code katas. Whatever you call them it still boils down to one thing: practice.

Gladwell says 10,000 hours, others say ‘Just do it’ and I wish this had stuck in my brain at a younger age. I’ve since learned that I need to try, fail, research and try again in order to be successful. Trying to learn through osmosis is the quickest way to forget the skill or never really grasp it. Just like any traditional exercise to strengthen a muscle you have to put in the reps.

Granted this is often a painful exercise, in my case it points out all the things that I don’t know and things that I’m not good at. I’ve adopted the mindset that it’s ok to not be awesome at something but at least show up and try it. Just check your hubris at the door. It doesn’t matter that it was hard it was or you were terrible the first time, we learn from failure. We learn the path to success by eliminating all the wrong options.

In the software industry the vast majority of us don’t practice, we save the experimentation for work hours. A little unfair to the employer and besides wouldn’t you rather have the luxury of doing something at your own pace and to be able to really drill down and figure something. Isn’t that the allure to programming, making stuff and figuring out how other stuff works?

Whatever your passion is keep working at it.

Upgrading to Ruby 2.1.0

Tags

, , , , ,

Over the holidays I upgraded my Mac to Mavericks, upgraded Ruby to 2.1.0 and upgraded Rails to 4.0. It was a fairly smooth transition aside from some issues regarding some linked files with Homebrew, but those were easily fixed after a bit of Googling.

Yesterday however, I started a new project only to find that I had errors with both sqlite and mysql2 gems. Neither version I had could be compiled. The project was properly scaffold but these errors persisted.

It turns out that during the scaffolding process (rails new projectname) bundle install is run at the end and since there was a problem with the gems I got a bunch of errors.

The solution I found (thanks Stackoverflow) was simple. The following steps worked for me:


1.gem uninstall mysql2
2.brew update
3.brew upgrade mysql
4.gem install mysql2
5.gem install sqlite3

After that the project scaffolded out properly and with no errors.

Using Grunt

Tags

, , ,

I’ve been reading about grunt for awhile and to honest I was skeptical about its value to my development workflow. I realize after using Grunt that I was doing a number of things inefficiently in my build process.

So what is Grunt and why would you use it? In short, Grunt is a taskrunner; think of it as bunch of batch files but organized into plugins. It does the boring mundane tasks like minifying javascript files, compiling LESS or SASS, copying working files, concatenating files and it can also incorporate livereload. These are just a few of the things it can do but it should be enough for to have a serious look at it.

I won’t go into installing npm or Grunt itself as there are tons of resources available for that. Lets assume that everything went according to plan and you’re ready to start.

Package.json

Before you can use and run Grunt in a new project, you’ll need the following:
1. A package.json file. It contains meta data about the dependencies of the project and should be created first.
2. A Gruntfile.js. This file loads and configures tasks for Grunt.

To create package.json file, run either npm install, npm init or grunt-init from the command line in the root directory of your project. If you’ve installed npm globally and have it in your path, use npm init. You’ll be asked a bunch of profiling questions about your project. Just answer them the best you can. Most of the fields can be blank but I did have to have the version value as 0.0.0 or it threw an error.

The first package.json file should look something like this:

{
"name": "testgrunt",
"version": "0.0.0",
"description": "my test",
"main": "index.html",
"scripts": {
"test": "test"
},
"keywords": [
"none"
],
"author": "jeff wrathall",
"license": "BSD-2-Clause"
}

Gruntfile

Next, to get Grunt set up we have to run npm install grunt --save-dev. This will install the latest version of Grunt locally and add it to the list of dependencies in the package.json file. Moving forward, whenever you want to install or use any module with npm and Grunt you will need to run this same command. If you want to, for example, install jsHint for use in you Grunt file you would use npm install grunt-contrib-jshint --save-dev. Check out the Gruntjs repro on Github for more plugins.

Go ahead and manually create the Gruntfile.js in your project root along side the package.json file.

The Gruntfile consists of a wrapper function, task configuration, loading Grunt plugins and tasks and custom tasks that you want to add. The Gruntfile is a valid javascript file and should be placed in the root of your project along with the package.json file. Instead of breaking down each part, have a look at the comment Gruntfile


//wrapper function
module.exports = function(grunt){ 
    "use strict";
    // task configuration
    grunt.initConfig({
        //loading meta data from package.json
        pkg: grunt.file.readJSON('package.json'), 

        //configuration for compass plugin tasks
        compass: {
            dist: {
                options: {
                    sassDir: 'styles/sass',
                    fontsDir: 'fonts/',
                    cssDir: '',
                    outputStyle: 'compressed'
                }
            }
        },
        // configuration for jshint plugin tasks
        jshint: {
            // You get to make the name
            // The paths tell JSHint which files to validate
            myFiles: ['dir1/**/*.js', 'dir2/**/*.js']
        }

    });
    //plugins
    grunt.loadNpmTasks('grunt-contrib-compass');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    //custom tasks
    grunt.registerTask('default', ['jshint','compass']);
};

You’ll notice that each plugin has its task properties set in Gruntfile. The Gruntjs repro at Github has lots of useful plugins and they are all well documented.

Once a plugin is loaded using npm install module --save-dev into the package.json file, it can then be used in the Gruntfile by calling using grunt.loadNpmTasks('module-name').

The last step is to get Grunt to run your tasks when you type grunt into the command line. Register your task as part of the default command by adding grunt.registerTask('default', ['jshint','compass']); as the last line in your Gruntfile. Optionally, you could write the register task like this grunt.registerTask('default', 'jshint'); and then you would have to call each task individually like: grunt jshint

Once you are ready to test it out enter grunt into the command line.

I hope this brief post helps with the basics configuring Grunt. There is much more Grunt can do and I encourage you to check out the official docs.

Google Driven Development

Tags

,

Recently, Scott Hanselman posted his thoughts on being a good developer or just a good Googler. The post and comments got me reflecting on my programming and learning style.

My Google-fu is pretty strong and I relied on it heavily, even to the point of considering it a personal strength. I often think: I may not know the answer but I know where to find it. Finding it usually involves sifting through Google results, StackOverflow questions and blog posts looking for a result that closely matched whatever I was trying to accomplish.  I am ashamed to admit it but sometimes this was a straight up ctrl-c, ctrl-v action.

In my mind, this is the central problem. Relying too much on Google and other sites is akin to a  gateway drug and in my case it’s done two things.

First, it has slowed my growth as a developer. I would think less of what and how I was trying to accomplish and more of where I could find the easy answer. Therefore, I would read less of the docs, think less and consequently not really understand what was happening in my code or what side effects dropping in someone else’s code would lead to.

Second, I wasted tons time searching for quick fixes and implementing other people’s ideas that never really fit with what I was trying to accomplish. Every challenge is different and there is no magic solution to fit all scenarios. This time would have been much better used actually solving the problem from the ground up instead looking for the quick fix.

I’m not taking a hard line that developers should have instant recall when it comes to a language or framework.  Everyone needs a hand, or that spark to jump start a new train of thought. I think the best approach is to use the Google judiciously, especially if you are just learning a technology, but really focus on learning and exploring the fundamentals first.

Getting up to speed in new technologies requires a solid understanding of the basics so you can progress into more complicated aspects. Personally, I learn better when someone explains it (usually a number of times) with pictures, then I have to repeat it over and over and over. Focusing on the fundamentals enables you to transfer that core knowledge to other languages and problem domains, create clean, concise solutions and solve problems better.

Not reaching for Google first and reading the API docs requires discipline. It can also be frustrating but with practice everything becomes easier. Combining these two strategies will ultimately increase your skill because you will understand how things work in depth and you’ll have a good idea of how to do it.

Inaugural post

After much procrastination I’ve finally created my own blog. My goal is to post something web development related once a week. I tend to gravitate toward .Net, Ruby on rails, WordPress,  javascript, css and most things web related. I haven’t put a ton of thought into the structure or the content, I’ll just let that work itself out and I’ll write about whatever headspace I’m in for any given time.

My motivation for the blog is simple: I take a ton from the community whether its StackOverflow, podcasts,  blogs or just plain ole Google and It’s time I start contributing and sharing my opinion.

I’m pretty nervous and excited about putting it all out there. Writing code that lives on the web is one thing but sharing words, experiences and thoughts for public consumption and criticism is a little intimidating.