lacquer 0.4.1 → 0.5.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,12 +12,14 @@ module Lacquer
12
12
  end
13
13
 
14
14
  # Sends the command 'url.purge *path*'
15
- def purge(path)
16
- send_command('url.purge ' << path).all? do |result|
17
- result =~ /200/
15
+ def purge(*paths)
16
+ paths.all? do |path|
17
+ send_command('url.purge ' << path.gsub('\\', '\\\\\\')).all? do |result|
18
+ result =~ /200/
19
+ end
18
20
  end
19
21
  end
20
-
22
+
21
23
  # Sends commands over telnet to varnish servers listed in the config.
22
24
  def send_command(command)
23
25
  Lacquer.configuration.varnish_servers.collect do |server|
@@ -55,7 +57,7 @@ module Lacquer
55
57
  end
56
58
 
57
59
  connection.cmd('String' => command, 'Match' => /\n\n/) {|r| response = r.split("\n").first.strip}
58
- connection.close
60
+ connection.close if connection.respond_to?(:close)
59
61
  rescue Exception => e
60
62
  if retries < Lacquer.configuration.retries
61
63
  retry
@@ -0,0 +1,131 @@
1
+ module Lacquer
2
+ class Varnishd
3
+ attr_accessor :listen, :telnet, :sbin_path, :storage, :working_dir, :user, :backend, :params
4
+
5
+ cattr_accessor :started_check_delay, :vcl_script_filename
6
+ self.started_check_delay = 1
7
+ self.vcl_script_filename = 'config/varnish.vcl'
8
+
9
+ def self.root_path
10
+ Rails.root
11
+ end
12
+
13
+ def self.env
14
+ Rails.env
15
+ end
16
+
17
+ def self.config_file
18
+ root_path.join('config/varnishd.yml')
19
+ end
20
+
21
+ def self.config
22
+ YAML.load(File.read(config_file))[env].stringify_keys
23
+ end
24
+
25
+ def initialize(settings = self.class.config)
26
+ self.listen, self.telnet, self.backend, self.sbin_path, self.storage, self.working_dir, self.user, self.params =
27
+ settings.values_at("listen", "telnet", "backend", "sbin_path", "storage", "working_dir", "user", "params")
28
+ end
29
+
30
+ def render_vcl
31
+ require 'erubis'
32
+ eruby = Erubis::Eruby.new(erb_vcl_script_filename.read)
33
+ eruby.result(binding)
34
+ end
35
+
36
+ def generate_vcl
37
+ if erb_vcl_script_filename.exist?
38
+ log "#{erb_vcl_script_filename} found rendering to #{vcl_script_filename}"
39
+ File.open(vcl_script_filename, "w") do |vcl|
40
+ vcl.write(render_vcl)
41
+ end
42
+ end
43
+ end
44
+
45
+ def start
46
+ if running?
47
+ log("Already running")
48
+ return
49
+ end
50
+ generate_vcl
51
+ execute("#{varnishd_cmd} #{args} #{params_args}")
52
+ sleep(self.class.started_check_delay)
53
+ log("Failed to start varnishd daemon") unless running?
54
+ end
55
+
56
+ def stop
57
+ if running?
58
+ execute("kill #{pid}")
59
+ pid_file.delete
60
+ else
61
+ log("pid file not found or varnishd not running")
62
+ end
63
+ end
64
+
65
+ def running?
66
+ !!pid && !!Process.kill(0, pid.to_i)
67
+ rescue
68
+ false
69
+ end
70
+
71
+ def args
72
+ options.map { |k, v| "#{k} #{v}" }.join(" ")
73
+ end
74
+
75
+ def params_args
76
+ params.map { |k, v| "-p #{k}=#{v}" }.join(" ")
77
+ end
78
+
79
+ def options
80
+ opt = {}
81
+ opt["-P"] = pid_file
82
+ opt["-a"] = listen
83
+ opt["-T"] = telnet if telnet.present?
84
+ opt["-n"] = working_dir if working_dir.present?
85
+ opt["-u"] = user if user.present?
86
+ opt["-s"] = eval(%Q("#{storage}"))
87
+ opt["-f"] = vcl_script_filename
88
+ opt
89
+ end
90
+
91
+ def params
92
+ @params || {}
93
+ end
94
+
95
+ protected
96
+
97
+ def varnishd_cmd
98
+ Pathname.new(sbin_path).join('varnishd')
99
+ end
100
+
101
+ def pid_file
102
+ self.class.root_path.join("log/varnishd.#{self.class.env}.pid")
103
+ end
104
+
105
+ def vcl_script_filename
106
+ self.class.root_path.join(self.class.vcl_script_filename)
107
+ end
108
+
109
+ def erb_vcl_script_filename
110
+ vcl_script_filename.sub_ext('.vcl.erb')
111
+ end
112
+
113
+ def log(message)
114
+ puts "** [#{self.class.name}] #{message}"
115
+ end
116
+
117
+ def execute(cmd)
118
+ log(cmd)
119
+ `#{cmd}`
120
+ end
121
+
122
+ def pid
123
+ if pid_file.exist?
124
+ pid_file.read
125
+ else
126
+ nil
127
+ end
128
+ end
129
+
130
+ end
131
+ end
data/lib/lacquer.rb CHANGED
@@ -8,7 +8,11 @@ require "active_support/core_ext"
8
8
 
