rack-scaffold 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7ef91f24e25308a80570de00566258b1f6dd8ba3
4
- data.tar.gz: 044364fe5fca8ce8bfe21d4ca62f34201b5f2d3b
3
+ metadata.gz: 5d2030b9f5a66a76fcf8f658cf0a83ace7717130
4
+ data.tar.gz: 24a2f01f229584c7482511deb05f38aba9dfe57a
5
5
  SHA512:
6
- metadata.gz: 57c614e8c131c3f8b0aef53b3a2f5b6d4d9ea991ae251e0c4d11623f68a85398920fa5a6e5c139c08dec42bf85dc328a85887305dceb61a9208da601c737e961
7
- data.tar.gz: d2c028e14bd9dd1dc82cc1cdd5be3c216cbbcebef372c9f5c6c1fde50ba2b299bfb08e6ae97fe0db033b6a28722a9e5c311d8a4cb275f9012aafbf8cca6b54ee
6
+ metadata.gz: bc643c54ef2aabd7d762fdcae13e40a32e63bdba17dadf4b725cf1b23a04e599cba2ce95e0948f56d2b7c4249a8cca56eabd6c7caa9e732ab59ea58799078508
7
+ data.tar.gz: d07c15033d0195bdf70381e47c64ecda1fbb818e00aa5d24676014e684b215cb31d7435248c96ac7c05279c5329c490fbf413b48fcfd076dbdc93363d3f399a1
data/Gemfile CHANGED
@@ -1,3 +1,4 @@
1
+ ruby '2.0.0'
1
2
  source "https://rubygems.org"
2
3
 
3
4
  gemspec
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rack-scaffold (0.1.0)
4
+ rack-scaffold (0.2.0)
5
5
  activesupport (>= 3.0)
6
6
  rack (~> 1.4)
7
7
  rack-contrib (~> 1.1)
@@ -12,47 +12,73 @@ PATH
12
12
  GEM
13
13
  remote: https://rubygems.org/
14
14
  specs:
15
- activesupport (4.0.0)
16
- i18n (~> 0.6, >= 0.6.4)
17
- minitest (~> 4.2)
18
- multi_json (~> 1.3)
15
+ activesupport (4.1.5)
16
+ i18n (~> 0.6, >= 0.6.9)
17
+ json (~> 1.7, >= 1.7.7)
18
+ minitest (~> 5.1)
19
19
  thread_safe (~> 0.1)
20
- tzinfo (~> 0.3.37)
21
- atomic (1.1.10)
22
- backports (3.3.3)
23
- eventmachine (1.0.3)
24
- i18n (0.6.4)
25
- minitest (4.7.5)
26
- multi_json (1.7.7)
20
+ tzinfo (~> 1.1)
21
+ backports (3.6.0)
22
+ core_data (0.1.1)
23
+ nokogiri (~> 1.4)
24
+ database_cleaner (1.3.0)
25
+ diff-lcs (1.2.5)
26
+ i18n (0.6.11)
27
+ json (1.8.1)
28
+ mini_portile (0.6.0)
29
+ minitest (5.4.0)
30
+ multi_json (1.10.1)
31
+ nokogiri (1.6.3.1)
32
+ mini_portile (= 0.6.0)
27
33
  rack (1.5.2)
28
34
  rack-contrib (1.1.0)
29
35
  rack (>= 0.9.1)
30
- rack-protection (1.5.0)
36
+ rack-protection (1.5.3)
31
37
  rack
32
38
  rack-test (0.6.2)
33
39
  rack (>= 1.0)
34
- rake (10.0.4)
35
- sinatra (1.4.3)
40
+ rake (10.3.2)
41
+ rspec (3.0.0)
42
+ rspec-core (~> 3.0.0)
43
+ rspec-expectations (~> 3.0.0)
44
+ rspec-mocks (~> 3.0.0)
45
+ rspec-core (3.0.4)
46
+ rspec-support (~> 3.0.0)
47
+ rspec-expectations (3.0.4)
48
+ diff-lcs (>= 1.2.0, < 2.0)
49
+ rspec-support (~> 3.0.0)
50
+ rspec-mocks (3.0.4)
51
+ rspec-support (~> 3.0.0)
52
+ rspec-support (3.0.4)
53
+ sequel (4.13.0)
54
+ sinatra (1.4.5)
36
55
  rack (~> 1.4)
