vodka 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/.travis.yml +2 -0
  2. data/README.md +33 -10
  3. data/lib/party.rb +2 -1
  4. data/lib/vodka/client.rb +0 -2
  5. data/lib/vodka/client/middleware/signed_request.rb +1 -1
  6. data/lib/vodka/client/middleware/signed_response.rb +1 -1
  7. data/lib/vodka/configuration.rb +27 -12
  8. data/lib/vodka/server.rb +3 -0
  9. data/lib/vodka/server/controllers/vodka_controller.rb +1 -5
  10. data/lib/vodka/server/handlers/resource.rb +6 -2
  11. data/lib/vodka/server/handlers/response.rb +10 -6
  12. data/lib/vodka/server/handlers/scaffold.rb +5 -35
  13. data/lib/vodka/server/middleware/signed_request.rb +6 -4
  14. data/lib/vodka/server/plugins/presentable.rb +24 -9
  15. data/lib/vodka/server/presenters/vodka_presenter.rb +23 -0
  16. data/lib/vodka/server/railtie.rb +13 -0
  17. data/lib/vodka/server/relation.rb +95 -0
  18. data/lib/vodka/server/response.rb +18 -7
  19. data/lib/vodka/version.rb +1 -1
  20. data/script/dummy_console +6 -0
  21. data/script/setup_db +2 -2
  22. data/script/show_logs +1 -1
  23. data/script/spec +5 -9
  24. data/script/start_server +2 -2
  25. data/script/stop_server +1 -1
  26. data/spec/client/article.rb +2 -0
  27. data/spec/client/author.rb +3 -0
  28. data/spec/client/comment.rb +4 -0
  29. data/spec/dummy/Gemfile +6 -5
  30. data/spec/dummy/Gemfile.lock +19 -4
  31. data/spec/dummy/app/controllers/articles_controller.rb +5 -0
  32. data/spec/dummy/app/controllers/vodka/authors_controller.rb +4 -0
  33. data/spec/dummy/app/controllers/vodka/comments_controller.rb +4 -0
  34. data/spec/dummy/app/models/article.rb +9 -2
  35. data/spec/dummy/app/models/author.rb +5 -0
  36. data/spec/dummy/app/models/comment.rb +12 -0
  37. data/spec/dummy/app/models/like.rb +9 -0
  38. data/spec/dummy/app/presenters/article_presenter.rb +9 -0
  39. data/spec/dummy/app/presenters/author_custom_presenter.rb +5 -0
  40. data/spec/dummy/app/presenters/comment_presenter.rb +13 -0
  41. data/spec/dummy/config/database.yml +3 -3
  42. data/spec/dummy/config/initializers/mongo_mapper_connection.rb +4 -0
  43. data/spec/dummy/config/initializers/vodka_setup.rb +1 -0
  44. data/spec/dummy/config/mongoid.yml +32 -0
  45. data/spec/dummy/config/routes.rb +4 -0
  46. data/spec/dummy/config/thin.yml +1 -1
  47. data/spec/dummy/db/migrate/20130217185353_create_articles.rb +1 -0
  48. data/spec/dummy/db/schema.rb +1 -0
  49. data/spec/dummy/db/seeds.rb +18 -1
  50. data/spec/her/extensions/paginated/paginate_spec.rb +32 -0
  51. data/spec/middleware/response_locale_spec.rb +2 -0
  52. data/spec/requests/relations_spec.rb +9 -0
  53. data/spec/spec_helper.rb +2 -1
  54. data/vodka.gemspec +1 -1
  55. metadata +23 -8
  56. data/lib/vodka/her/extensions/extended_orm.rb +0 -92
  57. data/lib/vodka/her/extensions/will_paginate.rb +0 -32
  58. data/spec/her/extensions/will_paginate/paginate_spec.rb +0 -16
@@ -6,6 +6,19 @@ module Vodka
6
6
  initializer 'vodka.inject_middleware' do |app|
