Browse files

Use draft blurbs in development

  • Loading branch information...
1 parent 0cd076e commit ecc7f6592a03378487ea1909e018fd4ccbc37160 @jferris jferris committed Oct 6, 2010
View
1 Gemfile
@@ -14,4 +14,5 @@ gem "yard", :require => false
gem "aruba"
gem "ruby-debug"
gem "json"
+gem "thin"
View
7 Gemfile.lock
@@ -24,7 +24,9 @@ GEM
gherkin (~> 2.1.4)
json_pure (~> 1.4.3)
term-ansicolor (~> 1.0.4)
+ daemons (1.1.0)
diff-lcs (1.1.2)
+ eventmachine (0.12.10)
gherkin (2.1.5)
trollop (~> 1.16.2)
httparty (0.6.1)
@@ -54,6 +56,10 @@ GEM
rack (>= 1.0)
sqlite3-ruby (1.3.1)
term-ansicolor (1.0.5)
+ thin (1.2.7)
+ daemons (>= 1.0.9)
+ eventmachine (>= 0.12.6)
+ rack (>= 1.0.0)
trollop (1.16.2)
webmock (1.3.5)
addressable (>= 2.1.1)
@@ -76,5 +82,6 @@ DEPENDENCIES
sham_rack
sinatra
sqlite3-ruby
+ thin
webmock
yard
View
44 features/rails.feature
@@ -7,8 +7,8 @@ Feature: Using copycopter in a rails app
Scenario: copycopter in the controller
Given the "abc123" project has the following blurbs:
- | key | published content |
- | en.users.index.controller-test | This is a test |
+ | key | draft content |
+ | en.users.index.controller-test | This is a test |
When I write to "app/controllers/users_controller.rb" with:
"""
class UsersController < ActionController::Base
@@ -34,8 +34,8 @@ Feature: Using copycopter in a rails app
Scenario: copycopter in the view
Given the "abc123" project has the following blurbs:
- | key | published content |
- | en.users.index.view-test | This is a test |
+ | key | draft content |
+ | en.users.index.view-test | This is a test |
When I write to "app/controllers/users_controller.rb" with:
"""
class UsersController < ActionController::Base
@@ -61,8 +61,8 @@ Feature: Using copycopter in a rails app
Scenario: copycopter detects updates to copy
Given the "abc123" project has the following blurbs:
- | key | published content |
- | en.users.index.controller-test | Old content |
+ | key | draft content |
+ | en.users.index.controller-test | Old content |
When I write to "app/controllers/users_controller.rb" with:
"""
class UsersController < ActionController::Base
@@ -86,8 +86,8 @@ Feature: Using copycopter in a rails app
And I visit /users/
Then the output should contain "Old content"
When the the following blurbs are updated in the "abc123" project:
- | key | published content |
- | en.users.index.controller-test | New content |
+ | key | draft content |
+ | en.users.index.controller-test | New content |
And I wait for changes to be synchronized
And I visit /users/
Then the output should contain "New content"
@@ -119,3 +119,31 @@ Feature: Using copycopter in a rails app
| key | draft content |
| en.users.index.404 | not found |
+ Scenario: copycopter in development
+ Given the "abc123" project has the following blurbs:
+ | key | published content | draft content |
+ | en.users.index.controller-test | This is a test | Extra extra |
+ When I write to "app/controllers/users_controller.rb" with:
+ """
+ class UsersController < ActionController::Base
+ def index
+ @text = t("users.index.controller-test", :default => "default")
+ end
+ end
+ """
+ When I write to "config/routes.rb" with:
+ """
+ ActionController::Routing::Routes.draw do |map|
+ map.resources :users
+ end
+ """
+ When I write to "app/views/users/index.html.erb" with:
+ """
+ <%= @text %>
+ """
+ When I configure the copycopter client to used published data
+ And I start the application
+ And I wait for changes to be synchronized
+ And I visit /users/
+ Then the output should contain "This is a test"
+
View
15 features/step_definitions/copycopter_server_steps.rb
@@ -5,17 +5,12 @@
end
Given /^the "([^"]*)" project has the following blurbs:$/ do |api_key, table|
- project = FakeCopycopterApp.projects[api_key]
+ project = FakeCopycopterApp.project(api_key)
table.hashes.each do |blurb_hash|
key = blurb_hash['key']
-
- if blurb_hash['draft content']
- project.draft[key] = blurb_hash['draft content']
- end
-
- if blurb_hash['published content']
- project.published[key] = blurb_hash['published content']
- end
+ data = { 'draft' => { key => blurb_hash['draft content'] },
+ 'published' => { key => blurb_hash['published content'] } }
+ project.update(data)
end
end
@@ -24,7 +19,7 @@
end
Then /^the "([^"]*)" project should have the following blurbs:$/ do |api_key, table|
- project = FakeCopycopterApp.projects[api_key]
+ project = FakeCopycopterApp.project(api_key)
table.hashes.each do |blurb_hash|
key = blurb_hash['key']
View
19 features/step_definitions/rails_steps.rb
@@ -20,18 +20,23 @@
When "I start the application" do
in_current_dir do
- require 'config/environment'
+ RailsServer.start(ENV['RAILS_PORT'])
end
end
When "I visit /$path" do |path|
- app = ActionController::Dispatcher.new
- request = Rack::MockRequest.new(app)
- response = request.get(path)
- @last_stdout = response.body
+ @last_stdout = RailsServer.get(path)
+end
- if defined?(ActionController) && ActionController::Reloader.default_lock
- ActionController::Reloader.default_lock.unlock
+When /^I configure the copycopter client to used published data$/ do
+ in_current_dir do
+ config_path = "config/initializers/copycopter.rb"
+ contents = IO.read(config_path)
+ contents.sub!("end", " config.development_environments = []\nend")
+ File.open(config_path, "w") { |file| file.write(contents) }
end
end
+After do
+ RailsServer.stop
+end
View
42 features/support/rails_server.rb
@@ -0,0 +1,42 @@
+class RailsServer
+ class << self
+ attr_accessor :instance
+ end
+
+ def self.start(port = nil)
+ self.instance = new(port)
+ end
+
+ def self.stop
+ self.instance.stop if instance
+ self.instance = nil
+ end
+
+ def self.get(path)
+ self.instance.get(path)
+ end
+
+ def initialize(port)
+ @port = (port || 3001).to_i
+ @output = StringIO.new("")
+ @pid = fork do
+ $stdout = self.output
+ $stderr = self.output
+ require 'config/environment'
+ app = ActionController::Dispatcher.new
+ Rack::Handler::Thin.run(app, :Port => @port, :AccessLog => [])
+ end
+ sleep(5) # wait for app server to start
+ end
+
+ attr_accessor :output
+
+ def stop
+ Process.kill('INT', @pid)
+ Process.wait(@pid)
+ end
+
+ def get(path)
+ Net::HTTP.get(URI.parse("http://localhost:#{@port}").merge(path))
+ end
+end
View
16 lib/copycopter_client/client.rb
@@ -2,14 +2,14 @@ module CopycopterClient
# Communicates with the Copycopter server
class Client
def initialize(options)
- [:protocol, :api_key, :host, :port].each do |option|
+ [:protocol, :api_key, :host, :port, :public].each do |option|
instance_variable_set("@#{option}", options[option])
end
end
def download
connect do |http|
- response = http.request_get(uri("published_blurbs"))
+ response = http.request_get(uri(download_resource))
JSON.parse(response.body)
end
end
@@ -24,10 +24,22 @@ def upload(data)
attr_reader :protocol, :host, :port, :api_key
+ def public?
+ @public
+ end
+
def uri(resource)
"/api/v2/projects/#{api_key}/#{resource}"
end
+ def download_resource
+ if public?
+ "published_blurbs"
+ else
+ "draft_blurbs"
+ end
+ end
+
def connect
result = nil
Net::HTTP.start(host, port) do |http|
View
3 lib/copycopter_client/configuration.rb
@@ -96,7 +96,8 @@ def [](option)
# Returns a hash of all configurable options
def to_hash
- OPTIONS.inject({}) do |hash, option|
+ base_options = { :public => public? }
+ OPTIONS.inject(base_options) do |hash, option|
hash.merge(option.to_sym => send(option))
end
end
View
37 spec/copycopter_client/client_spec.rb
@@ -20,10 +20,16 @@ def add_project
it "downloads published blurbs for an existing project" do
project = add_project
- project.draft['key.one'] = "unexpected one"
- project.draft['key.three'] = "unexpected three"
- project.published['key.one'] = "expected one"
- project.published['key.two'] = "expected two"
+ project.update({
+ 'draft' => {
+ 'key.one' => "unexpected one",
+ 'key.three' => "unexpected three"
+ },
+ 'published' => {
+ 'key.one' => "expected one",
+ 'key.two' => "expected two"
+ }
+ })
blurbs = build_client(:api_key => project.api_key, :public => true).download
@@ -33,6 +39,27 @@ def add_project
}
end
+ it "downloads draft blurbs for an existing project" do
+ project = add_project
+ project.update({
+ 'draft' => {
+ 'key.one' => "expected one",
+ 'key.two' => "expected two"
+ },
+ 'published' => {
+ 'key.one' => "unexpected one",
+ 'key.three' => "unexpected three"
+ }
+ })
+
+ blurbs = build_client(:api_key => project.api_key, :public => false).download
+
+ blurbs.should == {
+ 'key.one' => 'expected one',
+ 'key.two' => 'expected two'
+ }
+ end
+
it "uploads defaults for missing blurbs in an existing project" do
project = add_project
@@ -44,7 +71,7 @@ def add_project
client = build_client(:api_key => project.api_key, :public => true)
client.upload(blurbs)
- project.draft.should == blurbs
+ project.reload.draft.should == blurbs
end
end
View
1 spec/copycopter_client/configuration_spec.rb
@@ -75,6 +75,7 @@
:proxy_user, :secure, :development_environments].each do |option|
hash[option].should == config[option]
end
+ hash[:public].should == config.public?
end
it "should be mergable" do
View
90 spec/support/fake_copycopter_app.rb
@@ -1,44 +1,39 @@
require 'sinatra/base'
+require 'json'
class FakeCopycopterApp < Sinatra::Base
- class << self
- attr_accessor :projects
- end
-
- self.projects = {}
-
def self.add_project(api_key)
- self.projects[api_key] = Project.new(api_key)
+ Project.create(api_key)
end
def self.reset
- self.projects.clear
+ Project.delete_all
end
- def projects
- self.class.projects
+ def self.project(api_key)
+ Project.find(api_key)
end
get "/api/v2/projects/:api_key/published_blurbs" do |api_key|
- if projects[api_key]
- projects[api_key].published.to_json
+ if project = Project.find(api_key)
+ project.published.to_json
else
halt 404, "No such project"
end
end
get "/api/v2/projects/:api_key/draft_blurbs" do |api_key|
- if projects[api_key]
- projects[api_key].draft.to_json
+ if project = Project.find(api_key)
+ project.draft.to_json
else
halt 404, "No such project"
end
end
post "/api/v2/projects/:api_key/draft_blurbs" do |api_key|
- if projects[api_key]
+ if project = Project.find(api_key)
data = JSON.parse(request.body.read)
- projects[api_key].draft.update(data)
+ project.update('draft' => data)
201
else
halt 404, "No such project"
@@ -52,10 +47,65 @@ def projects
class Project
attr_reader :draft, :published, :api_key
- def initialize(api_key)
- @api_key = api_key
- @draft = {}
- @published = {}
+ def initialize(attrs)
+ @api_key = attrs['api_key']
+ @draft = attrs['draft'] || {}
+ @published = attrs['published'] || {}
+ end
+
+ def to_hash
+ { 'api_key' => @api_key,
+ 'draft' => @draft,
+ 'published' => @published }
+ end
+
+ def update(attrs)
+ @draft. update(attrs['draft']) if attrs['draft']
+ @published.update(attrs['published']) if attrs['published']
+ self.class.save(self)
+ end
+
+ def reload
+ self.class.find(api_key)
+ end
+
+ def self.create(api_key)
+ project = Project.new('api_key' => api_key)
+ save(project)
+ project
+ end
+
+ def self.find(api_key)
+ open_project_data do |data|
+ Project.new(data[api_key].dup)
+ end
+ end
+
+ def self.delete_all
+ open_project_data do |data|
+ data.clear
+ end
+ end
+
+ def self.save(project)
+ open_project_data do |data|
+ data[project.api_key] = project.to_hash
+ end
+ end
+
+ def self.open_project_data
+ project_file = File.join(PROJECT_ROOT, 'tmp', 'projects.json')
+ if File.exist?(project_file)
+ data = JSON.parse(IO.read(project_file))
+ else
+ data = {}
+ end
+
+ result = yield(data)
+
+ File.open(project_file, "w") { |file| file.write(data.to_json) }
+
+ result
end
end
end
View
1 tmp/projects.json
@@ -0,0 +1 @@
+{}

0 comments on commit ecc7f65

Please sign in to comment.