9
9
  require "lacquer/configuration"
10
10
  require "lacquer/cache_utils"
11
+ require "lacquer/cache_control"
11
12
  require "lacquer/varnish"
13
+ require "lacquer/varnishd"
14
+
15
+ require "lacquer/railtie" if defined?(Rails::Railtie)
12
16
 
13
17
  module Lacquer
14
18
  class VarnishError < Exception; end # @private
data/rails/init.rb CHANGED
@@ -1 +1 @@
1
- require 'lacquer'
1
+ require 'lacquer'
@@ -0,0 +1 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'lacquer', 'recipes'))
@@ -0,0 +1,16 @@
1
+ backend default {
2
+ .host = "<%= backend.split(':').first %>";
3
+ .port = "<%= backend.split(':').last %>";
4
+ }
5
+
6
+ sub vcl_recv {
7
+ set req.backend = default;
8
+ unset req.http.Cookie;
9
+ set req.grace = 30m;
10
+ }
11
+
12
+ sub vcl_fetch {
13
+ unset beresp.http.Set-Cookie;
14
+ set beresp.grace = 30m;
15
+ }
16
+
@@ -0,0 +1,16 @@
1
+ backend default {
2
+ .host = "127.0.0.1";
3
+ .port = "3000";
4
+ }
5
+
6
+ sub vcl_recv {
7
+ set req.backend = default;
8
+ unset req.http.Cookie;
9
+ set req.grace = 30m;
10
+ }
11
+
12
+ sub vcl_fetch {
13
+ unset beresp.http.Set-Cookie;
14
+ set beresp.grace = 30m;
15
+ }
16
+
@@ -0,0 +1,10 @@
1
+ test:
2
+ listen: :80
3
+ telnet: localhost:6082
4
+ sbin_path: /usr/local/sbin
5
+ backend: 0.0.0.0:3000
6
+ storage: "file,#{Rails.root}/log/varnish,1GB"
7
+ working_dir: ""
8
+ user: "deploy"
9
+ params:
10
+ overflow_max: 2000
@@ -0,0 +1,72 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '../../spec_helper')
2
+ require 'lacquer/cache_control'
3
+
4
+ describe Lacquer::CacheControl do
5
+
6
+ describe "#register" do
7
+
8
+ it "persists cache settings for url" do
9
+ cache_control = described_class.new
10
+ cache_control.register :class_section, :url => "^/sv/class_sections/%s.*$", :args => "[0-9]+"
11
+ cache_control.store.first[:group].should == :class_section
12
+ cache_control.store.first[:url].should == "^/sv/class_sections/%s.*$"
13
+ cache_control.store.first[:args].should == ["[0-9]+"]
14
+ end
15
+
16
+ end
17
+
18
+ describe "#urls_for" do
19
+
20
+ it "returns urls to expire for object" do
21
+ cache_control = described_class.new
22
+ cache_control.register :class_section, :url => "^/sv/class_sections/%s.*$", :args => "[0-9]+"
23
+ cache_control.urls_for(:class_section, mock("ClassSection", :to_param => 1)).should == ["^/sv/class_sections/1.*$"]
24
+ end
25
+
26
+ end
27
+
28
+ context "vcl" do
29
+
30
+ it "returns all urls as vcl conditions" do
31
+ cache_control = described_class.new
32
+ cache_control.register :class_section, :url => "^/sv/class_sections/%s.*$", :args => "[0-9]+"
33
+ cache_control.register :class_section, :url => "^/sv/info_screens/%s.*$", :args => "[0-9]+"
34
+
35
+ conditions = cache_control.to_vcl_conditions
36
+ conditions.should include("req.url ~ \"^/sv/class_sections/[0-9]+.*$\"")
37
+ conditions.should include("||")
38
+ conditions.should include("req.url ~ \"^/sv/info_screens/[0-9]+.*$\"")
39
+ end
40
+
41
+ # if (req.url ~ "^/images" || req.url ~ "^/stylesheets" || req.url ~ "^/javascripts") {
42
+ # unset beresp.http.Set-Cookie;
43
+ # set beresp.ttl = 7d;
44
+ # return(deliver);
45
+ # }
46
+
47
+ it "returns vcl for override ttl on beresp" do
48
+ cache_control = described_class.new
49
+ cache_control.register :class_section, :url => "^/sv/competitions$", :expires_in => "7d"
50
+ override_ttl = cache_control.to_vcl_override_ttl_urls
51
+ override_ttl.should include('if(req.url ~ "^/sv/competitions$")')
52
+ override_ttl.should include('unset beresp.http.Set-Cookie')
53
+ override_ttl.should include('return(deliver)')
54
+ end
55
+
56
+ it "group by expires in" do
57
+ cache_control = described_class.new
58
+ cache_control.register :class_section, :url => "^/sv/competitions$", :expires_in => "1d"
59
+ cache_control.register :class_section, :url => "^/sv/competitions/%s$", :args => "[0-9]+", :expires_in => "2d"
60
+ cache_control.register :class_section, :url => "^/sv/competitions/%s/info_screen$", :args => "[0-9]+"
61
+
62
+ override_ttl = cache_control.to_vcl_override_ttl_urls
63
+ override_ttl.should include('if(req.url ~ "^/sv/competitions$")')
64
+ override_ttl.should include('set beresp.ttl = 1d')
65
+ override_ttl.should include('if(req.url ~ "^/sv/competitions/[0-9]+$")')
66
+ override_ttl.should include('set beresp.ttl = 2d')
67
+ override_ttl.should_not include('info_screen')
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -1,4 +1,5 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '../../spec_helper')
2
+ require 'lacquer/delayed_job_job'
2
3
 