37
56
  rack-protection (~> 1.4)
38
57
  tilt (~> 1.3, >= 1.3.4)
39
- sinatra-contrib (1.4.0)
58
+ sinatra-contrib (1.4.2)
40
59
  backports (>= 2.0)
41
- eventmachine
60
+ multi_json
42
61
  rack-protection
43
62
  rack-test
44
- sinatra (~> 1.4.2)
63
+ sinatra (~> 1.4.0)
45
64
  tilt (~> 1.3)
46
65
  sinatra-param (0.1.3)
47
66
  sinatra (~> 1.3)
48
- thread_safe (0.1.2)
49
- atomic
67
+ sqlite3 (1.3.9)
68
+ thread_safe (0.3.4)
50
69
  tilt (1.4.1)
51
- tzinfo (0.3.37)
70
+ tzinfo (1.2.2)
71
+ thread_safe (~> 0.1)
52
72
 
53
73
  PLATFORMS
54
74
  ruby
55
75
 
56
76
  DEPENDENCIES
77
+ core_data
78
+ database_cleaner
57
79
  rack-scaffold!
80
+ rack-test
58
81
  rake
82
+ rspec
83
+ sequel
84
+ sqlite3
@@ -29,6 +29,9 @@ module Rack
29
29
  end
30
30
 
31
31
  disable :raise_errors, :show_exceptions
32
+ if ENV["RACK_ENV"] == "test"
33
+ set :raise_errors, true
34
+ end
32
35
 
33
36
  def last_modified_time(resource, resources)
34
37
  update_timestamp_field = resource.update_timestamp_field.to_sym
@@ -41,7 +44,7 @@ module Rack
41
44
 
42
45
  def notify!(record)
43
46
  return unless @@connections
44
-
47
+
45
48
  pathname = Pathname.new(request.path)
46
49
 
47
50
  lines = []
@@ -73,7 +76,7 @@ module Rack
73
76
  @@connections = Hash.new([])
74
77
 
75
78
  route :get, :subscribe, "/#{resource.plural}/?" do
76
- pass unless request.accept? 'text/event-stream'
79
+ pass unless request.accept.include? 'text/event-stream'
77
80
 
78
81
  content_type 'text/event-stream'
79
82
 
@@ -89,7 +92,8 @@ module Rack
89
92
 
90
93
  @app.instance_eval do
91
94
  post "/#{resource.plural}/?" do
92
- if record = resource.create!(params)
95
+ record = resource.klass.new(params)
96
+ if record.save
93
97
  status 201
94
98
  notify!(record)
95
99
  {"#{resource.singular}" => record}.to_json
@@ -142,7 +146,7 @@ module Rack
142
146
  "#{association}" => associations
143
147
  }.to_json
144
148
  end
145
- end
149
+ end
146
150
  end if @actions.include?(:read)
147
151
 
148
152
  @app.instance_eval do
@@ -12,19 +12,17 @@ module Rack::Scaffold::Adapters
12
12
 
13
13
  def resources(xcdatamodel, options = {})
14
14
  model = ::CoreData::DataModel.new(xcdatamodel)
15
- resources = model.entities.collect{|entity| resource = new(entity, options)}
16
15
  model.entities.each do |entity|
17
- resources.each do |resource|
18
- resource.establish_associations!(entity)
19
- end
16
+ self.const_set(entity.name.capitalize, Class.new(::Sequel::Model)) unless self.const_defined?(entity.name.capitalize)
20
17
  end
21
18
 
22
- return resources
19
+ model.entities.collect{|entity| new(entity, options)}
23
20
  end
24
21
  end
25
22
 
26
23
  def initialize(entity, options = {})
