Let's create a gem with

  • sass
  • coffee
  • rails helper
  • 2 custom class
  • write a new method on class Hash in core of ruby

gem version 0.1.0

Go to ~/Documents and create a new template of gem
Before create your gem, try this url to check if gem name already in use https://rubygems.org/gems/your_gem_name

$ cd ~/Documents
$ bundler gem gtest
  Creating gem 'gtest'...
  MIT License enabled in config
  Code of conduct enabled in config
        create  gtest/Gemfile
        create  gtest/.gitignore
        create  gtest/lib/gtest.rb
        create  gtest/lib/gtest/version.rb
        create  gtest/gtest.gemspec
        create  gtest/Rakefile
        create  gtest/README.md
        create  gtest/bin/console
        create  gtest/bin/setup
        create  gtest/.travis.yml
        create  gtest/.rspec
        create  gtest/spec/spec_helper.rb
        create  gtest/spec/gtest_spec.rb
        create  gtest/LICENSE.txt
        create  gtest/CODE_OF_CONDUCT.md
  Initializing git repo in /home/thiago/Documents/gtest
$ cd gtest

My gtest_spec.gemspec be like this

# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'gtest/version'

Gem::Specification.new do |spec|
  spec.name          = "gtest"
  spec.version       = Gtest::VERSION
  spec.authors       = ["thiago feitosa"]
  spec.email         = ["mail@thiago.pro"]

  spec.summary       = %q{TODO: Write a short summary, because Rubygems requires one.}
  spec.description   = %q{TODO: Write a longer description or delete this line.}
  spec.homepage      = "TODO: Put your gem's website or public repo URL here."
  spec.license       = "MIT"

  # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
  # delete this section to allow pushing this gem to any host.
  if spec.respond_to?(:metadata)
    spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
  else
    raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
  end

  spec.files         = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
  spec.bindir        = "exe"
  spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
  spec.require_paths = ["lib"]

  spec.add_development_dependency "bundler", "~> 1.11"
  spec.add_development_dependency "rake", "~> 10.0"
  spec.add_development_dependency "rspec", "~> 3.0"
end

To works correctly we need change

  • spec.summary
  • spec.description
  • spec.homepage
  • comment lines 19 to 23
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'gtest/version'

Gem::Specification.new do |spec|
  spec.name          = "gtest"
  spec.version       = Gtest::VERSION
  spec.authors       = ["thiago feitosa"]
  spec.email         = ["mail@thiago.pro"]

  spec.summary       = "My gem test"
  spec.description   = "this gem do cool stuff"
  spec.homepage      = "https://rubygems.org/gems/gtest"
  spec.license       = "MIT"

  # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
  # delete this section to allow pushing this gem to any host.
  #if spec.respond_to?(:metadata)
  #  spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
  #else
  #  raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
  #end

  spec.files         = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
  spec.bindir        = "exe"
  spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
  spec.require_paths = ["lib"]

  spec.add_development_dependency "bundler", "~> 1.11"
  spec.add_development_dependency "rake", "~> 10.0"
  spec.add_development_dependency "rspec", "~> 3.0"
end

Build your gem with this command

$ gem build gtest.gemspec
    Successfully built RubyGem
    Name: gtest
    Version: 0.1.0
    File: gtest-0.1.0.gem

Push your gem to https://rubygems.org with this command

$ gem push gtest-0.1.0.gem
  Pushing gem to https://rubygems.org...
  Successfully registered gem: gtest (0.1.0)

Done! Your gem is ready to use
Before continuing let's put this gem on github
Create a new repo on your git account

In .gitignore add

*.gem

Now put this gem on your new repo

$ git remote add origin git@github.com:your_user/your_gem_name.git
$ git add .
$ git commit -m "initial commit"
$ git push -u origin master
$ git tag -a v0.1.0 -m "initial commit"
$ git push --tag

Your gem will be used, but her is completely empty for now

gem "gtest", "~> 0.1.0"

gem version 0.2.0

Let's add a new sass and coffee in gem

mkdir -p vendor/assets/{javascripts/gtest,stylesheets/gtest}

In vendor/assets/javascripts/gtest/gtest.coffee put this

gtest = () ->
  console.log('you call me? :)')

