cramp 0.11 → 0.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/lib/cramp.rb +12 -1
  2. data/lib/cramp/abstract.rb +72 -0
  3. data/lib/cramp/action.rb +12 -0
  4. data/lib/cramp/body.rb +48 -0
  5. data/lib/cramp/callbacks.rb +48 -0
  6. data/lib/cramp/keep_connection_alive.rb +19 -0
  7. data/lib/cramp/periodic_timer.rb +49 -0
  8. data/lib/cramp/rendering.rb +11 -0
  9. data/lib/cramp/test_case.rb +54 -0
  10. data/lib/cramp/websocket.rb +84 -0
  11. data/lib/cramp/{controller/websocket → websocket}/rainbows_backend.rb +1 -1
  12. data/lib/cramp/{controller/websocket → websocket}/thin_backend.rb +1 -1
  13. metadata +37 -86
  14. data/lib/cramp/controller.rb +0 -15
  15. data/lib/cramp/controller/abstract.rb +0 -71
  16. data/lib/cramp/controller/action.rb +0 -14
  17. data/lib/cramp/controller/body.rb +0 -50
  18. data/lib/cramp/controller/callbacks.rb +0 -50
  19. data/lib/cramp/controller/keep_connection_alive.rb +0 -21
  20. data/lib/cramp/controller/periodic_timer.rb +0 -51
  21. data/lib/cramp/controller/rendering.rb +0 -13
  22. data/lib/cramp/controller/test_case.rb +0 -57
  23. data/lib/cramp/controller/websocket.rb +0 -63
  24. data/lib/cramp/model.rb +0 -40
  25. data/lib/cramp/model/arel_monkey_patches.rb +0 -66
  26. data/lib/cramp/model/attribute.rb +0 -104
  27. data/lib/cramp/model/attribute_methods.rb +0 -83
  28. data/lib/cramp/model/base.rb +0 -119
  29. data/lib/cramp/model/callbacks.rb +0 -41
  30. data/lib/cramp/model/column.rb +0 -72
  31. data/lib/cramp/model/emysql_ext.rb +0 -21
  32. data/lib/cramp/model/engine.rb +0 -75
  33. data/lib/cramp/model/engine/connection.rb +0 -32
  34. data/lib/cramp/model/evented_mysql.rb +0 -298
  35. data/lib/cramp/model/finders.rb +0 -27
  36. data/lib/cramp/model/quoting.rb +0 -104
  37. data/lib/cramp/model/relation.rb +0 -62
  38. data/lib/cramp/model/status.rb +0 -18
