Skip to content

Commit

Permalink
Updated Ruby snippet formatting and copyright year
Browse files Browse the repository at this point in the history
  • Loading branch information
AndyObtiva committed Mar 24, 2015
1 parent a30c731 commit f699940
Showing 1 changed file with 24 additions and 1 deletion.
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ UserIdentifiable module.

#### 1) self.included(base)

```ruby
module UserIdentifiable
include ActiveModel::Model

Expand All @@ -43,11 +44,13 @@ module UserIdentifiable
"#{self.class.name}_#{user_id}"
end
end
```

This is a lot to think about and process for simply wanting inclusion of class method definitions (like <code>most_active_user</code>) and class method invocations (like <code>belongs_to</code> and <code>validates</code>). The unnecessary complexity gets in the way of problem-solving; slows down productivity with repetitive boiler-plate code; and breaks expectations set in other similar object-oriented languages, discouraging companies from including Ruby in a polyglot stack, such as Groupon's Ruby/Java/Node.js stack and SoundCloud's JRuby/Scala/Clojure stack.

#### 2) ActiveSupport::Concern

```ruby
module UserIdentifiable
extend ActiveSupport::Concern
include ActiveModel::Model
Expand All @@ -67,11 +70,13 @@ module UserIdentifiable
"#{self.class.name}_#{user_id}"
end
end
```

A step forward that addresses the boiler-plate DRY concern, but is otherwise really just lipstick on a pig.

#### 3) SuperModule

```ruby
module UserIdentifiable
include SuperModule
include ActiveModel::Model
Expand All @@ -87,6 +92,7 @@ module UserIdentifiable
"#{self.class.name}_#{user_id}"
end
end
```

SuperModule provides a simple conventional object-oriented approach that works just as expected. Given that it collapses difference between having a base class extend a super class or include a super module, it encourages as a side benefit writing better Object-Oriented code and helps Ruby be more polyglot and beginner friendly.

Expand All @@ -112,6 +118,7 @@ Add the following at the top of your Ruby file: <pre>require 'super_module'</pre

#### 2) Include SuperModule at the top of the module

```ruby
module UserIdentifiable
include SuperModule
include ActiveModel::Model
Expand All @@ -127,30 +134,38 @@ module UserIdentifiable
"#{self.class.name}_#{user_id}"
end
end
```

#### 3) Mix newly defined module into a class or another super module

```ruby
class ClubParticipation < ActiveRecord::Base
include UserIdentifiable
end

class CourseEnrollment < ActiveRecord::Base
include UserIdentifiable
end

module Accountable
include SuperModule
include UserIdentifiable
end

class Activity < ActiveRecord::Base
include Accountable
end
```

#### 4) Start using by invoking class methods or instance methods

```ruby
CourseEnrollment.most_active_user
ClubParticipation.most_active_user
Activity.last.slug
ClubParticipation.create(club_id: club.id, user_id: user.id).slug
CourseEnrollment.new(course_id: course.id).valid?
```

## Glossary

Expand All @@ -170,6 +185,7 @@ CourseEnrollment.new(course_id: course.id).valid?

## Another Example

```ruby
require 'super_module'

module Foo
Expand Down Expand Up @@ -210,6 +226,7 @@ class MediaAuthorization < ActiveRecord::Base
end

MediaAuthorization.create.errors.messages.inspect
```

=> "{:credit_card_id=>[\"can't be blank\"], :user_id=>[\"can't be blank\"]}"

Expand All @@ -233,15 +250,18 @@ MediaAuthorization.bar

Although the library code is written in a very simple and modular fashion, making it easy to read through the algorithm, here is a basic rundown of how the implementation works.

```ruby
def included(base)
__invoke_super_module_class_method_calls(base)
__define_super_module_class_methods(base)
end
```

##### 1) The first step ensures invoking super module class method calls from the base object that includes it.

For example, suppose we have a super module called Locatable:

```ruby
module Locatable
include SuperModule

Expand All @@ -258,13 +278,15 @@ class Vehicle < ActiveRecord::Base
include Locatable
# … more code follows
end
```

This first step guarantees invocation of the two Locatable <code>validates</code> method calls on the Vehicle object class.

##### 2) The second step redefines super module class methods on the base class to simulate the effect of base.extend(super_module)

For example, suppose we have a super module called Addressable:

```ruby
module Addressable
include SuperModule

Expand All @@ -283,6 +305,7 @@ class Contact < ActiveRecord::Base
include Addressable
# … more code follows
end
```

The second step ensures that <code>merge_duplicates</code> is included in Contact as a class method, allowing the call <code>Contact.merge_duplicates</code>

Expand All @@ -295,5 +318,5 @@ You are welcome to read through the code for more in-depth details.

## Copyright

Copyright (c) 2014 Andy Maleh. See LICENSE.txt for
Copyright (c) 2014-2015 Andy Maleh. See LICENSE.txt for
further details.

0 comments on commit f699940

Please sign in to comment.