7
7
  app.config.middleware.use 'Vodka::Server::Middleware::SignedRequest'
8
8
  end
9
+
10
+ initializer 'vodka.inject_presenter' do |app|
11
+ if defined?(ActiveRecord)
12
+ ActiveRecord::Base.send(:include, Vodka::Server::Plugins::Presentable)
13
+ end
14
+ if defined?(MongoMapper)
15
+ MongoMapper::Document.send(:include, Vodka::Server::Plugins::Presentable)
16
+ MongoMapper::EmbeddedDocument.send(:include, Vodka::Server::Plugins::Presentable)
17
+ end
18
+ if defined?(Mongoid)
19
+ Mongoid::Document.send(:include, Vodka::Server::Plugins::Presentable)
20
+ end
21
+ end
9
22
  end
10
23
  end
11
24
  end
@@ -0,0 +1,95 @@
1
+ module Vodka
2
+ module Server
3
+ class Relation
4
+ attr_accessor :klass, :relation, :params, :data, :metadata
5
+
6
+ def initialize(klass, params)
7
+ @klass = klass
8
+ @relation = klass
9
+ @params = params
10
+ @data = []
11
+ @metadata = {}
12
+
13
+ convert!
14
+ end
15
+
16
+ private
17
+
18
+ def convert!
19
+ apply_where_conditions!
20
+ apply_group_conditions!
21
+ apply_having_conditions!
22
+ apply_order_conditions!
23
+ apply_limit_condition!
24
+ apply_offset_condition!
25
+ apply_pagination!
26
+
27
+ if params.has_key?(:her_special_count)
28
+ @data = [relation.count]
29
+ elsif relation == klass
30
+ @data = relation.all
31
+ elsif relation.respond_to?(:to_a)
32
+ @data = relation.to_a
33
+ end
34
+ end
35
+
36
+ def apply!(method, *args)
37
+ @relation = @relation.send(method, *args) if @relation.respond_to?(method)
38
+ end
39
+
40
+ def apply_where_conditions!
41
+ return unless params.has_key?(:her_special_where)
42
+
43
+ MultiJson.load(params[:her_special_where]).each do |condition|
44
+ condition.is_a?(Hash) ? apply!(:where, condition) : apply!(:where, *condition)
45
+ end
46
+ end
47
+
48
+ def apply_group_conditions!
49
+ return unless params.has_key?(:her_special_group)
50
+
51
+ MultiJson.load(params[:her_special_group]).each do |condition|
52
+ if relation.respond_to?(:group)
53
+ apply!(:group, condition)
54
+ elsif relation.respond_to?(:group_by)
55
+ apply!(:group_by, condition)
56
+ end
57
+ end
58
+ end
59
+
60
+ def apply_having_conditions!
61
+ return unless params.has_key?(:her_special_having)
62
+
63
+ MultiJson.load(params[:her_special_having]).each do |condition|
64
+ apply!(:having, condition)
65
+ end
66
+ end
67
+
68
+ def apply_order_conditions!
69
+ return unless params.has_key?(:her_special_order)
70
+
71
+ MultiJson.load(params[:her_special_order]).each do |condition|
72
+ apply!(:order, condition)
73
+ end
74
+ end
75
+
76
+ def apply_limit_condition!
77
+ apply!(:limit, params[:her_special_limit].to_i) if params.has_key?(:her_special_limit)
78
+ end
79
+
80
+ def apply_offset_condition!
81
+ apply!(:offset, params[:her_special_offset].to_i) if params.has_key?(:her_special_offset)
82
+ end
83
+
84
+ def apply_pagination!
85
+ return unless params.has_key?(:her_special_paginate)
86
+
87
+ per_page = params[:her_special_limit].to_i
88
+ current_page = params[:her_special_offset].to_i / per_page + 1
89
+ total_entries = relation.count
90
+
91
+ @metadata = { current_page: current_page, per_page: per_page, total_entries: total_entries }
92
+ end
93
+ end
94
+ end
95
+ end
@@ -1,7 +1,7 @@
1
1
  module Vodka