In vendor/assets/stylesheets/gtest/gtest.sass put this

.gtest
  color: red
  background-color: white

Your file lib/gtest.rb be like that

require "gtest/version"

module Gtest
  # Your code goes here...
end

Change to

require "gtest/version"

module Gtest
  class Engine < ::Rails::Engine; end
end

Update version in lib/gtest/version.rb

module Gtest
  VERSION = "0.2.0"
end

Create CHANGELOG

v0.2.0
  - add sass and coffee
v0.1.0
  - initial commit

Push new version of gem in to github

$ git add .
$ git commit -m "add sass and coffee to gem"
$ git push
$ git tag -a v0.2.0 -m "sass and coffee added"
$ git push --tag

Generate new version of gem

$ rm -rf *.gem
$ gem build gtest.gemspec
    Successfully built RubyGem
    Name: gtest
    Version: 0.2.0
    File: gtest-0.2.0.gem

Push gem

$ gem push gtest-0.2.0.gem
  Pushing gem to https://rubygems.org...
  Successfully registered gem: gtest (0.2.0)

using gem version 0.2.0

$ cd /tmp
$ rails new test_app
$ cd test_app

Let's test this!

in Gemfile put

gem "gtest"

And run

$ bundle install
$ rails g controller test index

Set up app/views/test/index.html.erb like this

<h1>Test#index</h1>
<p class="gtest" >Find me in app/views/test/index.html.erb</p>

Run rails

rails server

Try localhots:3000/test/index

You see css applied?
Open browser console and try gtest();
Maybe this error has occurred

Uncaught ReferenceError: gtest is not defined?

gem version 0.2.1

Ok, lets solve this

cd ~/Documents/gtest

In /vendor/assets/javascripts/gtest/gtest.coffee add @ before name method, this make method global

@.gtest = () ->
  console.log('you call me? :)')

Update version on lib/gtest/version.rb to 0.2.1

module Gtest
  VERSION = "0.2.1"
end

Push to git a new version

$ git add .
$ git commit -m "fix js"
$ git push
$ git tag -a v0.2.1 -m "fix js"
$ git push --tag

Build new version of gem

$ rm -rf *.gem
$ gem build gtest.gemspec
    Successfully built RubyGem
    Name: gtest
    Version: 0.2.1
    File: gtest-0.2.1.gem

Push gem

$ gem push gtest-0.2.1.gem
  Pushing gem to https://rubygems.org...
  Successfully registered gem: gtest (0.2.1)

using gem version 0.2.1

Teste new version of gem

cd /tmp/gtest

In Gemfile

gem "gtest", "~> 0.2.1"

Install new gem and start server

$ bundle install
$ rails server

Try again localhots:3000/test/index

Try execute the method gtest on console of browser, it's works now? 😊

gem version 0.3.0

Now let's open class Hash and add recursive method symbolize_keys

$ cd ~/Documents/gtest
$ mkdir lib/core
$ vim lib/core/hash.rb

Put this

class Hash
  def symbolize_keys_recursive
    r = {}
    self.keys.each do |xKey|
      if self[xKey].is_a? Hash
        r[xKey.to_sym] = self[xKey].symbolize_keys_recursive
      elsif (self[xKey].is_a? Array) && (self[xKey][0].is_a? Hash)
        self[xKey].each do |x|  
          r[xKey.to_sym] ||= []
          r[xKey.to_sym] << x.symbolize_keys_recursive
        end
      else
        r[xKey.to_sym] = self[xKey]
      end
    end
    r
  end
end

In lib/gtest.rb add this

require "core/hash"

update CHANGELOG

CHANGELOG
v0.3.0
  - add method symbolize_keys_recursive in class Hash
v0.2.1
  - set method gtest in coffee global
v0.2.0
  - add sass and coffee
v0.1.0
  - initial commit

Update gem version on lib/gtest/version.rb

module Gtest
  VERSION = "0.3.0"
end

Push on git, build gem and push her

$ git commit -m "add new method to class hash"
$ git push
$ git tag -a v0.3.0 -m "add method symbolize_keys_recursive in hash class"
$ git push --tag
$ gem build gtest.gemspec
$ gem push gtest-0.3.0.gem

using gem version 0.3.0

Going back the app test

cd /tmp/gtest

