grape-gen 0.0.5 → 0.0.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 28745d08b232ed5faeb876a406a2b3f587be9036
4
- data.tar.gz: 44c2dbad904233a90c7b58010d5629004e4c06a4
3
+ metadata.gz: 0e50733ed46b5a0d995856b26debf1b46f85f68f
4
+ data.tar.gz: 667b90bcfc49d876a21bc81c52b4314f4108b627
5
5
  SHA512:
6
- metadata.gz: 1c98b81b1848d883d932044fd6890675e8d12c8630a61003307e9ffb8f789c66e00618a3b97d68a622a9c6e3d746e009d0f080109b32ac320b192ac5f003f88d
7
- data.tar.gz: a96d538140c5d49aac1a0d27e51d5cfd2950757ef39e08e7fcd048643af2f4cd8a3c60e042100696d266a22df8690da7b16ffa521f0e83838f2cb31a6b3e81ba
6
+ metadata.gz: f3d87fc13fe0d3781c44143d1efb4fb95975182d5bcd2dc9e1cfb6a96cb2fe45bae7f545e9d1a8a314df6f2f76864370d6248d8f81af685f457298332e5fc5ff
7
+ data.tar.gz: ce52755d2c38f7303cec926b352464d2e3fdaa94d2776538e3d0503cdd412e6395ee1a394d2a1528926dd946f4af72022a88683963d1769c7637240414ddc910
data/README.md CHANGED
@@ -1,30 +1,76 @@
1
- # Grape::Scaffold
1
+ # Grape::Generate
2
+ Grape application template generator with batteries included
2
3
 
3
- TODO: Write a gem description
4
+ ## Getting started
4
5
 
5
- ## Installation
6
+ First, install gem into your system
6
7
 
7
- Add this line to your application's Gemfile:
8
+ $ gem install 'grape-gen'
9
+ then grape-gen binary will be available in your shell.
10
+ To generate default app skeleton, simply use:
8
11
 
9
- ```ruby
10
- gem 'grape-scaffold'
11
- ```
12
+ $ grape-gen app your_app_name
13
+ After executing complete, dir __your_app_name__ will be created in current dir.
14
+ Navigate into created dir and do ```$ bundle```
12
15
 
13
- And then execute:
16
+ ## Whats included?
17
+ * carrierwave
18
+ * sidekiq
19
+ * faye
20
+ * elastic search
21
+ * redis
14
22
 
15
- $ bundle
23
+ ## Grape API rack app
24
+ Rack app intended to be run under EventMachine-powered server (skeleton app using Thin)
25
+ Every library used is patched to play ball with EventMachine event loop.
26
+ To start web server:
16
27
 
17
- Or install it yourself as:
28
+ $ RACK_ENV=production thin start -p 9292
29
+ Example webserver responding to following API methods:
18
30
 
19
- $ gem install grape-scaffold
31
+ * POST /api/auth/register (display_name, email)
32
+ * POST /api/auth/approve_email (email, email_approvement_code)
33
+ * GET /api/profile
34
+ * PUT /api/profile (avatar, remove_avatar, display_name)
20
35
 
21
- ## Usage
36
+ /api/profile methods is restricted to use only by registered users.
37
+ API user must supply X-Authorize header, received from /api/auth/approve_email
22
38
 
23
- TODO: Write usage instructions here
39
+ When user approves email by calling POST /api/auth/approve_email with valid data,
40
+ message containing user __display_name__ will be published into faye __/user/registered__ channel
41
+ so all faye connections subscribed to /user/registered channel will receive info about newly registered user
42
+
43
+ ## Faye (optional, enabled by default)
44
+ Include faye support into skeleton app.
45
+ To start faye server:
46
+
47
+ $ thin start -p 9393 -R faye.ru -e production
48
+ While running web server and faye server, please, visit http://localhost:9292/faye
49
+ Webpage contains simple implementation of faye client, connecting to localhost:9393 server
50
+ After successful connection client subscribes on two channels: __/user/registered__ and __/time__
51
+ Faye events received displayed at the top of webpage
52
+
53
+ ## Sidekiq (optional, enabled by default)
54
+ Include support for background jobs via Sidekiq gem
55
+ Besides of main Sidekiq gem it also adds gem supporting jobs scheduling
56
+ Out of the box skeleton app have one scheduled job defined - __/jobs/pong_time.rb__
57
+ Job, scheduled to run each 5 seconds, simply publishes current time into /time faye channel
58
+ so all faye connections subscribed to /time channel will receive current time string
59
+ For more information take a look at /config/sidekiq.yml
60
+
61
+ ## Mandrill (optional, enabled by default)
62
+ Include support for email delivery with Mandrill service via MandrillMailer gem.
63
+ To have this gem running you should add your Mandrill api key to __/config/application.yml__
64
+ After successful registration with __POST /api/auth/register__ app tries to send message to user email using __/mailers/registraion_mailer.rb__
65
+ To have email delivered please make sure you have changed __from__ address in __/mailers/registraion_mailer.rb__ and appropriate domain name is registered for api key you add to config.file.
66
+
67
+ ## TODO
68
+
69
+ More documentation
24
70
 
