Skip to content

Commit

Permalink
Add path for downloading translations with a hierarchy instead of a flat
Browse files Browse the repository at this point in the history
namespace.
  • Loading branch information
cmavromoustakos committed Mar 15, 2012
1 parent 1d54e13 commit d27d69f
Show file tree
Hide file tree
Showing 13 changed files with 241 additions and 49 deletions.
2 changes: 1 addition & 1 deletion .rvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
rvm 1.9.2
rvm use 1.9.2-p180
3 changes: 2 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ end
group :test do
gem 'bourne', '1.1.1'
gem 'capybara-webkit', '0.3.0'
gem 'cucumber-rails', '0.4.1'
gem 'cucumber-rails'
gem 'database_cleaner', '0.7.1'
gem 'factory_girl_rails', '1.7.0'
gem 'fakeweb', '1.3.0'
gem 'ruby-debug19', '~> 0.11.6'
gem 'shoulda-matchers', '1.0.0'
gem 'timecop', '0.3.5'
end
19 changes: 17 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ GEM
activesupport (3.1.1)
multi_json (~> 1.0)
addressable (2.2.7)
archive-tar-minitar (0.5.2)
arel (2.2.3)
bourbon (1.4.0)
sass (>= 3.1)
Expand All @@ -50,6 +51,7 @@ GEM
celerity (0.9.2)
childprocess (0.3.1)
ffi (~> 1.0.6)
columnize (0.3.6)
cucumber (1.1.9)
builder (>= 2.1.2)
diff-lcs (>= 1.1.2)
Expand All @@ -61,7 +63,7 @@ GEM
nokogiri (>= 1.4.4)
rack-test (>= 0.5.7)
culerity (0.2.15)
daemons (1.1.4)
daemons (1.1.8)
database_cleaner (0.7.1)
diff-lcs (1.1.3)
dynamic_form (1.1.4)
Expand Down Expand Up @@ -91,6 +93,8 @@ GEM
json (1.6.5)
launchy (2.0.5)
addressable (~> 2.2.6)
linecache19 (0.5.12)
ruby_core_source (>= 0.1.4)
mail (2.3.3)
i18n (>= 0.4.0)
mime-types (~> 1.16)
Expand Down Expand Up @@ -143,6 +147,16 @@ GEM
activesupport (>= 3.0)
railties (>= 3.0)
rspec (~> 2.8.0)
ruby-debug-base19 (0.11.25)
columnize (>= 0.3.1)
linecache19 (>= 0.5.11)
ruby_core_source (>= 0.1.4)
ruby-debug19 (0.11.6)
columnize (>= 0.3.1)
linecache19 (>= 0.5.11)
ruby-debug-base19 (>= 0.11.19)
ruby_core_source (0.1.5)
archive-tar-minitar (>= 0.5.2)
rubyzip (0.9.6.1)
sass (3.1.15)
selenium-webdriver (2.20.0)
Expand Down Expand Up @@ -179,7 +193,7 @@ DEPENDENCIES
bourbon (= 1.4.0)
bourne (= 1.1.1)
capybara-webkit (= 0.3.0)
cucumber-rails (= 0.4.1)
cucumber-rails
database_cleaner (= 0.7.1)
dynamic_form (= 1.1.4)
factory_girl_rails (= 1.7.0)
Expand All @@ -193,6 +207,7 @@ DEPENDENCIES
pg (= 0.13.2)
rails (= 3.1.1)
rspec-rails (= 2.8.1)
ruby-debug19 (~> 0.11.6)
shoulda-matchers (= 1.0.0)
spork (= 0.9.0)
thin (= 1.3.1)
Expand Down
6 changes: 5 additions & 1 deletion app/controllers/api/v2/draft_blurbs_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
class Api::V2::DraftBlurbsController < Api::V2::BaseController
def index
if stale? :etag => current_project.etag
render :json => current_project.draft_json
if params[:hierarchy]
render :json => current_project.draft_json(:hierarchy => true)
else
render :json => current_project.draft_json
end
end
end

