rack-scaffold 0.0.1 → 0.0.2

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: 62eaf4d70bb8f5ffe5b174b33713b1ebeae39bc5
4
- data.tar.gz: 60452a102b8b505f53dfdc1a6ef2b32a56931ccf
3
+ metadata.gz: 2e321a350a25a6a2fe7440f27ec0e26dbdf6dcb4
4
+ data.tar.gz: d2a63d3b802a9d78efc70f0d2f92feef62dce3dc
5
5
  SHA512:
6
- metadata.gz: 5f9b7caa071e3813f3b0115e68db9ada8c116f57d5283594d3c6811a84faed2781a745ea1866dea66d722d3d9121058cd6f4f78c16c8dcf5009c3990fd51604d
7
- data.tar.gz: 36a22a42bbd975c11cfec13ca44f239774061b8a8a7115eeda608bf96031b84ec74813a7eddc113d72cbac3d1ec125cb1f1e43ee2171c4c578dae97ac351bc09
6
+ metadata.gz: d4bd26aa4a6313a847622a635b5da6d5bf575734092548d75581a8d7806f3a8c872d17495831f9ade59323c424114ba6f1a32a0497cab9f9c03d1dcfe81c5435
7
+ data.tar.gz: d9abfdd3d3bc747130d937a44cbdafcc701f4d127fcddacbe036e0c10e8ba8fefc0ee81f02cc67172a5c548231a16ba7f9ec8e34eb487415beaf449493344575
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rack-scaffold (0.0.1)
4
+ rack-scaffold (0.0.2)
5
5
  activesupport (>= 3.0)
6
6
  rack (~> 1.4)
7
7
  rack-contrib (~> 1.1)
@@ -15,7 +15,7 @@ GEM
15
15
  i18n (= 0.6.1)
16
16
  multi_json (~> 1.0)
17
17
  i18n (0.6.1)
18
- multi_json (1.7.2)
18
+ multi_json (1.7.3)
19
19
  rack (1.5.2)
20
20
  rack-contrib (1.1.0)
21
21
  rack (>= 0.9.1)
@@ -26,9 +26,9 @@ GEM
26
26
  rack (~> 1.5, >= 1.5.2)
27
27
  rack-protection (~> 1.4)
28
28
  tilt (~> 1.3, >= 1.3.4)
29
- sinatra-param (0.1.2)
29
+ sinatra-param (0.1.3)
30
30
  sinatra (~> 1.3)
31
- tilt (1.3.7)
31
+ tilt (1.4.1)
32
32
 
33
33
  PLATFORMS
34
34
  ruby
@@ -3,7 +3,6 @@ require 'rack/contrib'
3
3
  require 'sinatra/base'
4
4
  require 'sinatra/param'
5
5
 
6
- require 'rack/scaffold/version'
7
6
  require 'rack/scaffold/adapters'
8
7
 
9
8
  module Rack
@@ -26,6 +25,15 @@ module Rack
26
25
  end
27
26
 
28
27
  disable :raise_errors, :show_exceptions
28
+
29
+ def last_modified_time(resource, resources)
30
+ update_timestamp_field = resource.update_timestamp_field.to_sym
31
+ most_recently_updated = resources.class.include?(Enumerable) ? resources.max_by(&update_timestamp_field) : resources
32
+
33
+ timestamp = request.env['HTTP_IF_MODIFIED_SINCE']
34
+ timestamp = most_recently_updated.send(update_timestamp_field) if most_recently_updated
35
+ timestamp
36
+ end
29
37
  end
30
38
 
31
39
  @actions = (options[:only] || ACTIONS) - (options[:except] || [])
@@ -33,13 +41,13 @@ module Rack
33
41
  @adapter = Rack::Scaffold.adapters.detect{|adapter| adapter === options[:model]}
34
42
  raise "No suitable adapters found for #{options[:model]} in #{Rack::Scaffold.adapters}" unless @adapter
35
43
 
36
- resources = Array(@adapter.resources(options[:model]))
44
+ resources = Array(@adapter.resources(options[:model], options))
37
45
  resources.each do |resource|
38
46
  @app.instance_eval do
39
47
  post "/#{resource.plural}/?" do
40
48
  if record = resource.create!(params)
41
49
  status 201
42
- {entity.name.downcase => record}.to_json
50
+ {"#{resource.singular}" => record}.to_json
43
51
  else
44
52
  status 406
45
53
  {errors: record.errors}.to_json
@@ -53,8 +61,11 @@ module Rack
53
61
  param :page, Integer, default: 1, min: 1
54
62
  param :per_page, Integer, default: 100, in: (1..100)
55
63
 
64
+ resources = resource.paginate(params[:per_page], (params[:page] - 1) * params[:per_page])
65
+ last_modified(last_modified_time(resource, resources)) if resource.timestamps?
66
+
56
67
  {
57
- "#{resource.plural}" => resource.paginate(params[:per_page], (params[:page] - 1) * params[:per_page]),
68
+ "#{resource.plural}" => resources,
58
69
  page: params[:page],
59
70
  total: resource.count
60
71
  }.to_json