2
2
  module Server
3
3
  class Response
4
- attr_accessor :id, :code, :success, :data, :metadata, :errors
4
+ attr_accessor :id, :code, :success, :data, :presenter, :metadata, :errors
5
5
 
6
6
  def initialize
7
7
  @code = 200
@@ -13,25 +13,36 @@ module Vodka
13
13
  metadata[:vodka_action_success] = success unless success.nil?
14
14
 
15
15
  if data.nil?
16
- presented_data = nil
16
+ presented_data = {}
17
17
  errors_to_return = errors
18
18
  elsif data.is_a?(Array)
19
- presented_data = data.map(&:present_vodka)
19
+ presented_data = data.map{ |item| present(item) }
20
20
  errors_to_return = errors
21
21
  else
22
- presented_data = data.present_vodka
22
+ presented_data = present(data)
23
23
  errors_to_return = presented_data.delete(:errors)
24
24
  end
25
25
 
26
- MultiJson.dump(
26
+ response = {
27
27
  data: presented_data,
28
28
  metadata: metadata,
29
29
  errors: errors_to_return
30
- )
30
+ }
31
+ # ap response if Rails.env.development? && defined?(AwesomePrint)
32
+ MultiJson.dump(response)
33
+ end
34
+
35
+ def present(item)
36
+ return item if item.is_a?(Hash)
37
+ if presenter.nil?
38
+ item.try(:present)
39
+ else
40
+ presenter.new(item).present
41
+ end
31
42
  end
32
43
 
33
44
  def signature
34
- Digest::SHA512.hexdigest([id, Vodka::Server.config.response_secret].join)
45
+ Vodka::Server.config.digest.hexdigest([id, Vodka::Server.config.response_secret].join)
35
46
  end
36
47
  end
37
48
  end
@@ -1,3 +1,3 @@
1
1
  module Vodka
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.2'
3
3
  end
@@ -0,0 +1,6 @@
1
+ #!/bin/bash
2
+ dummy_path="$(pwd)/spec/dummy"
3
+ BUNDLE_PATH=$dummy_path/.bundle
4
+ BUNDLE_GEMFILE=$dummy_path/Gemfile
5
+ RAILS_ENV=development
6
+ cd $dummy_path && bundle exec rails console
@@ -2,6 +2,6 @@
2
2
  dummy_path="$(pwd)/spec/dummy"
3
3
  BUNDLE_PATH=$dummy_path/.bundle
4
4
  BUNDLE_GEMFILE=$dummy_path/Gemfile
5
- RAILS_ENV=test
5
+ RAILS_ENV=development
6
6
  cd $dummy_path && bundle exec rake db:migrate 2>&1 > $dummy_path/log/setup_db.log
7
- cd $dummy_path && bundle exec rake db:test:prepare 2>&1 > $dummy_path/log/setup_db.log
7
+ cd $dummy_path && bundle exec rake db:seed 2>&1 >> $dummy_path/log/setup_db.log
@@ -18,5 +18,5 @@ cat $dummy_path/log/thin.3000.log
18
18
  echo ''
19
19
 
20
20
  echo 'Dummy log:'
21
- cat $dummy_path/log/test.log
21
+ cat $dummy_path/log/development.log
22
22
  echo ''
@@ -1,14 +1,10 @@
1
1
  #!/bin/bash
2
2
 
