rest_kat 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.rvmrc ADDED
@@ -0,0 +1,2 @@
1
+ rvm ruby-1.9.2@rest_kat
2
+
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rspec", "~> 2.3.0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.6.4"
12
+ gem "rcov", ">= 0"
13
+ end
14
+
15
+ gem 'kwalify'
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 mySugr Apps OG
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,188 @@
1
+ RestKat
2
+ =======
3
+
4
+ We have all heard the mantra that REST does not require a schema because it is
5
+ just JSON. However when I found myself writing hundreds of lines of objective C
6
+ binding code with [RestKit](http://restkit.org) I thought that there must be
7
+ a better way of doing the boring bits.
8
+
9
+ Now there is RestKat.
10
+
11
+ You just have to declare your API in a YAML file using an extension to the
12
+ [kwalify](http://www.kuwata-lab.com/kwalify/) schema validator.
13
+
14
+ A schema looks like the following
15
+
16
+ configuration_type: &configuration_type
17
+ type: map
18
+ name: XXConfiguration
19
+ mapping:
20
+ name:
21
+ type: str
22
+ required: yes
23
+ email:
24
+ type: str
25
+ required: yes
26
+
27
+ log_type: &todo_type
28
+ type: map
29
+ name: XXTodo
30
+ mapping:
31
+ id:
32
+ type:int
33
+ required: yes
34
+ due:
35
+ type: str
36
+ name: NSDate
37
+ desc:
38
+ type: str
39
+ name: NSString
40
+
41
+ search_type: &search_type
42
+ type: map
43
+ name: XXTodoSearch
44
+ mapping:
45
+ desc:
46
+ type: str
47
+ required: yes
48
+
49
+
50
+
51
+
52
+ ##########################################
53
+ # REQUEST TYPES
54
+ ##########################################
55
+
56
+ # permissions and generated routes. A 's' singleton
57
+ # modifier can be added to indicate that the resource
58
+ # does not represent a collection
59
+ #
60
+ # s - singleton modifier
61
+ #
62
+ # c - POST "/resource"
63
+ # sc - invalid
64
+ #
65
+ # r - GET "/resource/:id"
66
+ # GET "/resource"
67
+ # sr - GET "/resource"
68
+ #
69
+ # u - adds PUT "/resource/:id"
70
+ # su - adds PUT "/resource"
71
+ #
72
+ # d - adds PUT "/resource/:id"
73
+ # sd - adds PUT "/resource"
74
+ #
75
+ resources:
76
+
77
+ # singletons
78
+ - name: configuration
79
+ type: *configuration_type
80
+ resource: /configuration
81
+ permissions: sru
82
+
83
+ # collections
84
+ - name: todo
85
+ type: *todo_type
86
+ resource: /todo
87
+ queries:
88
+ - name: search
89
+ type: *search_type
90
+ permissions: crud
91
+
92
+ The resources section defines the RESTful resources and
93
+ thier methods. The type of each resource refers to types
94
+ defined further up the file. The name of each type must
95
+ refer to the desired objective C class name for each
96
+ type.
97
+
98
+ Resources can be interfaced with through the generated
99
+ subclasses via this interface.
100
+
101
+ @interface MSRestSerializableResource : MSRestSerializable
102
+
103
+ #pragma mark methods to be overridden
104
+
105
+ + (Class) classForResource;
106
+
107
+ // The resource path. If this
108
+ + (NSString *) resourcePath;
109
+
110
+ // Is the resource a singleton or a collection
111
+ + (bool) isSingleton;
112
+
113
+ // Can the client create resources
114
+ + (bool) canCreate;
115
+
116
+ // Can the client read resources
117
+ + (bool) canRead;
118
+
119
+ // Can the client update resources
120
+ + (bool) canUpdate;
121
+
122
+ // Can the client delete resources
123
+ + (bool) canDelete;
124
+
125
+ #pragma mark helpers
126
+
127
+ // The router for this class
128
+ + (RKObjectRouter *) router;
129
+
130
+ // Intialize the routing module. Must
131
+ // be called from +initialize in a
132
+ // subclass or the logic will not
133
+ // work.
134
+ + (void) initializeRouting;
135
+
136
+
137
+ // save the object
138
+ -(void) saveWithDelegate:(id<RKObjectLoaderDelegate>)delegate;
139
+
140
+ // Find an instance by id
141
+ + (void) find:(NSNumber *)id
142
+ withDelegate:(id<RKObjectLoaderDelegate>)delegate;
143
+
144
+ // Load collection
145
+ + (void) loadCollectionWithDelegate:(id<RKObjectLoaderDelegate>)delegate;
146
+
147
+ // Load collection with query
148
+ + (void) loadCollectionThroughQuery:(MSRestSerializable *)mappableQueryObject
149
+ withDelegate:(id<RKObjectLoaderDelegate>)delegate;
150
+
151
+ @end
152
+
153
+ Standard types of int, float, str are mapped to
154
+ NSNumber, NSNumber and NSString respectively unless
155
+ a specialized class is given.
156
+
157
+ There is a helper for your custom rake task to do
158
+ the building of the source code for you. For example
159
+ you could do
160
+
161
+ require 'rest_kat'
162
+
163
+ namespace :iphone do
164
+ namespace :api do
165
+ ApiLocation = File.expand_path "src/AutoGen", __FILE__
166
+ SchemaLocation = File.expand_path "api_schema.yml", __FILE__
167
+
168
+ task :_generate => RestKat::generate_api(ApiLocation, SchemaLocation)
169
+
170
+ desc "Generate iPhone API to #{ApiLocation}"
171
+ task :generate => :_generate
172
+ end
173
+ end
174
+
175
+ The class heirarchy for the generated classes is
176
+
177
+ MSRestSerializable
178
+ ^
179
+ |
180
+ MSRestSerializableResource
181
+
182
+ All types that are also are resource derive from MSRestSerializableResource
183
+ and all helper or nested types derive from MSRestSerializable.
184
+
185
+ Refer to MSRestSerializable.h for more details and the [restKit documentation](http://restkit.org)
186
+
187
+
188
+
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = rest_kat
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to rest_kat
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
+ * Fork the project
10
+ * Start a feature/bugfix branch
11
+ * Commit and push until you are happy with your contribution
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2011 mySugr Apps OG. See LICENSE.txt for
18
+ further details.
19
+
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "rest_kat"
18
+ gem.homepage = "http://github.com/mysugr/rest_kat"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Generate objective C RestKit boilerplate code from a yaml schema}
21
+ gem.description = %Q{The generated source code is a layer on top of the iOS REST framework http://restkit.org/}
22
+ gem.email = "brad.phelan@mysugr.com"
23
+ gem.authors = ["Brad Phelan"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ task :default => :spec
40
+
41
+ require 'rake/rdoctask'
42
+ Rake::RDocTask.new do |rdoc|
43
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = "rest_kat #{version}"
47
+ rdoc.rdoc_files.include('README*')
48
+ rdoc.rdoc_files.include('lib/**/*.rb')
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.4
data/lib/model.h.erb ADDED
@@ -0,0 +1,60 @@
1
+ #import <Foundation/Foundation.h>
2
+ #import <RestKit/Restkit.h>
3
+ #import "MSRestSerializable.h"
4
+
5
+ <%classes.each do |klass|%>
6
+ <%if klass.resource%>
7
+ //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
8
+ //@@
9
+ //@@ Resource Name
10
+ //@@
11
+ //@@ <%= klass.resource.hash[:name] %>
12
+ //@@
13
+ //@@ Resource Type
14
+ //@@
15
+ //@@ <%= klass.resource.hash[:type][:name] %>
16
+ //@@
17
+ //@@ Resource Path
18
+ //@@ <%= klass.resource.hash[:resource] %>
19
+ //@@
20
+ //@@ Permissions:
21
+ //@@
22
+ //@@ Singleton: <%= klass.resource.c_permission_for 's' %>
23
+ //@@ Create : <%= klass.resource.c_permission_for 'c' %>
24
+ //@@ Read : <%= klass.resource.c_permission_for 'r' %>
25
+ //@@ Update : <%= klass.resource.c_permission_for 'u' %>
26
+ //@@ Delete : <%= klass.resource.c_permission_for 'd' %>
27
+ //@@
28
+ //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
29
+ <%else%>
30
+ //////////////////////////////////////////////////////////////////////////////
31
+ //// <%= klass.objc_class %>
32
+ //////////////////////////////////////////////////////////////////////////////
33
+ <%end%>
34
+ @interface <%= klass.objc_class %> : <%= klass.objc_super_class %>
35
+ <%klass.properties.each do |property|%>
36
+ <%if property.klass.seq? %>
37
+ // <%=property.name%> : <%=property.klass.json_type%> of <%=property.klass.sequence_of.objc_class%>
38
+ <%else%>
39
+ // <%=property.name%> : <%=property.klass.json_type%>
40
+ <%end%>
41
+ <%if property.klass.enum?%>
42
+ // Enumeration of
43
+ <%property.klass.enum.each do |e|%>
44
+ // - <%=e%>
45
+ <%end%>
46
+ <%end%>
47
+ <%=property.klass.objc_property_decl property.name%>;
48
+ <%end%>
49
+
50
+ // Initialize all the methods. Called by +initialize ( don't call manually )
51
+ + (void)initializeMapping;
52
+
53
+ // Static initializer ( don't call manually )
54
+ + (void)initialize;
55
+
56
+ // <%= klass.objc_class %> convenience builder.
57
+ + (<%=klass.objc_class%> *)buildWith_<%=klass.objc_properites_arg_list_decl%>;
58
+ @end
59
+
60
+ <%end%>
data/lib/model.m.erb ADDED
@@ -0,0 +1,115 @@
1
+ #import "<%=header%>"
2
+
3
+ <%classes.each do |klass|%>
4
+ //////////////////////////////////////////////////////////////////////////////
5
+ //// <%= klass.objc_class %>
6
+ //////////////////////////////////////////////////////////////////////////////
7
+ @implementation <%= klass.objc_class %>
8
+
9
+ <%klass.properties.each do |property|%>
10
+ @synthesize <%= property.name %>;
11
+ <%end%>
12
+
13
+ + (void)initialize{
14
+ <%if klass.resource%>
15
+ [self initializeRouting];
16
+ <%end%>
17
+ [self initializeMapping];
18
+ }
19
+
20
+ + (void)initializeMapping{
21
+ RKObjectMapping* mapping = [RKObjectMapping mappingForClass:[<%=klass.objc_class%> class]];
22
+
23
+ // -------------------------------------------
24
+ // Define the properties mappings
25
+ <%klass.properties.each do |property|%> <%if not property.klass.complex? %>
26
+ [mapping mapKeyPath:@"<%=property.name%>" toAttribute:@"<%=property.name%>"];
27
+ <%end%> <%end%>
28
+
29
+ // -------------------------------------------
30
+ // Define the relationship mappings
31
+ <%klass.properties.each do |property|%>
32
+ <%if property.klass.complex? %>
33
+ {
34
+ <%if property.klass.map?%>
35
+ RKObjectMapping * mapper = [[RKObjectManager sharedManager].mappingProvider objectMappingForClass:[<%=property.klass.objc_class%> class]];
36
+ [mapping hasOne:@"<%=property.name%>" withMapping:mapper];
37
+ <%elsif property.klass.seq?%>
38
+ RKObjectMapping * mapper = [[RKObjectManager sharedManager].mappingProvider objectMappingForClass:[<%=property.klass.sequence_of.objc_class%> class]];
39
+ [mapping hasMany:@"<%=property.name%>" withMapping:mapper];
40
+ <%end%>
41
+ }
42
+ <%end%>
43
+ <%end%>
44
+
45
+ // -------------------------------------------
46
+ // Register the mapper for the class
47
+ [[RKObjectManager sharedManager].mappingProvider addObjectMapping:mapping];
48
+
49
+ // -------------------------------------------
50
+ // Register the serializer for the class
51
+ [[RKObjectManager sharedManager].mappingProvider setSerializationMapping:[mapping inverseMapping] forClass:[<%=klass.objc_class%> class] ];
52
+ }
53
+
54
+ <%if klass.resource%>
55
+ + (NSString *) resourcePath {
56
+ return @"<%= klass.resource.hash[:resource] %>";
57
+ }
58
+
59
+
60
+ + (Class) classForResource{
61
+ return [ <%=klass.resource.objc_resource_type%> class];
62
+ }
63
+
64
+ + (bool)isSingleton
65
+ {
66
+ return <%=klass.resource.c_permission_for 's'%>;
67
+ }
68
+
69
+ + (bool)canCreate
70
+ {
71
+ return <%=klass.resource.c_permission_for 'c'%>;
72
+ }
73
+
74
+ + (bool)canRead
75
+ {
76
+ return <%=klass.resource.c_permission_for 'r'%>;
77
+ }
78
+
79
+ + (bool)canUpdate
80
+ {
81
+ return <%=klass.resource.c_permission_for 'u'%>;
82
+ }
83
+
84
+ + (bool)canDelete
85
+ {
86
+ return <%=klass.resource.c_permission_for 'd'%>;
87
+ }
88
+ <%end%>
89
+
90
+ // <%=klass.objc_class%> convenience builder.
91
+ // Note that +id+ field if present is not set by this
92
+ // builder and so can be used to construct a *new* object
93
+ + (<%=klass.objc_class%> *)buildWith_<%=klass.objc_properites_arg_list_decl%>
94
+ {
95
+ <%=klass.objc_class%> * object = [[<%=klass.objc_class%> alloc] init];
96
+ <%klass.properties.reject{|p|p.name=='id'}.each do |property|%>
97
+ object.<%=property.name%> = <%=property.name%>;
98
+ <%end%>
99
+ return object;
100
+ }
101
+
102
+
103
+ // Deep Copy
104
+ - (id) copyWithZone : (NSZone * ) zone
105
+ {
106
+ <%=klass.objc_class%> * object = [[<%=klass.objc_class%> allocWithZone:zone] init];
107
+ <%klass.properties.each do |property|%>
108
+ object.<%=property.name%> = [self.<%=property.name%> copy];
109
+ <%end%>
110
+ return object;
111
+ }
112
+
113
+ @end
114
+
115
+ <%end%>