primer 0.1.0

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.
Files changed (46) hide show
  1. data/README.rdoc +213 -0
  2. data/example/README.rdoc +69 -0
  3. data/example/application.rb +26 -0
  4. data/example/config.ru +5 -0
  5. data/example/environment.rb +31 -0
  6. data/example/models/blog_post.rb +4 -0
  7. data/example/models/connection.rb +10 -0
  8. data/example/public/style.css +75 -0
  9. data/example/script/setup_database.rb +11 -0
  10. data/example/views/index.erb +13 -0
  11. data/example/views/layout.erb +26 -0
  12. data/example/views/show.erb +7 -0
  13. data/example/worker.rb +3 -0
  14. data/lib/javascript/primer.js +36 -0
  15. data/lib/primer/bus/amqp.rb +43 -0
  16. data/lib/primer/bus/memory.rb +12 -0
  17. data/lib/primer/bus.rb +30 -0
  18. data/lib/primer/cache/memory.rb +60 -0
  19. data/lib/primer/cache/redis.rb +70 -0
  20. data/lib/primer/cache.rb +84 -0
  21. data/lib/primer/enabler.rb +18 -0
  22. data/lib/primer/helpers.rb +66 -0
  23. data/lib/primer/real_time.rb +80 -0
  24. data/lib/primer/route_set.rb +50 -0
  25. data/lib/primer/watcher/active_record_macros.rb +70 -0
  26. data/lib/primer/watcher/macros.rb +70 -0
  27. data/lib/primer/watcher.rb +62 -0
  28. data/lib/primer/worker/active_record_agent.rb +120 -0
  29. data/lib/primer/worker.rb +34 -0
  30. data/lib/primer.rb +31 -0
  31. data/spec/models/artist.rb +10 -0
  32. data/spec/models/blog_post.rb +5 -0
  33. data/spec/models/calendar.rb +7 -0
  34. data/spec/models/concert.rb +6 -0
  35. data/spec/models/performance.rb +6 -0
  36. data/spec/models/person.rb +14 -0
  37. data/spec/models/watchable.rb +17 -0
  38. data/spec/primer/bus_spec.rb +31 -0
  39. data/spec/primer/cache_spec.rb +309 -0
  40. data/spec/primer/helpers/erb_spec.rb +89 -0
  41. data/spec/primer/watcher/active_record_spec.rb +189 -0
  42. data/spec/primer/watcher_spec.rb +101 -0
  43. data/spec/schema.rb +31 -0
  44. data/spec/spec_helper.rb +60 -0
  45. data/spec/templates/page.erb +3 -0
  46. metadata +235 -0