3
- cd spec/dummy
4
- rm -f log/*
5
- bundle install --path .bundle 2>&1 > log/bundler.log
6
- RAILS_ENV=test bundle exec rake db:reset 2>&1 > log/setup_db.log
7
- RAILS_ENV=test bundle exec thin start -C config/thin.yml 2>&1 > log/thin_start.log
8
- cd ../..
3
+ rm -f spec/dummy/log/*
4
+ ./script/bundle_dummy
5
+ ./script/setup_db
6
+ ./script/start_server
9
7
  bundle exec rspec
10
8
  code=$?
11
- cd spec/dummy
12
- RAILS_ENV=test bundle exec thin stop -C config/thin.yml 2>&1 > log/thin_stop.log
13
- cd ../..
9
+ ./script/stop_server
14
10
  exit $code
@@ -2,5 +2,5 @@
2
2
  dummy_path="$(pwd)/spec/dummy"
3
3
  BUNDLE_PATH=$dummy_path/.bundle
4
4
  BUNDLE_GEMFILE=$dummy_path/Gemfile
5
- RAILS_ENV=test
6
- cd $dummy_path && bundle exec thin start -C $dummy_path/config/thin.yml 2>&1 > $dummy_path/log/thin_start.log
5
+ RAILS_ENV=development
6
+ cd $dummy_path && bundle exec thin start -C $dummy_path/config/thin.yml # 2>&1 > $dummy_path/log/thin_start.log
@@ -2,5 +2,5 @@
2
2
  dummy_path="$(pwd)/spec/dummy"
3
3
  BUNDLE_PATH=$dummy_path/.bundle
4
4
  BUNDLE_GEMFILE=$dummy_path/Gemfile
5
- RAILS_ENV=test
5
+ RAILS_ENV=development
6
6
  cd $dummy_path && bundle exec thin stop -C $dummy_path/config/thin.yml 2>&1 > /dev/null
@@ -1,4 +1,6 @@
1
1
  class Article
2
2
  include Her::Model
3
3
  custom_get :hello
4
+ has_many :comments
5
+ belongs_to :author
4
6
  end
@@ -0,0 +1,3 @@
1
+ class Author
2
+ include Her::Model
3
+ end
@@ -0,0 +1,4 @@
1
+ class Comment
2
+ include Her::Model
3
+ belongs_to :author
4
+ end
@@ -1,9 +1,10 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'rails', '~> 3.2.12'
4
- gem 'will_paginate', '~> 3.0.4'
5
- gem 'sqlite3', '~> 1.3.7'
6
- gem 'thin', '~> 1.5.0'
7
- gem 'multi_json', '~> 1.6.1'
3
+ gem 'rails', '~> 3.2.12'
4
+ gem 'thin', '~> 1.5.0'
5
+
6
+ gem 'sqlite3', '~> 1.3.7'
7
+ gem 'mongo_mapper', '~> 0.12.0'
8
+ gem 'mongoid', '~> 3.1.2'
8
9
 
9
10
  gem 'vodka', path: '../..', require: 'vodka/server'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- vodka (0.0.1)
4
+ vodka (0.1.0)
5
5
  her (~> 0.4)
6
6
  multi_json (~> 1.6.1)
7
7
 
@@ -36,6 +36,7 @@ GEM
36
36
  i18n (~> 0.6)
37
37
  multi_json (~> 1.0)
38
38
  arel (3.0.2)
39
+ bson (1.8.2)
39
40
  builder (3.0.4)
40
41
  daemons (1.1.9)
41
42
  erubis (2.7.0)
@@ -55,8 +56,23 @@ GEM
55
56
  mime-types (~> 1.16)
56
57
  treetop (~> 1.4.8)
57
58
  mime-types (1.21)
59
+ mongo (1.8.2)
60
+ bson (~> 1.8.2)
61
+ mongo_mapper (0.12.0)
62
+ activemodel (~> 3.0)
63
+ activesupport (~> 3.0)
64
+ plucky (~> 0.5.2)
65
+ mongoid (3.1.2)
66
+ activemodel (~> 3.2)
67
+ moped (~> 1.4.2)
68
+ origin (~> 1.0)
69
+ tzinfo (~> 0.3.22)
70
+ moped (1.4.2)
58
71
  multi_json (1.6.1)
59
72
  multipart-post (1.1.5)
73
+ origin (1.0.11)
74
+ plucky (0.5.2)
75
+ mongo (~> 1.5)
60
76
  polyglot (0.3.3)
61
77
  rack (1.4.5)
62
78
  rack-cache (1.2)
@@ -99,15 +115,14 @@ GEM
99
115
  polyglot
100
116
  polyglot (>= 0.3.1)
101
117
  tzinfo (0.3.35)
102
- will_paginate (3.0.4)
103
118
 
104
119
  PLATFORMS
105
120
  ruby
106
121
 
107
122
  DEPENDENCIES
108
- multi_json (~> 1.6.1)
123
+ mongo_mapper (~> 0.12.0)
124
+ mongoid (~> 3.1.2)
109
125
  rails (~> 3.2.12)
110
126
  sqlite3 (~> 1.3.7)
111
127
  thin (~> 1.5.0)
112
128
  vodka!
113
- will_paginate (~> 3.0.4)
@@ -0,0 +1,5 @@
1
+ class ArticlesController < ApplicationController
2
+ def index
3
+ render json: Article.all
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module Vodka
2
+ class AuthorsController < VodkaController
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Vodka
2
+ class CommentsController < VodkaController
3
+ end
4
+ end
@@ -1,10 +1,17 @@
1
1
  class Article < ActiveRecord::Base
2
- present_with :id, :title
3
- attr_accessible :title
2
+ attr_accessible :title, :author_id
4
3
  validates_presence_of :title
5
4
  before_destroy :ensure_article_in_not_special
6
5
 
7
6
  def ensure_article_in_not_special
8
7
  return false if title == 'special'
9
8
  end
9
+
10
+ def author
11
+ Author.find(author_id) if author_id?
12
+ end
13
+
14
+ def comments
15
+ Comment.where(article_id: id)
16
+ end
10
17
  end
@@ -0,0 +1,5 @@
1
+ class Author
2
+ include Mongoid::Document
3
+ field :name, type: String
4
+ present_with AuthorCustomPresenter
5
+ end
@@ -0,0 +1,12 @@
1
+ class Comment
2
+ include MongoMapper::Document
3
+ key :article_id, Integer
4
+ key :body, String
5
+ key :author_id, String
6
+
7
+ many :likes
8
+
9
+ def author
10
+ Author.find(author_id)
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ class Like
2
+ include MongoMapper::EmbeddedDocument
3
+ key :author_id, String
4
+ embedded_in :comment
5
+
6
+ def author
7
+ Author.find(author_id)
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class ArticlePresenter < VodkaPresenter
2
+ def present
3
+ json(
4
+ id: resource.id,
5
+ title: resource.title,
6
+ author: resource.author.try(:present)
7
+ )
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class AuthorCustomPresenter < VodkaPresenter
2
+ def present
3
+ json(id: resource.id, name: resource.name)
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ class CommentPresenter < VodkaPresenter
2
+ def present
3
+ json(
4
+ body: resource.body,
5
+ author: resource.author.try(:present),
6
+ likes: likes
7
+ )
8
+ end
9
+
10
+ def likes
11
+ resource.likes.map{ |like| like.author.try(:present) }
12
+ end
13
+ end
@@ -1,17 +1,17 @@
1
1
  development:
2
2
  adapter: sqlite3
3
- database: db/test.sqlite3
3
+ database: db/development.sqlite3
4
4
  pool: 5
5
5
  timeout: 5000
6
6
 
7
7
  test:
8
8
  adapter: sqlite3
9
- database: db/test.sqlite3
9
+ database: db/development.sqlite3
10
10
  pool: 5
11
11
  timeout: 5000
12
12
 
13
13
  production:
14
14
  adapter: sqlite3
15
- database: db/test.sqlite3
15
+ database: db/development.sqlite3
16
16
  pool: 5
17
17
  timeout: 5000