Expand Down
6 changes: 5 additions & 1 deletion app/controllers/api/v2/published_blurbs_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
class Api::V2::PublishedBlurbsController < Api::V2::BaseController
def index
if stale? :etag => current_project.etag
render :json => current_project.published_json
if params[:hierarchy]
render :json => current_project.published_json(:hierarchy => true)
else
render :json => current_project.published_json
end
end
end
end
30 changes: 29 additions & 1 deletion app/models/blurb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,45 @@ def self.ordered
def self.to_hash(attribute)
scope = joins(:localizations => :locale).
select("blurbs.key AS blurb_key, locales.key AS locale_key, #{attribute} AS content")
connection.select_rows(scope.to_sql).inject({}) do |result, (blurb_key, locale_key, content)|
blurbs = connection.select_rows(scope.to_sql)

data = blurbs.inject({}) do |result, (blurb_key, locale_key, content)|
key = [locale_key, blurb_key].join(".")
result.update key => content
end

hierarchichal_data = blurbs.inject({}) do |result, (blurb_key, locale_key, content)|
keys = blurb_key.split('.')
result.deep_merge!({ locale_key => create_hierarchichal_hash_from_array(keys + [content]) })
end

{ :data => data, :hierarchichal_data => hierarchichal_data }
end

def self.keys
select('key').map { |blurb| blurb.key }
end

private
def self.create_hierarchichal_hash_from_array(array_hierarchy, hash_hierarchy = {})
return hash_hierarchy if array_hierarchy.empty?

# The last 2 values in the array are the most drilled down part, so given:
# [d,c,b,a,1]
# The first Iteration you would get:
# { "a" => 1 }
# Second iteration:
# { "b" => { "a" => 1 } }, etc..
#
if hash_hierarchy.empty?
value = array_hierarchy.pop
hash_hierarchy.merge!(array_hierarchy.pop => value)
else
hash_hierarchy = { array_hierarchy.pop => hash_hierarchy }
end

return create_hierarchichal_hash_from_array(array_hierarchy, hash_hierarchy)
end

def update_project_caches
project.update_caches
Expand Down
25 changes: 18 additions & 7 deletions app/models/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,12 @@ def deploy!
update_caches
end

def draft_json
draft_cache.data
def draft_json(options = { :hierarchy => false })
if options[:hierarchy]
draft_cache.hierarchichal_data
else
draft_cache.data
end
end

def etag
Expand All @@ -71,8 +75,12 @@ def lock_key_for_creating_defaults
"project-#{id}-create-defaults"
end

def published_json
published_cache.data
def published_json(options = { :hierarchy => false })
if options[:hierarchy]
published_cache.hierarchichal_data
else
published_cache.data
end
end

def self.regenerate_caches
Expand All @@ -82,8 +90,8 @@ def self.regenerate_caches
end

def update_caches
draft_cache.update_attributes! :data => generate_json(:draft_content)
published_cache.update_attributes! :data => generate_json(:published_content)
draft_cache.update_attributes!(generate_json(:draft_content))
published_cache.update_attributes!(generate_json(:published_content))
touch
end

Expand Down Expand Up @@ -111,6 +119,9 @@ def generate_api_key
end

def generate_json(content)
Yajl::Encoder.encode blurbs.to_hash(content)
blurbs_hash = blurbs.to_hash(content)
blurbs_hash[:data] = Yajl::Encoder.encode blurbs_hash[:data]
blurbs_hash[:hierarchichal_data] = Yajl::Encoder.encode blurbs_hash[:hierarchichal_data]
blurbs_hash
end
end
11 changes: 11 additions & 0 deletions db/migrate/20120315145922_add_hierarchy_text_to_text_cache.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class AddHierarchyTextToTextCache < ActiveRecord::Migration
def up
change_table :text_caches do |t|
t.text :hierarchichal_data
end
end

def down
remove_column :text_cahces, :hierarchichal_data
end
end
38 changes: 38 additions & 0 deletions features/api_v2_download.feature
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,41 @@ Feature: Download blurbs for a project through API
Then I should receive the following as a JSON object:
| en.test.one | update |

Scenario: download published blurbs with a json hieratchy for a known project
Given a project exists with a name of "Breakfast"
When I POST the v2 API URI for "Breakfast" draft blurbs:
| en.test.one | expected one |
| en.test.two | expected two |
And I POST the v2 API URI for "Breakfast" deploys
When I GET the v2 API URI for "Breakfast" published blurbs with a hierarchy param
Then I should receive a HTTP 200
And I should receive the following JSON response:
"""
{
"en": {
"test": {
"one": "expected one",
"two": "expected two"
}
}
}
"""