@@ -62,16 +73,21 @@ module Rack
62
73
  param :limit, Integer, default: 100, in: (1..100)
63
74
  param :offset, Integer, default: 0, min: 0
64
75
 
76
+ resources = resource.paginate(params[:limit], params[:offset])
77
+ last_modified(last_modified_time(resource, resources)) if resource.timestamps?
78
+
65
79
  {
66
- "#{resource.plural}" => resource.paginate(params[:limit], params[:offset])
80
+ "#{resource.plural}" => resources
67
81
  }.to_json
68
82
  end
69
83
  end
70
84
 
71
85
  get "/#{resource.plural}/:id/?" do
72
86
  record = resource[params[:id]] or halt 404
73
- {entity.name.downcase => record}.to_json
87
+ last_modified(last_modified_time(resource, record)) if resource.timestamps?
88
+ {"#{resource.singular}" => record}.to_json
74
89
  end
90
+
75
91
  end if @actions.include?(:read)
76
92
 
77
93
  @app.instance_eval do
@@ -79,7 +95,7 @@ module Rack
79
95
  record = resource[params[:id]] or halt 404
80
96
  if record.update!(params)
81
97
  status 200
82
- {entity.name.downcase => record}.to_json
98
+ {"#{resource.singular}" => record}.to_json
83
99
  else
84
100
  status 406
85
101
  {errors: record.errors}.to_json
@@ -97,7 +113,7 @@ module Rack
97
113
  {errors: record.errors}.to_json
98
114
  end
99
115
  end
100
- end if @actions.include?(:delete)
116
+ end if @actions.include?(:destroy)
101
117
 
102
118
  # @app.instance_eval do
103
119
  # entity.relationships.each do |relationship|
@@ -20,7 +20,7 @@ module Rack
20
20
  raise NotImplementedError
21
21
  end
22
22
 
23
- def resources(model)
23
+ def resources(model, options = {})
24
24
  raise NotImplementedError
25
25
  end
26
26
  end
@@ -68,6 +68,14 @@ module Rack
68
68
  def destroy!
69
69
  raise NotImplementedError
70
70
  end
71
+
72
+ def timestamps?
73
+ raise NotImplementedError
74
+ end
75
+
76
+ def update_timestamp_field
77
+ raise NotImplementedError
78
+ end
71
79
  end
72
80
  end
73
81
  end
@@ -12,9 +12,13 @@ module Rack::Scaffold::Adapters
12
12
  ::ActiveRecord::Base === model
13
13
  end
14
14
 
15
- def resources(model)
15
+ def resources(model, options = {})
16
16
  model
17
17
  end
18
+
19
+ def timestamps?
20
+ record_timestamps?
21
+ end
18
22
  end
19
23
 
20
24
  def singular
@@ -32,5 +36,9 @@ module Rack::Scaffold::Adapters
32
36
  def [](id)
33
37
  self.find(id)
34
38
  end
39
+
40
+ def update_timestamp_field
41
+ self.attribute_names.include?("updated_at") ? "updated_at" : "updated_on"
42
+ end
35
43
  end
36
44
  end
@@ -10,13 +10,13 @@ module Rack::Scaffold::Adapters
10
10
  !! ::CoreData::DataModel.new(model) rescue false
11
11
  end
12
12
 
13
- def resources(xcdatamodel)
13
+ def resources(xcdatamodel, options = {})
14
14
  model = ::CoreData::DataModel.new(xcdatamodel)
15
- model.entities.collect{|entity| new(entity)}
15
+ model.entities.collect{|entity| new(entity, options)}
16
16
  end
17
17
  end
18
18
 
19
- def initialize(entity)
19
+ def initialize(entity, options = {})
20
20
  klass = Class.new(::Sequel::Model)
21
21
  klass.dataset = entity.name.downcase.pluralize.to_sym
22
22
 
@@ -28,6 +28,15 @@ module Rack::Scaffold::Adapters
28
28
  plugin :schema
29
29
  plugin :validation_helpers
30
30
 
31
+ if options[:timestamps]
32
+ if options[:timestamps].instance_of? Hash
33
+ plugin :timestamps, options[:timestamps]
34
+ else
35
+ plugin :timestamps
36
+ end
37
+ # plugin :timestamps, create: :createdAt, update: :updatedAt
38
+ end
39
+
31
40
  def url
32
41
  "/#{self.class.table_name}/#{self[primary_key]}"
33
42
  end
@@ -55,16 +64,16 @@ module Rack::Scaffold::Adapters
55
64
  }
56
65
 
57
66
  type = case attribute.type