@@ -0,0 +1,189 @@
1
+ require 'spec_helper'
2
+
3
+ describe Primer::Watcher::ActiveRecordMacros do
4
+ before do
5
+ @person = Person.create(:name => "Abe")
6
+ @impostor = Person.create(:name => "Aaron")
7
+ @post = @person.blog_posts.create(:title => "web scale")
8
+ @id = @person.id
9
+
10
+ @artist = Artist.create(:name => "Wolf Parade")
11
+ @concert = Concert.create(:date => 6.months.ago, :venue => "Borderline")
12
+ @festival = Concert.create(:date => 3.months.ago, :venue => "End of the Road")
13
+ @calendar = Calendar.create(:artists => [@artist])
14
+
15
+ @artist.concerts << @festival
16
+
17
+ Primer::Worker::ActiveRecordAgent.bind_to_bus
18
+ Primer::Watcher.enable!
19
+ end
20
+
21
+ after do
22
+ @person.delete
23
+ end
24
+
25
+ def should_publish(topic, *message)
26
+ @publish ||= Primer.bus.method(:publish)
27
+ Primer.bus.should_receive(:publish).with(topic, message) do |*args|
28
+ @publish.call(*args)
29
+ end
30
+ end
31
+
32
+ describe "#primer_identifier" do
33
+ it "returns a tuple that tells us enough to find the object" do
34
+ @person.primer_identifier.should == ["ActiveRecord", "Person", @person.id]
35
+ end
36
+ end
37
+
38
+ it "is mixed in automatically when using Primer with ActiveRecord" do
39
+ Person.should be_kind_of(Primer::Watcher::ActiveRecordMacros)
40
+ end
41
+
42
+ it "watches ActiveRecord attributes" do
43
+ @person.name.should == "Abe"
44
+ Primer::Watcher.call_log.should == [[@person, :name, [], nil, "Abe"]]
45
+ end
46
+
47
+ it "watches calls to has_many associations" do
48
+ @person.blog_posts.count.should == 1
49
+ Primer::Watcher.call_log.should include([@person, :blog_posts, [], nil, [@post]])
50
+ end
51
+
52
+ it "watches calls to belongs_to associations" do
53
+ @post.person.should == @person
54
+ Primer::Watcher.call_log.should include([@post, :person, [], nil, @person])
55
+ end
56
+
57
+ it "logs calls made inside other methods" do
58
+ @person.all_attributes.should == [@id, "Abe"]
59
+ Primer::Watcher.call_log.should == [
60
+ [@person, :id, [], nil, @id ],
61
+ [@person, :name, [], nil, "Abe"]
62
+ ]
63
+ end
64
+
65
+ it "publishes a message when an attribute changes" do
66
+ should_publish(:active_record, :update, "Person", anything, anything)
67
+ should_publish(:changes, "ActiveRecord", "Person", @person.id, "name")
68
+ @person.update_attribute(:name, "Aaron")
69
+ end
70
+
71
+ it "publishes messages when an object is deleted" do
72
+ should_publish(:active_record, :destroy, "Person", anything)
73
+ should_publish(:changes, "ActiveRecord", "Person", @person.id, "id")
74
+ should_publish(:changes, "ActiveRecord", "Person", @person.id, "name")
75
+ should_publish(:changes, "ActiveRecord", "Person", @person.id, "age")
76
+ should_publish(:changes, "ActiveRecord", "BlogPost", @post.id, "person")
77
+ @person.destroy
78
+ end
79
+
80
+ it "publishes a message about a belongs_to association when the foreign key changes" do
81
+ should_publish(:active_record, :create, "BlogPost", anything)
82
+ should_publish(:changes, "ActiveRecord", "Person", @person.id, "blog_posts")
83
+ BlogPost.create(:person => @person, :title => "How to make a time machine")
84
+ end
85
+
86
+ it "publishes a message about a belongs_to association when the object changes" do
87
+ should_publish(:active_record, :update, "BlogPost", anything, anything)
88
+ should_publish(:changes, "ActiveRecord", "BlogPost", @post.id, "person_id")
89
+ should_publish(:changes, "ActiveRecord", "BlogPost", @post.id, "person")
90
+ should_publish(:changes, "ActiveRecord", "Person", @impostor.id, "blog_posts")
91
+ should_publish(:changes, "ActiveRecord", "Person", @person.id, "blog_posts")
92
+ @post.update_attribute(:person, @impostor)
93
+ end
94
+
95
+ it "publishes a message when a has_many collection gains a member" do
96
+ should_publish(:active_record, :create, "BlogPost", anything)
97
+ should_publish(:changes, "ActiveRecord", "Person", @person.id, "blog_posts")
98
+ BlogPost.create(:person => @person, :title => "How to make a time machine")
99
+ end
100
+
101
+ it "publishes a message when a has_many collection loses a member" do
102
+ should_publish(:active_record, :destroy, "BlogPost", anything)
103
+ should_publish(:changes, "ActiveRecord", "BlogPost", @post.id, "id")
104
+ should_publish(:changes, "ActiveRecord", "BlogPost", @post.id, "person_id")
105
+ should_publish(:changes, "ActiveRecord", "BlogPost", @post.id, "title")
106
+ should_publish(:changes, "ActiveRecord", "BlogPost", @post.id, "person")
107
+ should_publish(:changes, "ActiveRecord", "Person", @person.id, "blog_posts")
108
+ @post.destroy
109
+ end
110
+
111
+ it "publishes a message when an object is pushed to a has_many :through has_many" do
112
+ should_publish(:active_record, :create, "Performance", anything)
113
+ should_publish(:changes, "ActiveRecord", "Concert", @concert.id, "performances")
114
+ should_publish(:changes, "ActiveRecord", "Artist", @artist.id, "performances")
115
+ should_publish(:changes, "ActiveRecord", "Artist", @artist.id, "concerts")
116
+ @artist.concerts << @concert
117
+ end
118
+
119
+ it "publishes a message when a join object is pushed to a has_many :through has_many" do
120
+ should_publish(:active_record, :create, "Performance", anything)
121
+ should_publish(:changes, "ActiveRecord", "Concert", @concert.id, "performances")
122
+ should_publish(:changes, "ActiveRecord", "Artist", @artist.id, "performances")
123
+ should_publish(:changes, "ActiveRecord", "Artist", @artist.id, "concerts")
124
+ @artist.performances << Performance.new(:concert => @concert)
125
+ end
126
+
127
+ it "publishes a message when a join object is created for has_many :through has_many" do
128
+ should_publish(:active_record, :create, "Performance", anything)
129
+ should_publish(:changes, "ActiveRecord", "Concert", @concert.id, "performances")
130
+ should_publish(:changes, "ActiveRecord", "Artist", @artist.id, "performances")
131
+ should_publish(:changes, "ActiveRecord", "Artist", @artist.id, "concerts")
132
+ Performance.create(:concert => @concert, :artist => @artist)
133
+ end
134
+
135
+ it "publishes messages when a join object is deleted from a has_many :through has_many collection" do
136
+ @performance = @festival.performances.first
137
+ should_publish(:active_record, :destroy, "Performance", anything)
138
+ should_publish(:changes, "ActiveRecord", "Performance", @performance.id, "artist_id")
139
+ should_publish(:changes, "ActiveRecord", "Performance", @performance.id, "artist")
140
+ should_publish(:changes, "ActiveRecord", "Performance", @performance.id, "concert_id")
141
+ should_publish(:changes, "ActiveRecord", "Performance", @performance.id, "concert")
142
+ should_publish(:changes, "ActiveRecord", "Performance", @performance.id, "id")
143
+ should_publish(:changes, "ActiveRecord", "Artist", @artist.id, "performances")
144
+ should_publish(:changes, "ActiveRecord", "Artist", @artist.id, "concerts")
145
+ should_publish(:changes, "ActiveRecord", "Concert", @festival.id, "performances")
146
+ @artist.performances.first.destroy
147
+ end
148
+
149
+ it "publishes messages when a member is deleted from a has_many :through has_many collection" do
150
+ @performance = @festival.performances.first
151
+ should_publish(:active_record, :destroy, "Performance", anything)
152
+ should_publish(:changes, "ActiveRecord", "Performance", @performance.id, "artist_id")
153
+ should_publish(:changes, "ActiveRecord", "Performance", @performance.id, "artist")
154
+ should_publish(:changes, "ActiveRecord", "Artist", @artist.id, "performances")
155
+ should_publish(:changes, "ActiveRecord", "Artist", @artist.id, "concerts")
156
+ should_publish(:changes, "ActiveRecord", "Performance", @performance.id, "concert_id")
157
+ should_publish(:changes, "ActiveRecord", "Performance", @performance.id, "concert")
158
+ should_publish(:changes, "ActiveRecord", "Concert", @festival.id, "performances")
159
+ should_publish(:changes, "ActiveRecord", "Performance", @performance.id, "id")
160
+ should_publish(:active_record, :destroy, "Concert", anything)
161
+ should_publish(:changes, "ActiveRecord", "Concert", @festival.id, "id")
162
+ should_publish(:changes, "ActiveRecord", "Concert", @festival.id, "calendar_id")
163
+ should_publish(:changes, "ActiveRecord", "Concert", @festival.id, "calendar")
164
+ should_publish(:changes, "ActiveRecord", "Concert", @festival.id, "date")
165
+ should_publish(:changes, "ActiveRecord", "Concert", @festival.id, "venue")
166
+ @artist.concerts.first.destroy
167
+ end
168
+
169
+ it "publishes messages when a join object is pushed to a has_many :through belongs_to" do
170
+ should_publish(:active_record, :update, "Concert", anything, anything)
171
+ should_publish(:changes, "ActiveRecord", "Concert", @concert.id, "calendar_id")
172
+ should_publish(:changes, "ActiveRecord", "Concert", @concert.id, "calendar")
173
+ should_publish(:changes, "ActiveRecord", "Calendar", @calendar.id, "gigs")
174
+ should_publish(:changes, "ActiveRecord", "Artist", @artist.id, "upcoming_gigs")
175
+ @calendar.gigs << @concert
176
+ end
177
+
178
+ it "publishes messages when a join object is removed from a has_many :through belongs_to" do
179
+ @calendar.gigs << @festival
180
+ should_publish(:active_record, :update, "Concert", anything, anything)
181
+ should_publish(:changes, "ActiveRecord", "Concert", @festival.id, "calendar_id")
182
+ should_publish(:changes, "ActiveRecord", "Concert", @festival.id, "calendar")
183
+ should_publish(:changes, "ActiveRecord", "Calendar", @calendar.id, "gigs")
184
+ should_publish(:changes, "ActiveRecord", "Artist", @artist.id, "upcoming_gigs")
185
+ @festival.calendar = nil
186
+ @festival.save
187
+ end
188
+ end
189
+
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ describe Primer::Watcher do
4
+ let(:watchable) { Watchable.new("Aaron") }
5
+
6
+ describe "#primer_identifier" do
7
+ it "returns a tuple that tells us enough to find the object" do
8
+ watchable.primer_identifier.should == ["Object", "Watchable", watchable.object_id]
9
+ end
10
+ end
11
+
12
+ describe "with watching disabled" do
13
+ before { Primer::Watcher.disable! }
14
+
15
+ it "lets methods run as usual" do
16
+ watchable.name.should == "Aaron"
17
+ end
18
+
19
+ it "does not log method calls" do
20
+ watchable.name
21
+ Primer::Watcher.call_log.should be_empty
22
+ end
23
+ end
24
+
25
+ describe "with watching enabled" do
26
+ before { Primer::Watcher.enable! }
27
+
28
+ it "lets methods return their usual return values" do
29
+ watchable.name.should == "Aaron"
30
+ end
31
+
32
+ it "logs the monitored method calls" do
33
+ watchable.name
34
+ Primer::Watcher.call_log.should == [[watchable, :name, [], nil, "Aaron"]]
35
+ end
36
+
37
+ it "logs arguments given to methods" do
38
+ watchable.is_called?("Aaron")
39
+ watchable.is_called?("Abe")
40
+ Primer::Watcher.call_log.should == [
41
+ [watchable, :is_called?, ["Aaron"], nil, true ],
42
+ [watchable, :is_called?, ["Abe"], nil, false]
43
+ ]
44
+ end
45
+
46
+ it "logs blocks passed to methods" do
47
+ block = lambda {}
48
+ watchable.name(&block)
49
+ Primer::Watcher.call_log.should == [[watchable, :name, [], block, "Aaron"]]
50
+ end
51
+
52
+ it "does not log after you disable the watcher" do
53
+ Primer::Watcher.disable!
54
+ watchable.name.should == "Aaron"
55
+ watchable.is_called?("Aaron").should be_true
56
+ watchable.is_called?("Abe").should be_false
57
+ Primer::Watcher.call_log.should be_empty
58
+ end
59
+ end
60
+
61
+ describe ".watching" do
62
+ it "returns the value of the block" do
63
+ Primer::Watcher.watching { watchable.name }.should == "Aaron"
64
+ end
65
+
66
+ it "logs calls during the block to a list you supply" do
67
+ calls = []
68
+ Primer::Watcher.watching(calls) { watchable.name }
69
+ calls.should == [[watchable, :name, [], nil, "Aaron"]]
70
+ end
71
+
72
+ it "does not log calls outside of the block" do
73
+ Primer::Watcher.watching { watchable.name }
74
+ watchable.name
75
+ Primer::Watcher.call_log.should == [[watchable, :name, [], nil, "Aaron"]]
76
+ end
77
+
78
+ it "allows nested blocks to just capture specific scopes" do
79
+ block = lambda {}
80
+
81
+ all_calls, inner_calls = [], []
82
+ Primer::Watcher.watching(all_calls) do
83
+ watchable.name
84
+ Primer::Watcher.watching(inner_calls) do
85
+ watchable.is_called?("Abe")
86
+ end
87
+ watchable.is_called?("Aaron", &block)
88
+ end
89
+
90
+ all_calls.should == [
91
+ [watchable, :name, [], nil, "Aaron"],
92
+ [watchable, :is_called?, ["Abe"], nil, false ],
93
+ [watchable, :is_called?, ["Aaron"], block, true ]
94
+ ]
95
+ inner_calls.should == [
96
+ [watchable, :is_called?, ["Abe"], nil, false ]
97
+ ]
98
+ end
99
+ end
100
+ end
101
+
data/spec/schema.rb ADDED
@@ -0,0 +1,31 @@
1
+ ActiveRecord::Schema.define do |version|
2
+ create_table :artists, :force => true do |t|
3
+ t.belongs_to :calendar
4
+ t.string :name
5
+ end
6
+
7
+ create_table :calendars, :force => true do |t|
8
+ end
9
+
10
+ create_table :concerts, :force => true do |t|
11
+ t.belongs_to :calendar
12
+ t.date :date
13
+ t.string :venue
14
+ end
15
+
16
+ create_table :performances, :force => true do |t|
17
+ t.belongs_to :artist
18
+ t.belongs_to :concert
19
+ end
20
+
21
+ create_table :blog_posts, :force => true do |t|
22
+ t.belongs_to :person
23
+ t.string :title
24
+ end
25
+
26
+ create_table :people, :force => true do |t|
27
+ t.string :name
28
+ t.integer :age
29
+ end
30
+ end
31
+
@@ -0,0 +1,60 @@
1
+ dir = File.expand_path(File.dirname(__FILE__))
2
+ $:.unshift(dir)
3
+
4
+ require dir + '/../lib/primer'
5
+ require 'tilt'
6
+ require 'erb'
7
+ require 'action_controller'
8
+
9
+ require 'fileutils'
10
+ require 'active_record'
11
+ FileUtils.mkdir_p(dir + '/db')
12
+ ActiveRecord::Base.establish_connection(
13
+ :adapter => 'sqlite3',
14
+ :database => dir + '/db/test.sqlite3')
15
+
16
+ require 'schema'
17
+
18
+ require 'models/watchable'
19
+ require 'models/artist'
20
+ require 'models/calendar'
21
+ require 'models/concert'
22
+ require 'models/performance'
23
+ require 'models/blog_post'
24
+ require 'models/person'
25
+
26
+ module Helper
27
+ def self.next_id
28
+ @next_id ||= 0
29
+ @next_id += 1
30
+ @next_id
31
+ end
32
+ end
33
+
34
+ RSpec.configure do |config|
35
+ config.before do
36
+ Primer::Watcher.disable!
37
+ Primer.bus = Primer::Bus::Memory.new
38
+ Primer.cache = nil
39
+ Primer.real_time = false
40
+ end
41
+
42
+ config.after do
43
+ if Primer.cache
44
+ Primer.cache.clear
45
+ Primer.cache.routes = nil
46
+ end
47
+ Primer::Watcher.reset!
48
+ Primer.bus.unsubscribe_all
49
+
50
+ [ BlogPost,
51
+ Person,
52
+ Artist,
53
+ Calendar,
54
+ Concert,
55
+ Performance
56
+
57
+ ].each { |m| m.delete_all }
58
+ end
59
+ end
60
+
@@ -0,0 +1,3 @@
1
+ Welcome, <%= primer '/user' %>
2
+ <% primer '/cache/key' do %>Hello, <%= name %><% end %>
3
+ Thanks
metadata ADDED
@@ -0,0 +1,235 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: primer
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - James Coglan
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-11-25 00:00:00 +00:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: redis
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 2
30
+ - 1
31
+ - 1
32
+ version: 2.1.1
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: sinatra
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ segments:
44
+ - 1
45
+ - 1
46
+ - 0
47
+ version: 1.1.0
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: amqp
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ~>
57
+ - !ruby/object:Gem::Version
58
+ segments:
59
+ - 0
60
+ - 6
61
+ - 7
62
+ version: 0.6.7
63
+ type: :runtime
64
+ version_requirements: *id003
65
+ - !ruby/object:Gem::Dependency
66
+ name: faye
67
+ prerelease: false
68
+ requirement: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ - 5
76
+ version: "0.5"
77
+ type: :runtime
78
+ version_requirements: *id004
79
+ - !ruby/object:Gem::Dependency
80
+ name: rspec
81
+ prerelease: false
82
+ requirement: &id005 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ type: :development
91
+ version_requirements: *id005
92
+ - !ruby/object:Gem::Dependency
93
+ name: activerecord
94
+ prerelease: false
95
+ requirement: &id006 !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ type: :development
104
+ version_requirements: *id006
105
+ - !ruby/object:Gem::Dependency
106
+ name: sqlite3
107
+ prerelease: false
108
+ requirement: &id007 !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ segments:
114
+ - 0
115
+ version: "0"
116
+ type: :development
117
+ version_requirements: *id007
118
+ - !ruby/object:Gem::Dependency
119
+ name: actionpack
120
+ prerelease: false
121
+ requirement: &id008 !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ segments:
127
+ - 0
128
+ version: "0"
129
+ type: :development
130
+ version_requirements: *id008
131
+ - !ruby/object:Gem::Dependency
132
+ name: tilt
133
+ prerelease: false
134
+ requirement: &id009 !ruby/object:Gem::Requirement
135
+ none: false
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ segments:
140
+ - 0
141
+ version: "0"
142
+ type: :development
143
+ version_requirements: *id009
144
+ description:
145
+ email: jcoglan@gmail.com
146
+ executables: []
147
+
148
+ extensions: []
149
+
150
+ extra_rdoc_files:
151
+ - README.rdoc
152
+ - example/README.rdoc
153
+ files:
154
+ - README.rdoc
155
+ - spec/spec_helper.rb
156
+ - spec/primer/bus_spec.rb
157
+ - spec/primer/watcher_spec.rb
158
+ - spec/primer/helpers/erb_spec.rb
159
+ - spec/primer/watcher/active_record_spec.rb
160
+ - spec/primer/cache_spec.rb
161
+ - spec/templates/page.erb
162
+ - spec/schema.rb
163
+ - spec/models/calendar.rb
164
+ - spec/models/blog_post.rb
165
+ - spec/models/watchable.rb
166
+ - spec/models/performance.rb
167
+ - spec/models/artist.rb
168
+ - spec/models/person.rb
169
+ - spec/models/concert.rb
170
+ - lib/javascript/primer.js
171
+ - lib/primer/enabler.rb
172
+ - lib/primer/cache/memory.rb
173
+ - lib/primer/cache/redis.rb
174
+ - lib/primer/real_time.rb
175
+ - lib/primer/watcher.rb
176
+ - lib/primer/route_set.rb
177
+ - lib/primer/worker/active_record_agent.rb
178
+ - lib/primer/bus/memory.rb
179
+ - lib/primer/bus/amqp.rb
180
+ - lib/primer/worker.rb
181
+ - lib/primer/bus.rb
182
+ - lib/primer/watcher/active_record_macros.rb
183
+ - lib/primer/watcher/macros.rb
184
+ - lib/primer/cache.rb
185
+ - lib/primer/helpers.rb
186
+ - lib/primer.rb
187
+ - example/application.rb
188
+ - example/config.ru
189
+ - example/README.rdoc
190
+ - example/script/setup_database.rb
191
+ - example/public/style.css
192
+ - example/worker.rb
193
+ - example/environment.rb
194
+ - example/views/show.erb
195
+ - example/views/layout.erb
196
+ - example/views/index.erb
197
+ - example/models/blog_post.rb
198
+ - example/models/connection.rb
199
+ has_rdoc: true
200
+ homepage: http://github.com/jcoglan/primer
201
+ licenses: []
202
+
203
+ post_install_message:
204
+ rdoc_options:
205
+ - --main
206
+ - README.rdoc
207
+ - --title
208
+ - Primer
209
+ require_paths:
210
+ - lib
211
+ required_ruby_version: !ruby/object:Gem::Requirement
212
+ none: false
213
+ requirements:
214
+ - - ">="
215
+ - !ruby/object:Gem::Version
216
+ segments:
217
+ - 0
218
+ version: "0"
219
+ required_rubygems_version: !ruby/object:Gem::Requirement
220
+ none: false
221
+ requirements:
222
+ - - ">="
223
+ - !ruby/object:Gem::Version
224
+ segments:
225
+ - 0
226
+ version: "0"
227
+ requirements: []
228
+
229
+ rubyforge_project:
230
+ rubygems_version: 1.3.7
231
+ signing_key:
232
+ specification_version: 3
233
+ summary: Intelligent caching, no observers necessary
234
+ test_files: []
235
+