27
- klass = Class.new(::Sequel::Model)
24
+ adapter = self.class
25
+ klass = adapter.const_get(entity.name.capitalize)
28
26
  klass.dataset = entity.name.downcase.pluralize.to_sym
29
27
 
30
28
  klass.class_eval do
@@ -42,14 +40,31 @@ module Rack::Scaffold::Adapters
42
40
  if options[:timestamps].instance_of? Hash
43
41
  plugin :timestamps, options[:timestamps]
44
42
  else
45
- plugin :timestamps
43
+ plugin :timestamps, update_on_create: true
46
44
  end
47
45
  end
48
46
 
47
+ if options[:nested_attributes]
48
+ plugin :nested_attributes
49
+ end
50
+
49
51
  def url
50
52
  "/#{self.class.table_name}/#{self[primary_key]}"
51
53
  end
52
54
 
55
+ entity.relationships.each do |relationship|
56
+ entity_options = {class: adapter.const_get(relationship.destination.capitalize)}
57
+
58
+ if relationship.to_many?
59
+ one_to_many relationship.name.to_sym, entity_options
60
+ if options[:nested_attributes]
61
+ nested_attributes relationship.name.to_sym
62
+ end
63
+ else
64
+ many_to_one relationship.name.to_sym, options
65
+ end
66
+ end
67
+
53
68
  set_schema do
54
69
  primary_key :id
55
70
 
@@ -57,9 +72,9 @@ module Rack::Scaffold::Adapters
57
72
  next if attribute.transient?
58
73
 
59
74
  options = {
60
- :null => attribute.optional?,
61
- :index => attribute.indexed?,
62
- :default => attribute.default_value
75
+ null: attribute.optional?,
76
+ index: attribute.indexed?,
77
+ default: attribute.default_value
63
78
  }
64
79
 
65
80
  type = case attribute.type
@@ -80,8 +95,8 @@ module Rack::Scaffold::Adapters
80
95
 
81
96
  entity.relationships.each do |relationship|
82
97
  options = {
83
- :index => true,
84
- :null => relationship.optional?
98
+ index: true,
99
+ null: relationship.optional?
85
100
  }
86
101
 
87
102
  if not relationship.to_many?
@@ -116,22 +131,7 @@ module Rack::Scaffold::Adapters
116
131
  end
117
132
  end
118
133
 
119
- super(CoreData.const_set(entity.name, klass))
120
- end
121
-
122
- def establish_associations!(entity)
123
- klass.class_eval do
124
- entity.relationships.each do |relationship|
125
- options = {:class => CoreData.const_get(relationship.destination.capitalize)}
126
-
127
- options = {}
128
- if relationship.to_many?
129
- one_to_many relationship.name.to_sym, options
130
- else
131
- many_to_one relationship.name.to_sym, options
132
- end
133
- end
134
- end
134
+ super(klass)
135
135
  end
136
136
  end
137
137
  end
Binary file
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
7
7
  s.email = "m@mattt.me"
8
8
  s.homepage = "http://mattt.me"
9
9
  s.license = "MIT"
10
- s.version = "0.1.0"
10
+ s.version = "0.2.0"
11
11
  s.platform = Gem::Platform::RUBY
12
12
  s.summary = "Rack::Scaffold"
13
13
  s.description = "Automatically generate RESTful CRUD services"
@@ -20,6 +20,12 @@ Gem::Specification.new do |s|
20
20
  s.add_dependency "activesupport", ">= 3.0"
21
21
 
22
22
  s.add_development_dependency "rake"
23
+ s.add_development_dependency "rspec"
24
+ s.add_development_dependency "sequel"
25
+ s.add_development_dependency "core_data"
26
+ s.add_development_dependency "sqlite3"
27
+ s.add_development_dependency "database_cleaner"
28
+ s.add_development_dependency "rack-test"
23
29
 
24
30
  s.files = Dir["./**/*"].reject { |file| file =~ /\.\/(bin|example|log|pkg|script|spec|test|vendor)/ }