58
- when "Integer 16" then :int2
59
- when "Integer 32" then :int4
60
- when "Integer 64" then :int8
61
- when "Float" then :float4
62
- when "Double" then :float8
63
- when "Decimal" then :float8
64
- when "Date" then :timestamp
65
- when "Boolean" then :boolean
66
- when "Binary" then :bytea
67
- else :varchar
67
+ when "Integer 16" then :int2
68
+ when "Integer 32" then :int4
69
+ when "Integer 64" then :int8
70
+ when "Float" then :float4
71
+ when "Double" then :float8
72
+ when "Decimal" then :float8
73
+ when "Date" then :timestamp
74
+ when "Boolean" then :boolean
75
+ when "Binary" then :bytea
76
+ else :varchar
68
77
  end
69
78
 
70
79
  column attribute.name.to_sym, type, options
@@ -97,18 +106,19 @@ module Rack::Scaffold::Adapters
97
106
  klass.send :define_method, :validate do
98
107
  entity.attributes.each do |attribute|
99
108
  case attribute.type
100
- when "Integer 16", "Integer 32", "Integer 64"
101
- validates_integer attribute.name
102
- when "Float", "Double", "Decimal"
103
- validates_numeric attribute.name
104
- when "String"
105
- validates_min_length attribute.minimum_value, attribute.name if attribute.minimum_value
106
- validates_max_length attribute.maximum_value, attribute.name if attribute.maximum_value
107
- end
109
+ when "Integer 16", "Integer 32", "Integer 64"
110
+ validates_integer attribute.name
111
+ when "Float", "Double", "Decimal"
112
+ validates_numeric attribute.name
113
+ when "String"
114
+ validates_min_length attribute.minimum_value, attribute.name if attribute.minimum_value
115
+ validates_max_length attribute.maximum_value, attribute.name if attribute.maximum_value
116
+ end
108
117
  end
109
118
  end
110
119
 
111
- super(klass)
120
+
121
+ super(CoreData.const_set(entity.name, klass))
112
122
  end
113
123
  end
114
124
  end
@@ -5,20 +5,24 @@ module Rack::Scaffold::Adapters
5
5
  class Sequel < Base
6
6
  extend Forwardable
7
7
 
8
- def_delegators :@klass, :count, :all, :find, :[], :create!, :update!, :destroy!
8
+ def_delegators :@klass, :count, :all, :find, :[], :update_timestamp_field
9
+ def_delegator :@klass, :create, :create!
10
+ def_delegator :@klass, :update, :update!
11
+ def_delegator :@klass, :destroy, :destroy!
9
12
 
10
13
  class << self
11
14
  def ===(model)
12
15
  ::Sequel::Model === model
13
16
  end
14
17
 
15
- def resources(model)
18
+ def resources(model, options = {})
16
19
  model
17
20
  end
21
+
18
22
  end
19
23
 
20
24
  def singular
21
- @klass.name
25
+ @klass.name.demodulize.downcase
22
26
  end
23
27
 
24
28
  def plural
@@ -28,5 +32,10 @@ module Rack::Scaffold::Adapters
28
32
  def paginate(limit, offset)
29
33
  @klass.limit(limit, offset)
30
34
  end
35
+
36
+ def timestamps?
37
+ defined?(::Sequel::Plugins::Timestamps) and @klass.plugins.include?(::Sequel::Plugins::Timestamps)
38
+ end
39
+
31
40
  end
32
41
  end
Binary file
@@ -1,6 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
- require "rack/scaffold/version"
4
3
 
5
4
  Gem::Specification.new do |s|
6
5
  s.name = "rack-scaffold"
@@ -8,7 +7,7 @@ Gem::Specification.new do |s|
8
7
  s.email = "m@mattt.me"
9
8
  s.homepage = "http://mattt.me"
10
9
  s.license = "MIT"
11
- s.version = Rack::Scaffold::VERSION
10
+ s.version = "0.0.2"
12
11
  s.platform = Gem::Platform::RUBY
13
12
  s.summary = "Rack::Scaffold"
14
13
  s.description = "Automatically generate RESTful CRUD services"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-scaffold
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mattt Thompson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-23 00:00:00.000000000 Z
11
+ date: 2013-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -106,9 +106,9 @@ files:
106
106
  - ./lib/rack/scaffold/adapters/core_data.rb
107
107
  - ./lib/rack/scaffold/adapters/sequel.rb
108
108
  - ./lib/rack/scaffold/adapters.rb
109
- - ./lib/rack/scaffold/version.rb
110
109
  - ./lib/rack/scaffold.rb
111
110
  - ./LICENSE
111
+ - ./rack-scaffold-0.0.1.gem
112
112
  - ./rack-scaffold.gemspec
113
113
  - ./Rakefile
114
114
  - ./README.md
@@ -1,5 +0,0 @@
1
- module Rack
2
- class Scaffold
3
- VERSION = "0.0.1"
4
- end
5
- end