3
4
  describe "Lacquer" do
4
5
  before(:each) do
@@ -17,7 +18,7 @@ describe "Lacquer" do
17
18
  end
18
19
 
19
20
  it "sends commands to varnish instantly" do
20
- @varnish_stub.should_receive(:purge).twice
21
+ @varnish_stub.should_receive(:purge).with('/', '/blog/posts').once
21
22
  @controller.clear_cache_for('/', '/blog/posts')
22
23
  end
23
24
 
@@ -30,8 +31,8 @@ describe "Lacquer" do
30
31
  describe "when backend is :delayed_job" do
31
32
  it "sends commands to a delayed_job queue" do
32
33
  Lacquer.configuration.job_backend = :delayed_job
33
-
34
- Delayed::Job.should_receive(:enqueue).twice
34
+ Lacquer::DelayedJobJob.should_receive(:new).with(['/', '/blog/posts'])
35
+ Delayed::Job.should_receive(:enqueue).once
35
36
  @controller.clear_cache_for('/', '/blog/posts')
36
37
  end
37
38
  end
@@ -40,7 +41,7 @@ describe "Lacquer" do
40
41
  it "sends commands to a resque queue" do
41
42
  Lacquer.configuration.job_backend = :resque
42
43
 
43
- Resque.should_receive(:enqueue).twice
44
+ Resque.should_receive(:enqueue).once
44
45
  @controller.clear_cache_for('/', '/blog/posts')
45
46
  end
46
47
  end
