primer 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +213 -0
- data/example/README.rdoc +69 -0
- data/example/application.rb +26 -0
- data/example/config.ru +5 -0
- data/example/environment.rb +31 -0
- data/example/models/blog_post.rb +4 -0
- data/example/models/connection.rb +10 -0
- data/example/public/style.css +75 -0
- data/example/script/setup_database.rb +11 -0
- data/example/views/index.erb +13 -0
- data/example/views/layout.erb +26 -0
- data/example/views/show.erb +7 -0
- data/example/worker.rb +3 -0
- data/lib/javascript/primer.js +36 -0
- data/lib/primer/bus/amqp.rb +43 -0
- data/lib/primer/bus/memory.rb +12 -0
- data/lib/primer/bus.rb +30 -0
- data/lib/primer/cache/memory.rb +60 -0
- data/lib/primer/cache/redis.rb +70 -0
- data/lib/primer/cache.rb +84 -0
- data/lib/primer/enabler.rb +18 -0
- data/lib/primer/helpers.rb +66 -0
- data/lib/primer/real_time.rb +80 -0
- data/lib/primer/route_set.rb +50 -0
- data/lib/primer/watcher/active_record_macros.rb +70 -0
- data/lib/primer/watcher/macros.rb +70 -0
- data/lib/primer/watcher.rb +62 -0
- data/lib/primer/worker/active_record_agent.rb +120 -0
- data/lib/primer/worker.rb +34 -0
- data/lib/primer.rb +31 -0
- data/spec/models/artist.rb +10 -0
- data/spec/models/blog_post.rb +5 -0
- data/spec/models/calendar.rb +7 -0
- data/spec/models/concert.rb +6 -0
- data/spec/models/performance.rb +6 -0
- data/spec/models/person.rb +14 -0
- data/spec/models/watchable.rb +17 -0
- data/spec/primer/bus_spec.rb +31 -0
- data/spec/primer/cache_spec.rb +309 -0
- data/spec/primer/helpers/erb_spec.rb +89 -0
- data/spec/primer/watcher/active_record_spec.rb +189 -0
- data/spec/primer/watcher_spec.rb +101 -0
- data/spec/schema.rb +31 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/templates/page.erb +3 -0
- 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
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -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
|
+
|
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
|
+
|