In app/views/test/index.html.erb

<h1>Test#index</h1>
<p class="gtest" >Find me in app/views/test/index.html.erb</p>
<% h = {"a"=>{"b"=>10}}  %>
<p>h = <%= h %></p>
<p>h.symbolize_keys = <%= h.symbolize_keys  %></p>
<p>h.symbolize_keys_recursive = <%= h.symbolize_keys_recursive %></p>

See result on localhots:3000/test/index

gem version 0.4.0

Now, let's add a new helper in this gem

cd ~/Documents/gtest

In lib/helpers/gtest_helper.rb put this

module GtestHelper
  def wellcome_gtest name
    "#{name}! Wellcome dude!".html_safe
  end
end

In lib/gtest.rb add this

require "helpers/gtest_helper"

Update version on lib/gtest/version.rb

module Gtest
  VERSION = "0.4.0"
end

Update CHANGELOG

v0.4.0
  - add new helper
v0.3.0
  - add method symbolize_keys_recursive in class Hash
v0.2.1
  - set method gtest in coffee global
v0.2.0
  - add sass and coffee
v0.1.0
  - initial commit

Push on git new updates

$ git add .
$ git commit -m "add helper method"
$ git push
$ git tag -a v0.4.0 -m "add helper method"
$ git push --tag

Build a new version of gem

$ gem build gtest.gemspec
    Successfully built RubyGem
    Name: gtest
    Version: 0.4.0
    File: gtest-0.4.0.gem

Push a new version of gem

$ gem push gtest-0.4.0.gem
  Pushing gem to https://rubygems.org...
  Successfully registered gem: gtest (0.4.0)

using gem version 0.4.0

Test new version of gem

cd ~/Documents/gtest

In Gemfile

gem "gtest", "~> 0.4.0"

in app/views/test/index.html.erb

<h1>Test#index</h1>
<p class="gtest" >Find me in app/views/test/index.html.erb</p>
<% h = {"a"=>{"b"=>10}}  %>
<p>h = <%= h %></p>
<p>h.symbolize_keys = <%= h.symbolize_keys  %></p>
<p>h.symbolize_keys_recursive = <%= h.symbolize_keys_recursive %></p>

<%= wellcome_gtest 'Luke'  %>

See result on localhots:3000/test/index

gem version 0.5.0

Now, let's create a custom class in this gem

cd ~/Documents/gtest

In gtest/custom_class.rb

module Gtest
  class CustomClass
    def add n1, n2
      n1 + n2
    end

    def sub n1, n2
      n1 - n2
    end
  end
end

In gtest/custom_class2.rb

class CustomClass2
  def add n1, n2
    n1 + n2
  end

  def sub n1, n2
    n1 - n2
  end
end

In gtest.rb

require "gtest/version"
require "gtest/custom_class"
require 'gtest/custom_class2'
require "core/hash"
require "helpers/gtest_helper"

ActionView::Base.send :include, GtestHelper
module Gtest
  class Engine < ::Rails::Engine; end
end

In lib/gtest/version.rb

module Gtest
  VERSION = "0.5.0"
end

CHANGELOG

v0.5.0
  - add CustomClass and CustomClass2
v0.4.0
  - add new helper
v0.3.0
  - add method symbolize_keys_recursive in class Hash
v0.2.1
  - set method gtest in coffee global
v0.2.0
  - add sass and coffee
v0.1.0
  - initial commit

using gem version 0.5.0

Let's test a custom class now

cd ~/Documents/gtest

In app/views/test/index.html.erb

<h1>Test#index</h1>
<p class="gtest" >Find me in app/views/test/index.html.erb</p>
<% h = {"a"=>{"b"=>10}}  %>
<p>h = <%= h %></p>
<p>h.symbolize_keys = <%= h.symbolize_keys  %></p>
<p>h.symbolize_keys_recursive = <%= h.symbolize_keys_recursive %></p>

<%= wellcome_gtest 'Luke'  %>

<p>Gtest::CustomClass.new.add 1,2: <%= Gtest::CustomClass.new.add 1,2 %></p>

<p>CustomClass2.new.add 1,2: <%= Gtest::CustomClass.new.add 1,2 %></p>

See result on localhots:3000/test/index


🗓 2016-05-05
1028 👀