@@ -0,0 +1,71 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '../../spec_helper')
2
+
3
+ describe "Varnishd" do
4
+
5
+ before do
6
+ spec_root = Pathname.new(__FILE__).dirname.join('..').expand_path
7
+ Lacquer::Varnishd.stub!(:started_check_delay).and_return(0)
8
+ Lacquer::Varnishd.stub!(:env).and_return('test')
9
+ Lacquer::Varnishd.stub!(:root_path).and_return(spec_root)
10
+ end
11
+
12
+ def executes_with(regexp)
13
+ new_method = Lacquer::Varnishd.method(:new)
14
+ Lacquer::Varnishd.stub!(:new).and_return do |*args|
15
+ varnishd = new_method.call(*args)
16
+ varnishd.should_receive(:execute).with(regexp)
17
+ varnishd.stub!(:log)
18
+ varnishd
19
+ end
20
+ end
21
+
22
+ it "passes settings in the initailizer" do
23
+ Lacquer::Varnishd.new("listen" => ":80").listen.should == ":80"
24
+ end
25
+
26
+ it "loads settings from varnish_config" do
27
+ Lacquer::Varnishd.config.should have_key("listen")
28
+ Lacquer::Varnishd.config.should have_key("telnet")
29
+ Lacquer::Varnishd.config.should have_key("sbin_path")
30
+ Lacquer::Varnishd.config.should have_key("storage")
31
+ Lacquer::Varnishd.config["params"].should have_key('overflow_max')
32
+ end
33
+
34
+ it "returns full path to varnishd" do
35
+ executes_with(%r[/opt/varnishd/sbin/varnishd])
36
+ Lacquer::Varnishd.new("sbin_path" => "/opt/varnishd/sbin").start
37
+ end
38
+
39
+ it "returns pid file" do
40
+ executes_with(/log\/varnishd.test.pid/)
41
+ Lacquer::Varnishd.new("sbin_path" => "/opt/varnishd/sbin").start
42
+ end
43
+
44
+ it "returns params as string" do
45
+ Lacquer::Varnishd.new("params" => { "max" => 2000, "add" => 2 }).params_args.should == "-p max=2000 -p add=2"
46
+ end
47
+
48
+ it "returns listen arg as string" do
49
+ Lacquer::Varnishd.new("listen" => ":80").args.should include("-a :80")
50
+ end
51
+
52
+ it "starts varnishd with args and params" do
53
+ executes_with(%r[/opt/varnishd/sbin.*-P.*log/varnishd.test.pid])
54
+ Lacquer::Varnishd.new("sbin_path" => "/opt/varnishd/sbin", "params" => { "overflow_max" => 2000 }).start
55
+ end
56
+
57
+ it "raises error if vcl_script_file is not present" do
58
+ Lacquer::Varnishd.stub!(:vcl_script_filename).and_return("config/file_not_found.vcl")
59
+ expect {
60
+ Lacquer::Varnishd.new.vcl_script_path
61
+ }.to raise_error
62
+ end
63
+
64
+ it "renders vcl file when erb is present" do
65
+ Lacquer::Varnishd.stub!(:vcl_script_filename).and_return("config/generate.vcl")
66
+ result = Lacquer::Varnishd.new.render_vcl
67
+ result.should include('.host = "0.0.0.0"')
68
+ result.should include('.port = "3000"')
69
+ end
70
+
71
+ end
@@ -0,0 +1 @@
1
+ load File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'lacquer', 'tasks.rb'))
metadata CHANGED
@@ -1,131 +1,87 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lacquer
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 4
9
- - 1
10
- version: 0.4.1
4
+ prerelease: 6
5
+ version: 0.5.0.beta1
11
6
  platform: ruby
12
7
  authors:
13
8
  - Russ Smith (russ@bashme.org)
14
9
  - Ryan Johns
15
10
  - Garry Tan (garry@posterous.com), Gabe da Silveira (gabe@websaviour.com)
11
+ - "H\xC3\xA5kon Lerring"
16
12
  autorequire:
17
13
  bindir: bin
18
14
  cert_chain: []
19
15
 
20
- date: 2010-12-28 00:00:00 -08:00
16
+ date: 2011-04-25 00:00:00 -07:00
21
17
  default_executable:
22
18
  dependencies:
23
19
  - !ruby/object:Gem::Dependency
24
- type: :runtime
25
- prerelease: false
26
20
  name: activesupport
27
- version_requirements: &id001 !ruby/object:Gem::Requirement
21
+ requirement: &id001 !ruby/object:Gem::Requirement
28
22
  none: false
29
23
  requirements:
30
- - - "="
24
+ - - ~>
31
25
  - !ruby/object:Gem::Version