25
31
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -0,0 +1,150 @@
1
+ require "spec_helper"
2
+
3
+ describe Rack::Scaffold::Adapters::CoreData do
4
+ let(:app) { Rack::Scaffold.new(model: "./example/Example.xcdatamodeld") }
5
+ let(:adapter) { app.instance_variable_get("@adapter") }
6
+
7
+ describe "Artist" do
8
+ describe "collection" do
9
+ subject(:artists) { adapter::Artist.all }
10
+
11
+ it "is empty" do
12
+ is_expected.to be_empty
13
+ end
14
+
15
+ it "has an empty representation" do
16
+ get '/artists'
17
+ expect(last_response.status).to eq(200)
18
+ expect(last_response.body).to eq({artists: []}.to_json)
19
+ end
20
+ end
21
+
22
+ describe "record" do
23
+ let(:attributes) {
24
+ {
25
+ name: "Serge Gainsbourg",
26
+ artistDescription: "Renowned for his often provocative and scandalous releases"
27
+ }
28
+ }
29
+
30
+ before { post '/artists', attributes }
31
+ subject(:artist) { adapter::Artist.first }
32
+
33
+ it do
34
+ expect(last_response.status).to eq(201)
35
+ expect(last_response.body).to eq({artist: artist}.to_json)
36
+ end
37
+
38
+ it "is not nil" do
39
+ is_expected.not_to be_nil
40
+ end
41
+
42
+ it "has attributes in response body" do
43
+ expect(last_response.body).to eq({artist: artist}.to_json)
44
+ end
45
+
46
+ it "has the correct attributes" do
47
+ expect(artist.name).to eq(attributes[:name])
48
+ expect(artist.artistDescription).to eq(attributes[:artistDescription])
49
+ end
50
+
51
+ it "is listed with GET request" do
52
+ get '/artists'
53
+ expect(last_response.body).to eq({artists: [artist]}.to_json)
54
+ end
55
+
56
+ it "is shown with GET request" do
57
+ get '/artists/1'
58
+ expect(last_response.status).to eq(200)
59
+ expect(last_response.body).to eq({artist: artist}.to_json)
60
+ end
61
+
62
+ it "is updated with PUT request" do
63
+ name = "Lucien"
64
+ put '/artists/1', name: name
65
+ expect(last_response.status).to eq(200)
66
+ expect(adapter::Artist.first.name).to eq(name)
67
+ end
68
+
69
+ it "is updated with PATCH request" do
70
+ name = "Lucien"
71
+ patch '/artists/1', name: name
72
+ expect(last_response.status).to eq(200)
73
+ expect(adapter::Artist.first.name).to eq(name)
74
+ end
75
+
76
+ it "is deleted with DELETE request" do
77
+ delete "/artists/#{artist.id}"
78
+ expect(last_response.status).to eq(204)
79
+ expect(adapter::Artist.first(name: artist.name)).to be_nil
80
+ end
81
+ end
82
+ end
83
+
84
+ describe "Song" do
85
+ describe "collection" do
86
+ subject(:songs) { adapter::Song.all }
87
+
88
+ it "is empty" do
89
+ is_expected.to be_empty
90
+ end
91
+
92
+ it "has an empty representation" do
93
+ get '/songs'
94
+ expect(last_response.status).to eq(200)
95
+ expect(last_response.body).to eq({songs: []}.to_json)
96
+ end
97
+ end
98
+
99
+ describe "record" do
100
+ let(:artist) { adapter::Artist.create() }
101
+
102
+ let(:attributes) {
103
+ {
104
+ title: "Black Trombone",
105
+ artist_id: artist.id
106
+ }
107
+ }
108
+
109
+ before { post '/songs', attributes }
110
+ subject(:song) { adapter::Song.first }
111
+
112
+ it do
113
+ expect(last_response.status).to eq(201)
114
+ expect(last_response.body).to eq({song: song}.to_json)
115
+ end
116
+
117
+ it "is listed with GET" do
118
+ get "/artists/#{artist.id}/songs"
119
+ expect(last_response.status).to eq(200)
120
+ expect(last_response.body).to eq({songs: [song]}.to_json)
121
+ end
122
+
123
+ it "is shown with GET request" do
124
+ get "/songs/#{song.id}"
125
+ expect(last_response.status).to eq(200)
126
+ expect(last_response.body).to eq({song: song}.to_json)
127
+ end
128
+
129
+ it "is updated with PUT request" do
130
+ title = "Je T'Aime....Moi Non Plus"
131
+ put "/songs/#{song.id}", title: title
132
+ expect(last_response.status).to eq(200)
133
+ expect(adapter::Song.first.title).to eq(title)
134
+ end
135
+
136
+ it "is updated with PATCH request" do
137
+ title = "Je T'Aime....Moi Non Plus"
138
+ patch "/songs/#{song.id}", title: title
139
+ expect(last_response.status).to eq(200)
140
+ expect(adapter::Song.first.title).to eq(title)
141
+ end
142
+
143
+ it "is deleted with DELETE request" do
144
+ delete "/songs/#{song.id}"
145
+ expect(last_response.status).to eq(204)
146
+ expect(adapter::Song.first(title: song.title)).to be_nil
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,4 @@
1
+ require "spec_helper"
2
+
3
+ describe Rack::Scaffold::Adapters do
4
+ end
@@ -0,0 +1,4 @@
1
+ require "spec_helper"
2
+
3
+ describe Rack::Scaffold do
4
+ end
@@ -0,0 +1,32 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+
4
+ require "rack"
5
+ require "rack/test"
6
+ require "rspec"
7
+
8
+ require "sqlite3"
9
+ require "sequel"
10
+ require "core_data"
11
+ require "rack/scaffold"
12
+
13
+ require "database_cleaner"
14
+
15
+ DB = Sequel.sqlite
16
+
17
+ RSpec.configure do |config|
18
+ config.include Rack::Test::Methods
19
+ config.color = true
20
+
21
+ config.before(:suite) do
22
+ DatabaseCleaner.strategy = :transaction
23
+ end
24
+
25
+ config.before(:each) do
26
+ DatabaseCleaner.start
27
+ end
28
+
29
+ config.after(:each) do
30
+ DatabaseCleaner.clean
31
+ end
32
+ end
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.1.0
4
+ version: 0.2.0
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-08-28 00:00:00.000000000 Z
11
+ date: 2014-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -108,6 +108,90 @@ dependencies:
108
108
  - - '>='
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: sequel
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: core_data
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: sqlite3
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - '>='
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: database_cleaner
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - '>='
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: rack-test
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - '>='
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - '>='
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
111
195
  description: Automatically generate RESTful CRUD services