@@ -1,13 +0,0 @@
1
- module Cramp
2
- module Controller
3
- module Rendering
4
-
5
- extend ActiveSupport::Concern
6
-
7
- def render(body)
8
- @body.call(body)
9
- end
10
-
11
- end
12
- end
13
- end
@@ -1,57 +0,0 @@
1
- require 'active_support'
2
- require 'active_support/test_case'
3
-
4
- module Cramp
5
- module Controller
6
- class TestCase < ::ActiveSupport::TestCase
7
-
8
- setup :create_request
9
-
10
- def create_request
11
- @request = Rack::MockRequest.new(app)
12
- end
13
-
14
- def get(path, options = {}, headers = {}, &block)
15
- callback = options.delete(:callback) || block
16
- headers = headers.merge('async.callback' => callback)
17
-
18
- EM.run { @request.get(path, headers) }
19
- end
20
-
21
- def get_body(path, options = {}, headers = {}, &block)
22
- callback = options.delete(:callback) || block
23
- response_callback = proc {|response| response[-1].each {|chunk| callback.call(chunk) } }
24
- headers = headers.merge('async.callback' => response_callback)
25
-
26
- EM.run { @request.get(path, headers) }
27
- end
28
-
29
- def get_body_chunks(path, options = {}, headers = {}, &block)
30
- callback = options.delete(:callback) || block
31
- count = options.delete(:count) || 1
32
-
33
- stopping = false
34
- chunks = []
35
-
36
- get_body(path, options, headers) do |body_chunk|
37
- chunks << body_chunk unless stopping
38
-
39
- if chunks.count >= count
40
- stopping = true
41
- callback.call(chunks) if callback
42
- EM.next_tick { EM.stop }
43
- end
44
- end
45
- end
46
-
47
- def app
48
- raise "Please define a method called 'app' returning an async Rack Application"
49
- end
50
-
51
- def stop
52
- EM.stop
53
- end
54
- end
55
-
56
- end
57
- end
@@ -1,63 +0,0 @@
1
- module Cramp
2
- module Controller
3
- module WebsocketExtension
4
- WEBSOCKET_RECEIVE_CALLBACK = 'websocket.receive_callback'.freeze
5
-
6
- def websocket?
7
- @env['HTTP_CONNECTION'] == 'Upgrade' && @env['HTTP_UPGRADE'] == 'WebSocket'
8
- end
9
-
10
- def websocket_upgrade_data
11
- location = "ws://#{@env['HTTP_HOST']}#{@env['REQUEST_PATH']}"
12
-
13
- upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
14
- upgrade << "Upgrade: WebSocket\r\n"
15
- upgrade << "Connection: Upgrade\r\n"
16
- upgrade << "WebSocket-Origin: #{@env['HTTP_ORIGIN']}\r\n"
17
- upgrade << "WebSocket-Location: #{location}\r\n\r\n"
18
-
19
- upgrade
20
- end
21
- end
22
-
23
- class Websocket < Abstract
24
- include PeriodicTimer
25
-
26
- # TODO : Websockets shouldn't need this in an ideal world
27
- include KeepConnectionAlive
28
-
29
- class_inheritable_accessor :on_data_callbacks, :instance_reader => false
30
- self.on_data_callbacks = []
31
-
32
- class << self
33
- def backend=(backend)
34
- raise "Websocket backend #{backend} is unknown" unless [:thin, :rainbows].include?(backend.to_sym)
35
- require "cramp/controller/websocket/#{backend}_backend.rb"
36
- end
37
-
38
- def on_data(*methods)
39
- self.on_data_callbacks += methods
40
- end
41
- end
42
-
43
- def process
44
- @env['websocket.receive_callback'] = method(:_on_data_receive)
45
- super
46
- end
47
-
48
- def render(body)
49
- @body.call("\x00#{body}\xff")
50
- end
51
-
52
- def _on_data_receive(data)
53
- data = data.split(/\000([^\377]*)\377/).select{|d| !d.empty? }.collect{|d| d.gsub(/^\x00|\xff$/, '') }
54
- self.class.on_data_callbacks.each do |callback|
55
- data.each do |message|
56
- EM.next_tick { send(callback, message) }
57
- end
58
- end
59
- end
60
-
61
- end
62
- end
63
- end
data/lib/cramp/model.rb DELETED
@@ -1,40 +0,0 @@
1
- require 'cramp'
2
- require 'cramp/model/evented_mysql'
3
- require 'cramp/model/emysql_ext'
4
-
5
- require 'mysqlplus'
6
-
7
- require 'arel'
8
- require 'cramp/model/arel_monkey_patches'
9
-
10
- require 'active_model'
11
-
12
- module Cramp
13
- module Model
14
- autoload :Quoting, "cramp/model/quoting"
15
- autoload :Engine, "cramp/model/engine"
16
- autoload :Column, "cramp/model/column"
17
- autoload :Relation, "cramp/model/relation"
18
-
19
- autoload :Base, "cramp/model/base"
20
- autoload :Finders, "cramp/model/finders"
21
- autoload :Attribute, "cramp/model/attribute"
22
- autoload :AttributeMethods, "cramp/model/attribute_methods"
23
- autoload :Status, "cramp/model/status"
24
- autoload :Callbacks, "cramp/model/callbacks"
25
-
26
- def self.init(settings)
27
- Arel::Table.engine = Cramp::Model::Engine.new(settings)
28
- end
29
-
30
- def self.select(query, callback = nil, &block)
31
- callback ||= block
32
-
33
- EventedMysql.select(query) do |rows|
34
- callback.arity == 1 ? callback.call(rows) : callback.call if callback
35
- end
36
- end
37
-
38
- end
39
- end
40
-
@@ -1,66 +0,0 @@
1
- class Arel::Session
2
- def create(insert, &block)
3
- insert.call(&block)
4
- end
5
-
6
- def read(select, &block)
7
- select.call(&block)
8
- end
9
-
10
- def update(update, &block)
11
- update.call(&block)
12
- end
13
-
14
- def delete(delete, &block)
15
- delete.call(&block)
16
- end
17
-
18
- end
19
-
20
- module Arel::Relation
21
- def call(&block)
22
- engine.read(self, &block)
23
- end
24
-
25
- def all(&block)
26
- session.read(self) {|rows| block.call(rows) }
27
- end
28
-
29
- def first(&block)
30
- session.read(self) {|rows| block.call(rows[0]) }
31
- end
32
-
33
- def each(&block)
34
- session.read(self) {|rows| rows.each {|r| block.call(r) } }
35
- end
36
-
37
- def insert(record, &block)
38
- session.create(Arel::Insert.new(self, record), &block)
39
- end
40
-
41
- def update(assignments, &block)
42
- session.update(Arel::Update.new(self, assignments), &block)
43
- end
44
-
45
- def delete(&block)
46
- session.delete(Arel::Deletion.new(self), &block)
47
- end
48
- end
49
-
50
- class Arel::Deletion
51
- def call(&block)
52
- engine.delete(self, &block)
53
- end
54
- end
55
-
56
- class Arel::Insert
57
- def call(&block)
58
- engine.create(self, &block)
59
- end
60
- end
61
-
62
- class Arel::Update
63
- def call(&block)
64
- engine.update(self, &block)
65
- end
66
- end
@@ -1,104 +0,0 @@
1
- # Copyright (c) 2009 Koziarski Software Ltd
2
- #
3
- # Permission to use, copy, modify, and/or distribute this software for any
4
- # purpose with or without fee is hereby granted, provided that the above
5
- # copyright notice and this permission notice appear in all copies.
6
- #
7
- # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
- # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
- # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10
- # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
- # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
- # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
- # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
-
15
- module Cramp
16
- module Model
17
- class Attribute
18
-
19
- FORMATS = {}
20
- FORMATS[Date] = /^\d{4}\/\d{2}\/\d{2}$/
21
- FORMATS[Integer] = /^-?\d+$/
22
- FORMATS[Float] = /^-?\d*\.\d*$/
23
- FORMATS[Time] = /\A\s*
24
- -?\d+-\d\d-\d\d
25
- T
26
- \d\d:\d\d:\d\d
27
- (\.\d*)?
28
- (Z|[+-]\d\d:\d\d)?
29
- \s*\z/ix # lifted from the implementation of Time.xmlschema
30
-
31
- CONVERTERS = {}
32
- CONVERTERS[Date] = Proc.new do |str|
33
- Date.strptime(str, "%Y/%m/%d")
34
- end
35
-
36
- CONVERTERS[Integer] = Proc.new do |str|
37
- Integer(str)
38
- end
39
-
40
- CONVERTERS[Float] = Proc.new do |str|
41
- Float(str)
42
- end
43
-
44
- CONVERTERS[Time] = Proc.new do |str|
45
- Time.xmlschema(str)
46
- end
47
-
48
- attr_reader :name
49
- def initialize(name, owner_class, options)
50
- @name = name.to_s
51
- @owner_class = owner_class
52
- @options = options
53
-
54
- # append_validations!
55
- define_methods!
56
- end
57
-
58
- # I think this should live somewhere in Amo
59
- def check_value!(value)
60
- # Allow nil and Strings to fall back on the validations for typecasting
61
- # Everything else gets checked with is_a?
62
- if value.nil?
63
- nil
64
- elsif value.is_a?(String)
65
- value
66
- elsif value.is_a?(expected_type)
67
- value
68
- else
69
- raise TypeError, "Expected #{expected_type.inspect} but got #{value.inspect}"
70
- end
71
- end
72
-
73
- def expected_type
74
- @options[:type] || String
75
- end
76
-
77
- def type_cast(value)
78
- if value.is_a?(expected_type)
79
- value
80
- elsif (converter = CONVERTERS[expected_type]) && (value =~ FORMATS[expected_type])
81
- converter.call(value)
82
- else
83
- value
84
- end
85
- end
86
-
87
- def append_validations!
88
- if f = FORMATS[expected_type]
89
- @owner_class.validates_format_of @name, :with => f, :unless => lambda {|obj| obj.send(name).is_a? expected_type }, :allow_nil => @options[:allow_nil]
90
- end
91
- end
92
-
93
- def define_methods!
94
- @owner_class.define_attribute_methods(true)
95
- end
96
-
97
- def primary_key?
98
- @options[:primary_key]
99
- end
100
-
101
- end
102
-
103
- end
104
- end
@@ -1,83 +0,0 @@
1
- # Copyright (c) 2009 Koziarski Software Ltd
2
- #
3
- # Permission to use, copy, modify, and/or distribute this software for any
4
- # purpose with or without fee is hereby granted, provided that the above
5
- # copyright notice and this permission notice appear in all copies.
6
- #
7
- # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
- # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
- # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10
- # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
- # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
- # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
- # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
-
15
- module Cramp
16
- module Model
17
- module AttributeMethods
18
-
19
- extend ActiveSupport::Concern
20
- include ActiveModel::AttributeMethods
21
-
22
- module ClassMethods
23
- def attribute(name, options = {})
24
- write_inheritable_hash(:model_attributes, {name => Attribute.new(name, self, options)})
25
- end
26
-
27
- def define_attribute_methods(force = false)
28
- return unless model_attributes
29
- undefine_attribute_methods if force
30
- super(model_attributes.keys)
31
- end
32
- end
33
-
34
- included do
35
- class_inheritable_hash :model_attributes
36
- undef_method(:id) if method_defined?(:id)
37
-
38
- attribute_method_suffix("", "=")
39
- end
40
-
41
- def write_attribute(name, value)
42
- if ma = self.class.model_attributes[name.to_sym]
43
- value = ma.check_value!(value)
44
- end
45
- if(@attributes[name] != value)
46
- send "#{name}_will_change!".to_sym
47
- @attributes[name] = value
48
- end
49
- end
50
-
51
- def read_attribute(name)
52
- if ma = self.class.model_attributes[name]
53
- ma.type_cast(@attributes[name])
54
- else
55
- @attributes[name]
56
- end
57
- end
58
-
59
- def attributes=(attributes)
60
- attributes.each do |(name, value)|
61
- send("#{name}=", value)
62
- end
63
- end
64
-
65
- protected
66
-
67
- def attribute_method?(name)
68
- @attributes.include?(name.to_sym) || model_attributes[name.to_sym]
69
- end
70
-
71
- private
72
-
73
- def attribute(name)
74
- read_attribute(name.to_sym)
75
- end
76
-
77
- def attribute=(name, value)
78
- write_attribute(name.to_sym, value)
79
- end
80
-
81
- end
82
- end
83
- end
@@ -1,119 +0,0 @@
1
- module Cramp
2
- module Model
3
- class Base
4
-
5
- extend Finders
6
- include AttributeMethods
7
- include ActiveModel::Validations
8
- include ActiveModel::Dirty
9
- include Callbacks
10
-
11
- class << self
12
- def columns
13
- @columns ||= arel_table.columns
14
- end
15
-
16
- def column_names
17
- columns.map(&:name)
18
- end
19
-
20
- def primary_key
21
- @primary_key ||= model_attributes.detect {|k, v| v.primary_key? }[0]
22
- end
23
-
24
- def instantiate(record)
25
- object = allocate
26
- object.instance_variable_set("@attributes", record.with_indifferent_access)
27
- object
28
- end
29
- end
30
-
31
- attr_reader :attributes
32
-
33
- def initialize(attributes = {})
34
- @new_record = true
35
- @attributes = {}.with_indifferent_access
36
- self.attributes = attributes
37
- end
38
-
39
- def new_record?
40
- @new_record
41
- end
42
-
43
- def save(callback = nil, &block)
44
- callback ||= block
45
-
46
- if valid?
47
- new_record? ? create_record(callback) : update_record(callback)
48
- else
49
- callback.arity == 1 ? callback.call(Status.new(self, false)) : callback.call if callback
50
- end
51
- end
52
-
53
- def destroy(callback = nil, &block)
54
- callback ||= block
55
-
56
- relation.delete do
57
- status = Status.new(self, true)
58
- after_destroy_callbacks status
59
- callback.arity == 1 ? callback.call(status) : callback.call if callback
60
- end
61
- end
62
-
63
- private
64
-
65
- def create_record(callback = nil, &block)
66
- callback ||= block
67
-
68
- self.class.arel_table.insert(arel_attributes(true)) do |new_id|
69
- if new_id.present?
70
- self.id = new_id
71
- saved = true
72
- @new_record = false
73
- else
74
- saved = false
75
- end
76
-
77
- status = Status.new(self, saved)
78
- after_save status
79
- callback.arity == 1 ? callback.call(status) : callback.call if callback
80
- end
81
- end
82
-
83
- def update_record(callback = nil, &block)
84
- callback ||= block
85
-
86
- relation.update(arel_attributes) do |updated_rows|
87
- status = Status.new(self, true)
88
- after_save status
89
- callback.arity == 1 ? callback.call(status) : callback.call if callback
90
- end
91
- end
92
-
93
- def relation
94
- self.class.arel_table.where(self.class[self.class.primary_key].eq(send(self.class.primary_key)))
95
- end
96
-
97
- def after_save(status)
98
- if status.success?
99
- @previously_changed = changes
100
- changed_attributes.clear
101
- end
102
-
103
- after_save_callbacks status
104
- end
105
-
106
- def arel_attributes(exclude_primary_key = true, attribute_names = @attributes.keys)
107
- attrs = {}
108
-
109
- attribute_names.each do |name|
110
- value = read_attribute(name)
111
- attrs[self.class.arel_table[name]] = value
112
- end
113
-
114
- attrs
115
- end
116
-
117
- end
118
- end
119
- end