32
- hash: 5
33
- segments:
34
- - 3
35
- - 0
36
- - 1
37
- version: 3.0.1
38
- requirement: *id001
39
- - !ruby/object:Gem::Dependency
26
+ version: "3.0"
40
27
  type: :runtime
41
28
  prerelease: false
29
+ version_requirements: *id001
30
+ - !ruby/object:Gem::Dependency
42
31
  name: i18n
43
- version_requirements: &id002 !ruby/object:Gem::Requirement
32
+ requirement: &id002 !ruby/object:Gem::Requirement
44
33
  none: false
45
34
  requirements:
46
- - - "="
35
+ - - ~>
47
36
  - !ruby/object:Gem::Version
48
- hash: 13
49
- segments:
50
- - 0
51
- - 4
52
- - 1
53
- version: 0.4.1
54
- requirement: *id002
55
- - !ruby/object:Gem::Dependency
37
+ version: "0.4"
56
38
  type: :runtime
57
39
  prerelease: false
40
+ version_requirements: *id002
41
+ - !ruby/object:Gem::Dependency
58
42
  name: jeweler
59
- version_requirements: &id003 !ruby/object:Gem::Requirement
43
+ requirement: &id003 !ruby/object:Gem::Requirement
60
44
  none: false
61
45
  requirements:
62
46
  - - ">="
63
47
  - !ruby/object:Gem::Version
64
- hash: 3
65
- segments:
66
- - 0
67
48
  version: "0"
68
- requirement: *id003
69
- - !ruby/object:Gem::Dependency
70
49
  type: :runtime
71
50
  prerelease: false
51
+ version_requirements: *id003
52
+ - !ruby/object:Gem::Dependency
72
53
  name: rake
73
- version_requirements: &id004 !ruby/object:Gem::Requirement
54
+ requirement: &id004 !ruby/object:Gem::Requirement
74
55
  none: false
75
56
  requirements:
76
57
  - - ">="
77
58
  - !ruby/object:Gem::Version
78
- hash: 3
79
- segments:
80
- - 0
81
59
  version: "0"
82
- requirement: *id004
83
- - !ruby/object:Gem::Dependency
84
60
  type: :runtime
85
61
  prerelease: false
86
- name: rspec
87
- version_requirements: &id005 !ruby/object:Gem::Requirement
88
- none: false
89
- requirements:
90
- - - "="
91
- - !ruby/object:Gem::Version
92
- hash: 15
93
- segments:
94
- - 2
95
- - 0
96
- - 0
97
- version: 2.0.0
98
- requirement: *id005
62
+ version_requirements: *id004
99
63
  - !ruby/object:Gem::Dependency
100
- type: :runtime
101
- prerelease: false
102
64
  name: yard
103
- version_requirements: &id006 !ruby/object:Gem::Requirement
65
+ requirement: &id005 !ruby/object:Gem::Requirement
104
66
  none: false
105
67
  requirements:
106
68
  - - ">="
107
69
  - !ruby/object:Gem::Version
108
- hash: 3
109
- segments:
110
- - 0
111
70
  version: "0"
112
- requirement: *id006
113
- - !ruby/object:Gem::Dependency
114
- type: :development
71
+ type: :runtime
115
72
  prerelease: false
116
- name: rspec
117
- version_requirements: &id007 !ruby/object:Gem::Requirement
73
+ version_requirements: *id005
74
+ - !ruby/object:Gem::Dependency
75
+ name: erubis
76
+ requirement: &id006 !ruby/object:Gem::Requirement
118
77
  none: false
119
78
  requirements:
120
- - - ~>
79
+ - - ">="
121
80
  - !ruby/object:Gem::Version
122
- hash: 27
123
- segments:
124
- - 1
125
- - 3
126
- - 0
127
- version: 1.3.0
128
- requirement: *id007
81
+ version: "0"
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: *id006
129
85
  description: Rails drop in for Varnish support.
130
86
  email: russ@bashme.org
131
87
  executables: []
@@ -139,7 +95,6 @@ files:
139
95
  - .bundle/config
140
96
  - .document
141
97
  - Gemfile
142
- - Gemfile.lock
143
98
  - LICENSE
144
99
  - README.rdoc
145
100
  - Rakefile
@@ -149,19 +104,33 @@ files:
149
104
  - lib/generators/lacquer/USAGE
150
105
  - lib/generators/lacquer/install_generator.rb