25
71
  ## Contributing
26
72
 
27
- 1. Fork it ( https://github.com/[my-github-username]/grape-scaffold/fork )
73
+ 1. Fork it ( https://github.com/AlexYankee/grape-gen/fork )
28
74
  2. Create your feature branch (`git checkout -b my-new-feature`)
29
75
  3. Commit your changes (`git commit -am 'Add some feature'`)
30
76
  4. Push to the branch (`git push origin my-new-feature`)
@@ -1,5 +1,5 @@
1
1
  module Grape
2
2
  module Generate
3
- VERSION = '0.0.5'
3
+ VERSION = '0.0.6'
4
4
  end
5
5
  end
@@ -43,9 +43,6 @@ module Grape
43
43
 
44
44
  directory './', exclude_pattern: /(sidekiq|carrierwave|faye|mandrill|tire|elastic_search|search_indexes|mailers|uploaders|jobs)/
45
45
 
46
- directory './log'
47
- directory './tmp/pids'
48
-
49
46
  @redis ||= @sidekiq || @faye
50
47
 
51
48
  if @faye
@@ -54,8 +51,7 @@ module Grape
54
51
  copy_file './config/initializers/faye.rb'
55
52
  copy_file './config/initializers/em-patches/faye.rb'
56
53
  copy_file './public/faye.html'
57
- copy_file './lib/faye_auth_extension.rb'
58
- copy_file './lib/faye_publisher.rb'
54
+ directory './lib/faye'
59
55
  end
60
56
 
61
57
  if @sidekiq
data/template/Gemfile.tt CHANGED
@@ -52,6 +52,7 @@ group :utils do
52
52
  gem 'activesupport', '~> 4.2'
53
53
  gem 'multi_json', '~> 1.10.1'
54
54
  gem 'oj', '~> 2.11.2'
55
+ gem 'redis-namespace', '~> 1.5.1'
55
56
  end
56
57
  <%- if @es -%>
57
58
  # ElasticSearch
@@ -34,7 +34,7 @@ module API
34
34
  @user.save
35
35
  header['X-Authorize'] = @user.token
36
36
  <% if @faye %>
37
- FayePublisher.publish('/user/registered', {display_name: @user.display_name})
37
+ Faye::Publisher.instance.publish('/user/registered', {display_name: @user.display_name})
38
38
  <% end %>
39
39
  end
40
40
  end
@@ -18,5 +18,5 @@ ApplicationSettings.source File.expand_path('config/application.yml', APP_ROOT)
18
18
  ApplicationSettings.root = APP_ROOT
19
19
 
20
20
  require_relative 'initializers/logging'
21
- require_relative '../lib/faye_auth_extension'
22
- require_relative '../lib/faye_publisher'
21
+ require_relative '../lib/faye/auth_extension'
22
+ require_relative '../lib/faye/publisher'
@@ -1,4 +1,6 @@
1
1
  require_relative 'redis_lazy_evaluated_pool'
2
- require_relative '../../../lib/faye_publisher'
2
+ require_relative '../../../lib/faye/publisher'
3
3
 
4
- FayePublisher.redis = RedisLazyEvaluatedPool.pool_with_config(ApplicationSettings.faye.redis.to_hash.deep_symbolize_keys)
4
+ Faye::Publisher.configure do |config|
5
+ config.redis = RedisLazyEvaluatedPool.pool_with_config(ApplicationSettings.faye.redis.to_hash.deep_symbolize_keys)
6
+ end
@@ -14,7 +14,7 @@ class LazyEvaluatedPool < EventMachine::Synchrony::ConnectionPool
14
14
  private
15
15
  def acquire(fiber)
16
16
  if conn = @available.pop
17
- conn = self.instance_eval(&conn) if conn.respond_to?(:call)
17
+ conn = conn.call(@config) if conn.respond_to?(:call)
18
18
  @reserved[fiber.object_id] = conn
19
19
  conn
20
20
  else
@@ -26,7 +26,7 @@ class LazyEvaluatedPool < EventMachine::Synchrony::ConnectionPool
26
26
  class << self
27
27
  def pool_with_config(config, &block)
28
28
  config[:size] ||= 10
29
- LazyEvaluatedPool.new(config, &(block || connection))
29
+ new(config, &(block || connection))
30
30
  end
31
31
  private
32
32
  def connection; raise 'Please, override connection method or supply block' end
@@ -1,3 +1,5 @@
1
+ require 'mandrill'
2
+
1
3
  # Patch mandrill API to play ball with EventMachine
2
4
  module Mandrill
3
5
  class API
@@ -1,4 +1,3 @@
1
- require 'redis-namespace'
2
1
  require_relative 'redis'
3
2
  require_relative 'lazy_evaluated_pool'
4
3
 
@@ -9,8 +8,8 @@ class RedisLazyEvaluatedPool < LazyEvaluatedPool
9
8
  }
10
9
  private
11
10
  def self.connection
12
- Proc.new {
13
- config = RedisLazyEvaluatedPool::CONFIG_DEFAULTS.merge (@config|| {}).deep_symbolize_keys
11
+ Proc.new { |config|
12
+ config = RedisLazyEvaluatedPool::CONFIG_DEFAULTS.merge (config|| {}).deep_symbolize_keys
14
13
  connection = EventMachine::Hiredis.connect(config[:url])
15
14
  connection = Redis::Namespace.new(config[:namespace], redis: connection) if config[:namespace]
16
15
  connection
@@ -1,3 +1,5 @@
1
- require_relative '../../lib/faye_publisher'
1
+ require_relative '../../lib/faye/publisher'
2
2
 
3
- FayePublisher.redis = ApplicationSettings.faye.redis unless FayePublisher.configured?
3
+ Faye::Publisher.configure do |config|
4
+ config.redis = ApplicationSettings.faye.redis unless Faye::Publisher.configured?
5
+ end
@@ -1 +1,67 @@
1
- MandrillMailer.config.api = ApplicationSettings.mandrill.api_key
1
+ require 'mandrill'
2
+
3
+ module Mandrill
4
+ constants.select{|c| /Error$/ =~ c.to_s}.each{|const| remove_const(const) }
5
+ class Error < StandardError
6
+ end
7
+ class ValidationError < Error
8
+ end
9
+ class InvalidKeyError < Error
10
+ end
11
+ class PaymentRequiredError < Error
12
+ end
13
+ class UnknownSubaccountError < Error
14
+ end
15
+ class UnknownTemplateError < Error
16
+ end
17
+ class ServiceUnavailableError < Error
18
+ end
19
+ class UnknownMessageError < Error
20
+ end
21
+ class InvalidTagNameError < Error
22
+ end
23
+ class InvalidRejectError < Error
24
+ end
25
+ class UnknownSenderError < Error
26
+ end
27
+ class UnknownUrlError < Error
28
+ end
29
+ class UnknownTrackingDomainError < Error
30
+ end
31
+ class InvalidTemplateError < Error
32
+ end
33
+ class UnknownWebhookError < Error
34
+ end
35
+ class UnknownInboundDomainError < Error
36
+ end
37
+ class UnknownInboundRouteError < Error
38
+ end
39
+ class UnknownExportError < Error
40
+ end
41
+ class IPProvisionLimitError < Error
42
+ end
43
+ class UnknownPoolError < Error
44
+ end
45
+ class NoSendingHistoryError < Error
46
+ end
47
+ class PoorReputationError < Error
48
+ end
49
+ class UnknownIPError < Error
50
+ end
51
+ class InvalidEmptyDefaultPoolError < Error
52
+ end
53
+ class InvalidDeleteDefaultPoolError < Error
54
+ end
55
+ class InvalidDeleteNonEmptyPoolError < Error
56
+ end
57
+ class InvalidCustomDNSError < Error
58
+ end
59
+ class InvalidCustomDNSPendingError < Error
60
+ end
61
+ class MetadataFieldLimitError < Error
62
+ end
63
+ class UnknownMetadataFieldError < Error
64
+ end
65
+ end
66
+
67
+ MandrillMailer.config.api_key = ApplicationSettings.mandrill.api_key
@@ -1,6 +1,70 @@
1
1
  require 'tire/http/clients/faraday'
2
2
 
3
+ module Tire
4
+ class ExternalLogger < Tire::Logger
5
+
6
+ def initialize(logger)
7
+ @logger = logger
8
+ end
9
+
10
+ def level
11
+ @logger.level
12
+ end
13
+
14
+ def write(message)
15
+ @logger.info message
16
+ end
17
+
18
+ def log_request(endpoint, params=nil, curl='')
19
+ # 2001-02-12 18:20:42:32 [_search] (articles,users)
20
+ #
21
+ # curl -X POST ....
22
+ #
23
+ content = "# #{time}"
24
+ content += " [#{endpoint}]"
25
+ content += " (#{params.inspect})" if params
26
+ content += "\n#\n"
27
+ content += curl
28
+ content += "\n\n"
29
+ write content
30
+ end
31
+
32
+ def log_response(status, took=nil, json='')
33
+ # 2001-02-12 18:20:42:32 [200] (4 msec)
34
+ #
35
+ # {
36
+ # "took" : 4,
37
+ # "hits" : [...]
38
+ # ...
39
+ # }
40
+ #
41
+ content = "# #{time}"
42
+ content += " [#{status}]"
43
+ content += " (#{took} msec)" if took
44
+ content += "\n#\n" unless json.to_s !~ /\S/
45
+ json.to_s.each_line { |line| content += "# #{line}" } unless json.to_s !~ /\S/
46
+ content += "\n\n"
47
+ write content
48
+ end
49
+
50
+ def time
51
+ Time.now.strftime('%Y-%m-%d %H:%M:%S:%L')
52
+ end
53
+ end
54
+ end
55
+
56
+
57
+ module Tire
58
+ class Configuration
59
+ def self.logger(logger = nil)
60
+ return @logger = logger if logger
61
+ @logger || nil
62
+ end
63
+ end
64
+ end
65
+
3
66
  Tire.configure do
4
67
  url ApplicationSettings.elasticsearch.url
5
- logger Logging.logger[:elasticsearch]
6
- end
68
+ logger Tire::ExternalLogger.new(Logging.logger[:elasticsearch])
69
+ end
70
+
@@ -5,7 +5,7 @@ module DelayedJobs
5
5
  sidekiq_options unique: true
6
6
 
7
7
  def perform
8
- FayePublisher.publish('/time',Time.now.utc.to_s)
8
+ Faye::Publisher.instance.publish('/time',Time.now.utc.to_s)
9
9
  end
10
10
  end
11
11
  end
@@ -1,4 +1,4 @@
1
- require_relative 'warden/token_strategy'
1
+ require_relative '../warden/token_strategy'
2
2
 
3
3
  module Faye
4
4
  class AuthExtension
@@ -0,0 +1,57 @@
1
+ require 'connection_pool'
2
+ require 'em-synchrony/connection_pool'
3
+
4
+ module Faye
5
+ module Publisher
6
+ class << self
7
+ def instance
8
+ @default_instance ||= RedisPublisher.new(configuration.redis)
9
+ end
10
+
11
+ def configure
12
+ yield(configuration)
13
+ end
14
+
15
+ def configured?
16
+ !@config.nil?
17
+ end
18
+
19
+ private
20
+ def configuration
21
+ @config ||= OpenStruct.new(redis: {url: 'redis://localhost:6379', size: 10, namespace: 'faye'})
22
+ end
23
+ end
24
+
25
+ class RedisPublisher
26
+ def initialize(config)
27
+ case config
28
+ when
29
+ ::ConnectionPool,
30
+ EventMachine::Synchrony::ConnectionPool
31
+ @redis = config
32
+ else
33
+ @config = config
34
+ end
35
+ end
36
+
37
+ def publish(channel, payload)
38
+ redis.rpush(
39
+ 'faye.messages',
40
+ MultiJson.dump(
41
+ channel: channel,
42
+ payload: payload
43
+ )
44
+ )
45
+ end
46
+
47
+ private
48
+ def redis
49
+ @redis ||= ConnectionPool::Wrapper.new(size: @config[:size] || 10) do
50
+ connection = Redis.new(url: @config[:url])
51
+ connection = Redis::Namespace.new(@config[:namespace], redis: connection) if @config[:namespace]
52
+ connection
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,19 @@
1
+ module Faye
2
+ module Publisher
3
+ FakePublishing = Struct.new(:channel, :payload)
4
+
5
+ class RedisPublisher
6
+ def publish(*args)
7
+ publishings << Faye::Publisher::FakePublishing.new(*args)
8
+ end
9
+
10
+ def clear_publishings
11
+ @publishings.clear
12
+ end
13
+
14
+ def publishings
15
+ @publishings ||= []
16
+ end
17
+ end
18
+ end
19
+ end
@@ -7,8 +7,13 @@ require 'rspec_api_documentation'
7
7
  <% if @mandrill %>
8
8
  require 'mandrill_mailer/offline'
9
9
  <% end %>
10
+
10
11
  RACK_ENV = 'test' unless defined?(RACK_ENV)
11
12
 
13
+ %w{patches}.each do |path|
14
+ Dir[File.expand_path('patches/**/*.rb', File.dirname(__FILE__))].each {|f| require f}
15
+ end
16
+
12
17
  class TestApiClient < RspecApiDocumentation::RackTestClient
13
18
  def response_body
14
19
  body = JSON.load(last_response.body)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-gen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - AMar4enko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-16 00:00:00.000000000 Z
11
+ date: 2015-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -106,8 +106,8 @@ files:
106
106
  - template/config/sidekiq.yml.tt
107
107
  - template/faye.ru
108
108
  - template/jobs/pong_time.rb
109
- - template/lib/faye_auth_extension.rb
110
- - template/lib/faye_publisher.rb
109
+ - template/lib/faye/auth_extension.rb
110
+ - template/lib/faye/publisher.rb
111
111
  - template/lib/mongoid/tire_plugin.rb
112
112
  - template/lib/warden/token_strategy.rb
113
113
  - template/log/.gitkeep
@@ -118,6 +118,7 @@ files:
118
118
  - template/search_indexes/user_index.rb
119
119
  - template/spec/api/mounts/auth_spec.rb.tt
120
120
  - template/spec/factories/user.rb
121
+ - template/spec/patches/faye/publisher/test.rb
121
122
  - template/spec/spec_helper.rb.tt
122
123
  - template/tmp/pids/.gitkeep
123
124
  - template/uploaders/avatar_uploader.rb
@@ -1,63 +0,0 @@
1
- require 'connection_pool'
2
- require 'em-synchrony/connection_pool'
3
-
4
- module FayePublisher
5
- FakePublishing = Struct.new(:channel, :payload)
6
- class << self
7
- def fake!
8
- @fake = true
9
- end
10
-
11
- def redis=(arg)
12
- case arg
13
- when
14
- ::ConnectionPool,
15
- EventMachine::Synchrony::ConnectionPool # Or its descendants
16
- @redis = arg
17
- else
18
- @_config = arg
19
- end
20
- end
21
-
22
- def redis
23
- @redis ||= begin
24
- config = ApplicationSettings.faye.redis
25
- ConnectionPool::Wrapper.new(size: config[:size] || 10) do
26
- connection = Redis.new(url: config[:url])
27
- connection = Redis::Namespace.new(config[:namespace], redis: connection) if config[:namespace]
28
- connection
29
- end
30
- end
31
- end
32
-
33
- def publish(channel, payload)
34
- if @fake
35
- fake_publishings.push(FakePublishing.new(channel, payload))
36
- return true
37
- end
38
- redis.rpush(
39
- 'faye.messages',
40
- MultiJson.dump(
41
- channel: channel,
42
- payload: payload
43
- )
44
- )
45
- end
46
-
47
- def configured?; @connection || @_config end
48
-
49
- def publishings
50
- raise 'FayePublisher is not configured in fake! mode' unless @fake
51
- fake_publishings
52
- end
53
-
54
- def clear_publishings
55
- @fake_publishings.clear
56
- end
57
-
58
- private
59
- def fake_publishings
60
- @fake_publishings ||= []
61
- end
62
- end
63
- end