112
196
  email: m@mattt.me
113
197
  executables: []
@@ -122,9 +206,14 @@ files:
122
206
  - ./lib/rack/scaffold/adapters.rb
123
207
  - ./lib/rack/scaffold.rb
124
208
  - ./LICENSE
209
+ - ./rack-scaffold-0.2.0.gem
125
210
  - ./rack-scaffold.gemspec
126
211
  - ./Rakefile
127
212
  - ./README.md
213
+ - spec/scaffold/adapters/core_data_spec.rb
214
+ - spec/scaffold/adapters_spec.rb
215
+ - spec/scaffold_spec.rb
216
+ - spec/spec_helper.rb
128
217
  homepage: http://mattt.me
129
218
  licenses:
130
219
  - MIT
@@ -145,8 +234,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
145
234
  version: '0'
146
235
  requirements: []
147
236
  rubyforge_project:
148
- rubygems_version: 2.0.3
237
+ rubygems_version: 2.1.11
149
238
  signing_key:
150
239
  specification_version: 4
151
240
  summary: Rack::Scaffold
152
- test_files: []
241
+ test_files:
242
+ - spec/scaffold/adapters/core_data_spec.rb
243
+ - spec/scaffold/adapters_spec.rb
244
+ - spec/scaffold_spec.rb
245
+ - spec/spec_helper.rb