lacquer 0.4.1 → 0.5.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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