#245 New Gem with Bundler
- Download:
- source codeProject Files in Zip (3.62 KB)
- mp4Full Size H.264 Video (20.1 MB)
- m4vSmaller H.264 Video (9.2 MB)
- webmFull Size VP8 Video (22.5 MB)
- ogvFull Size Theora Video (16.8 MB)
루비 젬을 만들어 관리하는 방법은 수년에 걸쳐 발전해 왔습니다. 이전 135번[watch, read] 연제에서는 echoe 젬을 사용해서 젬을 작성하였고, 일년후, 183번[watch, read] 연제에서는 Jeweler 젬을 사용했었습니다. 이 두개의 젬 모두에서, 하나의 젬을 릴리스할 때마다 Gemsepc 파일을 생성하는 방법을 제공해 주고 있으며 이 툴을 이용해서 Gemspec 파일을 관리하게 됩니다. 이번 연제에서는 훨씬 더 간단한 메소드를 이용해서 직접 Gemspec 파일을 관리할 것입니다.
이러한 메소드를 사용하더라도, 젬 마다 초기 Gemspec 파일을 생성할 필요가 있습니다. 직접 코딩하여 작성할 수 있고, Bundler와 같은 툴을 이용하여 도움을 받을 수도 있습니다. Bundler는 일반적으로 어플리케이션의 의존성을 관리하는 방법으로 알려져 있지만, 젬을 생성하는 명령도 제공해 줍니다. 사실 이 명령은 잘 알려져 있지 않지만 젬을 제대로 작성해 줍니다. bundle gem
명령에 원하는 젬 이름을 넘겨줍니다. 이 연제의 목적상 lorem이라는 간단한 젬을 만들 것이며 이 젬은 “Lorem ipsum” 텍스트 일부를 생성해 줍니다.
$ bundle gem lorem create lorem/Gemfile create lorem/Rakefile create lorem/.gitignore create lorem/lorem.gemspec create lorem/lib/lorem.rb create lorem/lib/lorem/version.rb Initializating git repo in /Users/eifion/code/ep245/lorem
bundle gem
명령은 디렉토리를 새로 만들어 그 위치에 관련 파일들을 생성해 줍니다. 또한 해당 디렉토리에서 git 저장소로 초기화해 줍니다. 이것은 git 사용이 가능한 상태로 만들어 주는데, 그 이유는 잠시 후에 설명하도록 하겠습니다. 먼저 생성된 파일들에 대해 하나하나 알아보도록 하겠습니다. 먼저 lorem.gemspec
파일부터 보도록 하겠습니다.
# -*- encoding: utf-8 -*- $:.push File.expand_path("../lib", __FILE__) require "lorem/version" Gem::Specification.new do |s| s.name = "lorem" s.version = Lorem::VERSION s.platform = Gem::Platform::RUBY s.authors = ["TODO: Write your name"] s.email = ["TODO: Write your email address"] s.homepage = "" s.summary = %q{TODO: Write a gem summary} s.description = %q{TODO: Write a gem description} s.rubyforge_project = "lorem" s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = ["lib"] end
언뜻보아도 알 수 있듯이 이 파일내용 중에 TODO 항목들을 직접 변경하여 사용할 수 있습니다. 이 작업이 끝나면 Gemspec 파일을 바로 사용할 수 있게 될 것입니다. 이 파일에서 흥미로운 것은 파일의 끝에 있는 파일관련 속성들입니다. 이것들은 런타임시에 어떤 파일들이 젬에 포함될 것인지를 결정하기 위해 git을 사용하여 git ls-files
명령을 실행하게 되는데 바로 이것이 bundle gem
명령이 git 저장소를 생성하는 이유인 것입니다. git을 사용할 때 좋은 점은, .gitignore
의 내용을 자동으로 상속받기 때문에 임시파일이나 저장소에 포함시키고 싶지 않은 파일들(따라서 젬에도 포함되지 않는)을 제외시킬 수 있다는 것입니다. 위와 같은 디폴트 상태에서도 대부분의 젬에 대해서 작동을 하지만 제외항목을 관리하고자 할 때는 언제든지 수정할 수 있습니다.
또하나 주목할 것은, 버전 번호를 결정하는 방법에 대한 것입니다. 이것은 Lorem::VERSION
이라는 상수형태로 정의되는데 이 버전 값은 lib/lorem
디렉토리의 version.rb
이라는 파일에 정의되어 있습니다. 이 파일의 목적은 버전 번호를 정의하는 것입니다.
module Lorem VERSION = "0.0.1" end
기존 젬을 새 버전으로 업데이트할 때는, 이 파일에서 버전 번호를 변경하여 젬을 다시 공개할 수 있습니다.
lib
디렉토리 상에 생성된 파일 중에 lorem.rb
라는 것이 있습니다. 이것이 해당 젬을 require
할 때 로딩되는 파일입니다. 이 파일에 원하는 코드를 작성할 수 있고, 또는, lib
디렉토리에 다른 파일들을 생성해서 그 파일들을 require
할 수도 있습니다. 여기서 작성하는 간단한 기능을 가지는 Lorem 젬에 대해서는, ipsum
라는 클래스 메소드를 작성해서 Lorem Ipsum 텍스트 일부를 반환해 줄 것입니다.
module Lorem def self.ipsum "Lorem ipsum dolor sit amet, consectetur adipisicing ...." end end
젬 공개하기
이제 젬 작성을 마무리하고 첫번째 버전을 공개할 것입니다. 이전에 먼저, Gemsepc 파일을 업데이트해서 TODO 텍스트를 변경할 것입니다.
# -*- encoding: utf-8 -*- $:.push File.expand_path("../lib", __FILE__) require "lorem/version" Gem::Specification.new do |s| s.name = "lorem" s.version = Lorem::VERSION s.platform = Gem::Platform::RUBY s.authors = ["Eifion Bedford"] s.email = ["eifion@asciicasts.com"] s.homepage = "" s.summary = %q{Lorem ipsum generator} s.description = %q{Simply generates lorem ipsum text.} s.rubyforge_project = "lorem" s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = ["lib"] end
그리고나서, Gemspec 파일에 대해서 gem build
명령을 실행합니다.
$ gem build lorem.gemspec WARNING: no homepage specified Successfully built RubyGem Name: lorem Version: 0.0.1 File: lorem-0.0.1.gem
이 명령은 .gem
파일을 만들어 줍니다. 그리고 gem push
명령을 실행하면 해당 젬을 RubyGems.org 로 푸시해서 다른 사람들이 사용할 수 있도록 공개할 수 있게 되는 것입니다.
젬 업데이트하기
Gemspec 파일을 이용해서 하나의 젬을 공개하는 일이란 정말 이처럼 쉬운 것입니다. 해당 젬의 새 버전을 릴리스하고자 할 때는, 먼저 코드를 변경한 후에 version.rb
파일에서 버전 번호를 업데이트합니다.
module Lorem VERSION = "0.0.2" end
이제 gem build
와 gem push
명령을 다시 실행하면 새 버전을 만든 후 공개할 수 있게 됩니다.
Gemfile 과 Rakefile
아직 언급하지 않았지만 Bundler가 생성하는 파일 중에 2개가 더 있습니다. 바로 Gemfile과 Rakefile입니다. 먼저 Gemfile
을 보도록 하겠습니다. 레일스 어플리케이션에서 Gemfile
은 Bundler를 이용하여 젬 의존성을 관리하게 됩니다. Gemfile
내용을 보면 gemspec
이라는 단 하나의 명령을 보게 됩니다.
source "http://rubygems.org" # Specify your gem's dependencies in lorem.gemspec gemspec
이 명령은 해당 젬의 의존성을 점검하기 위해 이 젬의 Gemspec 파일을 들여다 보고 Bundler를 이용하여 그 파일들을 로드하게 될 것입니다. 따라서 보통은 이 Gemspec파일을 직접 관리할 필요가 없게 됩니다. 사실, 해당 젬의 의존성은 Gemspec 파일내에서 관리하고 Bundler로 하여금 Gemfile
을 통해서 자동으로 필요한 젬들을 로드할 수 있도록 하는 것이 더 좋습니다. 예를 들어, 해당 젬을 테스트하기 위해서 RSpec을 사용할 경우입니다. Gemfile
에 RSpec을 추가하지 않고 lorem.gemspec
파일에 development dependency로 추가할 것입니다.
Gemspec 파일을 다루는 것이 익숙하지 않을 때는 이 문서를 참조할 만합니다. 여기에는 여러가지 속성들을 설정하기 위해서, Gemspec 파일에서 사용할 수 있는, 여러가지 메소드(RSpec를 추가하기 위해 사용하는 add_development_dependency
메소드를 포함)에 대한 목록을 볼 수 있습니다.
# -*- encoding: utf-8 -*- $:.push File.expand_path("../lib", __FILE__) require "lorem/version" Gem::Specification.new do |s| s.add_development_dependency "rspec" # Other attributes omitted end
Gemfile
에서 Gemspec 파일을 참조하도록 해 놓으면, bundle
명령을 실행해서 필요한 모든 젬들이 설치되도록 할 수 있습니다.
$ bundle Fetching source index for http://rubygems.org/ Using diff-lcs (1.1.2) Using lorem (0.0.1) from source at /Users/eifion/Desktop/Dropbox/rails/apps_for_asciicasts/ep245/lorem Installing rspec-core (2.3.1) Installing rspec-expectations (2.3.0) Installing rspec-mocks (2.3.0) Installing rspec (2.3.0) Using bundler (1.0.7) Your bundle is complete! It was installed into /Users/eifion/.rvm/gems/ruby-1.9.2-p0
이러한 방법은, 해당 젬을 공개해서 다른 개발자들도 함께 작업을 할 수 있도록 할 때, README 파일에 bundle
명령을 실행하여 관련 젬을 모두 설치할 수 있도록 방법을 알려 주고자 할 때 유용합니다.
이상으로 Gemfile
에 대해 소개했습니다. 그렇다면 이제 Rakefile
에 대해 알아보겠습니다. 왜 Bundler는 이 파일을 만들까. 이 파일의 코드를 들여다 보면, Bundler로부터 몇가지 젬 헬퍼 태스크를 추가한다는 것을 알게 될 것입니다.
require 'bundler' Bundler::GemHelper.install_tasks
rake -T 명령을 실행하면 이와 관련된 태스크들을 볼 수 있습니다.
$ rake -T (in /Users/eifion/code/ep245/lorem) rake build # Build lorem-0.0.2.gem into the pkg directory rake install # Build and install lorem-0.0.2.gem into system gems rake release # Create tag v0.0.2 and build # and push lorem-0.0.2.gem to Rubygems
Rakefile
에 있는 코드는 3가지 태스크를 생성해 줍니다. 이것은, 젬을 만들어, 설치하고, 릴리스하는 일반적인 태스크입니다. 일반적인 작업과정은, 원하는데로 젬이 작성되었을 때, rake install
를 호출하여 로컬머신에 해당 젬을 설치하고, 문제가 없을 때까지 완벽하게 테스트해 볼 수 있습니다. 그리고나서, rake release
명령을 호출하여 릴리스를 표시하고 RubyGems로 해당 젬을 공개하는 것입니다.
기존 젬을 업데이트하기
Bundler를 이용하면 처음부터 직접 젬을 설정할 수 있게 되지만, 이미 만들어진 젬을 이와 같은 작업과정에 적용하고자 한다면 어떻게 될까요. 몇가지 파일에 대해서만 복사하면 간단하게 해결됩니다. 이 때, 필요한 파일은 Gemfile
, .gemspec
, 그리고, Bundler가 제공하는 rake 작업을 사용할 때는, Rakefile
도 포함됩니다. 이러한 파일들을 기존의 젬에 추가하게 되면 이와 같은 작업과정을 사용할 수 있게 될 것입니다.
전체적으로 봤을 때, Bundler는 젬을 만들고 관리하기 위한 훌륭한 방법입니다. 이전 연제에서 소개한 관련 툴들보다도 훨신 간단하게 사용할 수 었어서 젬을 새로 만들 때 Bundler는 사용할 만한 가치가 있습니다.