Scenario: download draft blurbs with a json hierarchy for a known project
Given a project exists with a name of "Breakfast"
When I POST the v2 API URI for "Breakfast" draft blurbs:
| en.test.one | expected one |
| en.test.two | expected two |
And I GET the v2 API URI for "Breakfast" draft blurbs with a hierarchy param
Then I should receive a HTTP 200
And I should receive the following JSON response:
"""
{
"en": {
"test": {
"one": "expected one",
"two": "expected two"
}
}
}
"""
21 changes: 17 additions & 4 deletions features/step_definitions/api_v2_steps.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
When /^I GET the v2 API URI for "([^"]*)" draft blurbs$/ do |project_name|
When /^I GET the v2 API URI for "([^"]*)" draft blurbs( with a hierarchy param)?$/ do |project_name, hierarchy|
project = Project.find_by_name!(project_name)
get_with_etag "/api/v2/projects/#{project.api_key}/draft_blurbs"
if hierarchy
get_with_etag "/api/v2/projects/#{project.api_key}/draft_blurbs?hierarchy=true"
else
get_with_etag "/api/v2/projects/#{project.api_key}/draft_blurbs"
end
end

When /^I GET the v2 API URI for "([^"]*)" published blurbs$/ do |project_name|
When /^I GET the v2 API URI for "([^"]*)" published blurbs( with a hierarchy param)?$/ do |project_name, hierarchy|
project = Project.find_by_name!(project_name)
get_with_etag "/api/v2/projects/#{project.api_key}/published_blurbs"
if hierarchy
get_with_etag "/api/v2/projects/#{project.api_key}/published_blurbs?hierarchy=true"
else
get_with_etag "/api/v2/projects/#{project.api_key}/published_blurbs"
end
end

When /^I GET the v2 API URI for "([^"]*)" published blurbs twice$/ do |project_name|
Expand Down Expand Up @@ -46,3 +54,8 @@
actual_result = Yajl::Parser.parse(page.source)
actual_result.should == expected_hash
end

Then /^I should receive the following JSON response:$/ do |string|
actual_result = JSON.parse(page.source)
actual_result.should == JSON.parse(string)
end
65 changes: 53 additions & 12 deletions spec/models/blurb_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,66 @@
one = Factory(:blurb, :key => 'test.one', :project => project)
two = Factory(:blurb, :key => 'test.two', :project => project)

Factory :localization, :blurb => one, :locale => en,
:draft_content => 'draft one', :published_content => 'published one'
Factory :localization, :blurb => two, :locale => en,
:draft_content => 'draft two', :published_content => 'published two'
Factory :localization, :blurb => two, :locale => fr,
:draft_content => 'ébauche', :published_content => 'publié'
Factory :localization, :blurb => one,
:locale => en,
:draft_content => 'draft one',
:published_content => 'published one'
Factory :localization, :blurb => two,
:locale => en,
:draft_content => 'draft two',
:published_content => 'published two'
Factory :localization, :blurb => two,
:locale => fr,
:draft_content => 'ébauche',
:published_content => 'publié'
end

it 'returns draft hash' do
Blurb.to_hash(:draft_content).should == {
'en.test.one' => 'draft one', 'en.test.two' => 'draft two',
Blurb.to_hash(:draft_content).should include(:data => {
'en.test.one' => 'draft one',
'en.test.two' => 'draft two',
'fr.test.two' => 'ébauche'
}
})
end

it 'returns published hash' do
Blurb.to_hash(:published_content).should == {
'en.test.one' => 'published one', 'en.test.two' => 'published two',
Blurb.to_hash(:published_content).should include(:data => {
'en.test.one' => 'published one',
'en.test.two' => 'published two',
'fr.test.two' => 'publié'
}
})
end

it 'returns a draft hash maintaining hierarchy' do
Blurb.to_hash(:draft_content).should include(:hierarchichal_data => {
'en' => {
'test' => {
'one' => 'draft one',
'two' => 'draft two'
}
},
'fr' => {
'test' => {
'two' => 'ébauche'
}
}
})
end

it 'returns a published hash maintaining hierarchy' do
Blurb.to_hash(:published_content).should include(:hierarchichal_data => {
'en' => {
'test' => {
'one' => 'published one',
'two' => 'published two'
}
},
'fr' => {
'test' => {
'two' => 'publié'
}
}
})

end
end
Loading

0 comments on commit d27d69f

Please sign in to comment.