151
106
  - lib/generators/lacquer/templates/initializer.rb
152
- - lib/generators/lacquer/templates/varnish.sample.vcl
107
+ - lib/generators/lacquer/templates/varnish.vcl.erb
108
+ - lib/generators/lacquer/templates/varnishd.yml
153
109
  - lib/lacquer.rb
110
+ - lib/lacquer/cache_control.rb
154
111
  - lib/lacquer/cache_utils.rb
112
+ - lib/lacquer/capistrano.rb
155
113
  - lib/lacquer/configuration.rb
156
114
  - lib/lacquer/delayed_job_job.rb
115
+ - lib/lacquer/railtie.rb
116
+ - lib/lacquer/recipes.rb
157
117
  - lib/lacquer/resque_job.rb
118
+ - lib/lacquer/tasks.rb
158
119
  - lib/lacquer/varnish.rb
120
+ - lib/lacquer/varnishd.rb
159
121
  - rails/init.rb
122
+ - recipes/lacquer.rb
123
+ - spec/config/generate.vcl.erb
124
+ - spec/config/varnish.vcl
125
+ - spec/config/varnishd.yml
126
+ - spec/lacquer/cache_control_spec.rb
160
127
  - spec/lacquer/cache_utils_spec.rb
161
128
  - spec/lacquer/delayed_job_job_spec.rb
162
129
  - spec/lacquer/resque_job_spec.rb
163
130
  - spec/lacquer/varnish_spec.rb
131
+ - spec/lacquer/varnishd_spec.rb
164
132
  - spec/spec_helper.rb
133
+ - tasks/lacquer.rake
165
134
  has_rdoc: true
166
135
  homepage: http://github.com/russ/lacquer
167
136
  licenses: []
@@ -176,29 +145,28 @@ required_ruby_version: !ruby/object:Gem::Requirement
176
145
  requirements:
177
146
  - - ">="
178
147
  - !ruby/object:Gem::Version
179
- hash: 3
148
+ hash: 1714554342870495979
180
149
  segments:
181
150
  - 0
182
151
  version: "0"
183
152
  required_rubygems_version: !ruby/object:Gem::Requirement
184
153
  none: false
185
154
  requirements:
186
- - - ">="
155
+ - - ">"
187
156
  - !ruby/object:Gem::Version
188
- hash: 3
189
- segments:
190
- - 0
191
- version: "0"
157
+ version: 1.3.1
192
158
  requirements: []
193
159
 
194
160
  rubyforge_project:
195
- rubygems_version: 1.3.7
161
+ rubygems_version: 1.5.0
196
162
  signing_key:
197
163
  specification_version: 3
198
164
  summary: Rails drop in for Varnish support.
199
165
  test_files:
166
+ - spec/lacquer/cache_control_spec.rb
200
167
  - spec/lacquer/cache_utils_spec.rb
201
168
  - spec/lacquer/delayed_job_job_spec.rb
202
169
  - spec/lacquer/resque_job_spec.rb
203
170
  - spec/lacquer/varnish_spec.rb
171
+ - spec/lacquer/varnishd_spec.rb
204
172
  - spec/spec_helper.rb
data/Gemfile.lock DELETED
@@ -1,34 +0,0 @@
1
- GEM
2
- remote: http://rubygems.org/
3
- specs:
4
- activesupport (3.0.1)
5
- diff-lcs (1.1.2)
6
- git (1.2.5)
7
- i18n (0.4.1)
8
- jeweler (1.5.2)
9
- bundler (~> 1.0.0)
10
- git (>= 1.2.5)
11
- rake
12
- rake (0.8.7)
13
- rspec (2.0.0)
14
- rspec-core (= 2.0.0)
15
- rspec-expectations (= 2.0.0)
16
- rspec-mocks (= 2.0.0)
17
- rspec-core (2.0.0)
18
- rspec-expectations (2.0.0)
19
- diff-lcs (>= 1.1.2)
20
- rspec-mocks (2.0.0)
21
- rspec-core (= 2.0.0)
22
- rspec-expectations (= 2.0.0)
23
- yard (0.6.4)
24
-
25
- PLATFORMS
26
- ruby
27
-
28
- DEPENDENCIES
29
- activesupport (= 3.0.1)
30
- i18n (= 0.4.1)
31
- jeweler
32
- rake
33
- rspec (= 2.0.0)
34
- yard