ruby_odata 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.gitignore +9 -0
  2. data/LICENSE +24 -0
  3. data/README.rdoc +107 -0
  4. data/Rakefile +28 -0
  5. data/VERSION +1 -0
  6. data/config/cucumber.yml +7 -0
  7. data/doc/classes/OData/ClassBuilder.html +219 -0
  8. data/doc/classes/OData/Operation.html +194 -0
  9. data/doc/classes/OData/QueryBuilder.html +305 -0
  10. data/doc/classes/OData/Service.html +420 -0
  11. data/doc/classes/OData.html +126 -0
  12. data/doc/created.rid +1 -0
  13. data/doc/files/README_rdoc.html +252 -0
  14. data/doc/files/lib/odata_ruby/class_builder_rb.html +101 -0
  15. data/doc/files/lib/odata_ruby/operation_rb.html +101 -0
  16. data/doc/files/lib/odata_ruby/query_builder_rb.html +101 -0
  17. data/doc/files/lib/odata_ruby/service_rb.html +101 -0
  18. data/doc/files/lib/odata_ruby_rb.html +114 -0
  19. data/doc/fr_class_index.html +31 -0
  20. data/doc/fr_file_index.html +32 -0
  21. data/doc/fr_method_index.html +40 -0
  22. data/doc/index.html +24 -0
  23. data/doc/rdoc-style.css +208 -0
  24. data/features/service.feature +82 -0
  25. data/features/service_manage.feature +44 -0
  26. data/features/step_definitions/service_steps.rb +132 -0
  27. data/features/support/env.rb +4 -0
  28. data/features/support/hooks.rb +4 -0
  29. data/lib/odata_ruby/class_builder.rb +84 -0
  30. data/lib/odata_ruby/operation.rb +18 -0
  31. data/lib/odata_ruby/query_builder.rb +63 -0
  32. data/lib/odata_ruby/service.rb +207 -0
  33. data/lib/odata_ruby.rb +15 -0
  34. data/ruby_odata.gemspec +94 -0
  35. data/test/Cassini x64.bat +1 -0
  36. data/test/Cassini x86.bat +1 -0
  37. data/test/SampleService/App_Code/Entities.cs +39 -0
  38. data/test/SampleService/App_Code/Model.Designer.cs +414 -0
  39. data/test/SampleService/App_Code/Model.edmx +140 -0
  40. data/test/SampleService/App_Data/_TestDB.mdf +0 -0
  41. data/test/SampleService/App_Data/_TestDB_Log.ldf +0 -0
  42. data/test/SampleService/Entities.svc +1 -0
  43. data/test/SampleService/web.config +27 -0
  44. data/test/blueprints.rb +16 -0
  45. metadata +158 -0
@@ -0,0 +1,132 @@
1
+ Given /^an ODataService exists with uri: "([^\"]*)"$/ do |uri|
2
+ @service = OData::Service.new(uri)
3
+ end
4
+
5
+ When /^I call "([^\"]*)" on the service$/ do |method|
6
+ @service_query = @service.send(method)
7
+ end
8
+
9
+ Then /^the result should be "([^\"]*)"$/ do |result|
10
+ @service_result.should == result
11
+ end
12
+
13
+ Then /^I should be able to call "([^\"]*)" on the service$/ do |method|
14
+ lambda { @service.send(method) }.should_not raise_error
15
+ end
16
+
17
+ Then /^I should not be able to call "([^\"]*)" on the service$/ do |method|
18
+ lambda { @service.send(method) }.should raise_error
19
+ end
20
+
21
+ Then /^I should be able to call "([^\"]*)" on the service with args: "([^\"]*)"$/ do |method, args|
22
+ lambda { @service.send(method, args) }.should_not raise_error
23
+ end
24
+
25
+ When /^I call "([^\"]*)" on the service with args: "([^\"]*)"$/ do |method, args|
26
+ @service_query = @service.send(method, args)
27
+ end
28
+
29
+ When /^I run the query$/ do
30
+ @service_result = @service.execute
31
+ end
32
+
33
+ Then /^the result should be of type "([^\"]*)"$/ do |type|
34
+ @service_result.class.to_s.should == type
35
+ end
36
+
37
+ Then /^the result should have a method: "([^\"]*)"$/ do |method|
38
+ @service_result.respond_to?(method.to_sym).should == true
39
+ end
40
+
41
+ Then /^the method "([^\"]*)" on the result should equal: "([^\"]*)"$/ do |method, value|
42
+ @service_result.send(method.to_sym).should == value
43
+ end
44
+
45
+ Then /^the method "([^\"]*)" on the result should be nil$/ do |method|
46
+ @service_result.send(method.to_sym).should == nil
47
+ end
48
+
49
+ When /^I set "([^\"]*)" on the result to "([^\"]*)"$/ do |property_name, value|
50
+ @service_result.send("#{property_name}=", value)
51
+ end
52
+
53
+ Given /^I expand the query to include "([^\"]*)"$/ do |expands|
54
+ @service_query.expand(expands)
55
+ end
56
+
57
+ When /^I filter the query with: "([^\"]*)"$/ do |filter|
58
+ @service_query.filter(filter)
59
+ end
60
+
61
+
62
+ Then /^the method "([^\"]*)" on the result should be of type "([^\"]*)"$/ do |method, type|
63
+ result = @service_result.send(method.to_sym)
64
+ result.class.to_s.should == type
65
+ end
66
+
67
+ Given /^I call "([^\"]*)" on the service with a new "([^\"]*)" object(?: with (.*))?$/ do |method, object, fields|
68
+ fields_hash = {}
69
+
70
+ if !fields.nil?
71
+ fields.split(', ').each do |field|
72
+ if field =~ /^(?:(\w+): "(.*)")$/
73
+ key = $1
74
+ val = $2
75
+ if val =~ /^@@LastSave$/
76
+ val = @saved_result
77
+ end
78
+
79
+ fields_hash.merge!({ key => val })
80
+ else
81
+ end
82
+ end
83
+ end
84
+
85
+ obj = object.constantize.send(:make, fields_hash)
86
+ @service.send(method.to_sym, obj)
87
+ end
88
+
89
+ When /^I save changes$/ do
90
+ @saved_result = @service.save_changes
91
+ end
92
+
93
+ Then /^the save result should be of type "([^\"]*)"$/ do |type|
94
+ @saved_result.class.to_s.should == type
95
+ end
96
+
97
+ When /^I call "([^\"]*)" on the service with the last save result$/ do |method|
98
+ @service.send(method.to_sym, @saved_result)
99
+ end
100
+
101
+ When /^I call "([^\"]*)" on the service with the last query result$/ do |method|
102
+ @service.send(method.to_sym, @service_result)
103
+ end
104
+
105
+ Then /^the save result should equal: "([^\"]*)"$/ do |result|
106
+ @saved_result.to_s.should == result
107
+ end
108
+
109
+ Then /^the method "([^\"]*)" on the save result should equal: "([^\"]*)"$/ do |method, value|
110
+ result = @saved_result.send(method.to_sym)
111
+ result.should == value
112
+ end
113
+
114
+ When /^blueprints exist for the service$/ do
115
+ require File.expand_path(File.dirname(__FILE__) + "../../../test/blueprints")
116
+ end
117
+
118
+ Given /^I call "([^\"]*)" on the service with a new "([^\"]*)" object it should throw an exception with message "([^\"]*)"$/ do |method, object, msg|
119
+ obj = object.constantize.send :make
120
+ lambda { @service.send(method.to_sym, obj) }.should raise_error(msg)
121
+ end
122
+
123
+ Then /^no "([^\"]*)" should exist$/ do |collection|
124
+ @service.send(collection)
125
+ results = @service.execute
126
+ results.should == []
127
+ end
128
+
129
+ Then /^the method "([^\"]*)" on the result's method "([^\"]*)" should equal: "([^\"]*)"$/ do |method, result_method, value|
130
+ obj = @service_result.send(result_method.to_sym)
131
+ obj.send(method.to_sym).should == value
132
+ end
@@ -0,0 +1,4 @@
1
+ require 'lib/odata_ruby'
2
+ require 'machinist/object'
3
+ require 'sham'
4
+ require 'faker'
@@ -0,0 +1,4 @@
1
+ Before do
2
+ Sham.reset
3
+ RestClient.post "http://localhost:8888/SampleService/Entities.svc/CleanDatabaseForTesting", {}
4
+ end
@@ -0,0 +1,84 @@
1
+ module OData
2
+ # Internally used helper class for building a dynamic class. This class shouldn't be called directly.
3
+ class ClassBuilder
4
+ # Creates a new instance of the ClassBuilder class
5
+ #
6
+ # ==== Required Attributes
7
+ # - klass_name: The name/type of the class to create
8
+ # - methods: The accessor methods to add to the class
9
+ # - nav_props: The accessor methods to add for navigation properties
10
+ def initialize(klass_name, methods, nav_props)
11
+ @klass_name = klass_name
12
+ @methods = methods
13
+ @nav_props = nav_props
14
+ end
15
+
16
+ # Returns a dynamically generated class definition based on the constructor parameters
17
+ def build
18
+ # return if already built
19
+ return @klass unless @klass.nil?
20
+
21
+ # need the class name to build class
22
+ return nil if @klass_name.nil?
23
+
24
+ # return if we can find constant corresponding to class name
25
+ if Object.constants.include? @klass_name
26
+ @klass = @klass_name.constantize
27
+ return @klass
28
+ end
29
+
30
+ Object.const_set(@klass_name, Class.new.extend(ActiveSupport::JSON))
31
+ @klass = @klass_name.constantize
32
+
33
+ add_methods(@klass)
34
+ add_nav_props(@klass)
35
+
36
+ return @klass
37
+ end
38
+
39
+ private
40
+ def add_methods(klass)
41
+ # Add metadata methods
42
+ klass.send :define_method, :__metadata do
43
+ instance_variable_get("@__metadata")
44
+ end
45
+ klass.send :define_method, :__metadata= do |value|
46
+ instance_variable_set("@__metadata", value)
47
+ end
48
+ klass.send :define_method, :as_json do |options|
49
+ meta = '__metadata'
50
+ vars = self.instance_values
51
+
52
+ if !options.nil? && !options[:seen].nil? && vars.has_key?(meta)
53
+ vars.delete_if { |k,v| k != meta}
54
+ else
55
+ vars.delete(meta)
56
+ end
57
+
58
+ vars
59
+ end
60
+
61
+
62
+ # Add the methods that were passed in
63
+ @methods.each do |method_name|
64
+ klass.send :define_method, method_name do
65
+ instance_variable_get("@#{method_name}")
66
+ end
67
+ klass.send :define_method, "#{method_name}=" do |value|
68
+ instance_variable_set("@#{method_name}", value)
69
+ end
70
+ end
71
+ end
72
+
73
+ def add_nav_props(klass)
74
+ @nav_props.each do |method_name|
75
+ klass.send :define_method, method_name do
76
+ instance_variable_get("@#{method_name}")
77
+ end
78
+ klass.send :define_method, "#{method_name}=" do |value|
79
+ instance_variable_set("@#{method_name}", value)
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end # module OData
@@ -0,0 +1,18 @@
1
+ module OData
2
+ # Internally used helper class for storing operations called against the service. This class shouldn't be used directly.
3
+ class Operation
4
+ attr_accessor :kind, :klass_name, :klass
5
+
6
+ # Creates a new instance of the Operation class
7
+ #
8
+ # ==== Required Attributes
9
+ # - kind: The operation type (Add, Update, or Delete)
10
+ # - klass_name: The name/type of the class to operate against
11
+ # - klass: The actual class
12
+ def initialize(kind, klass_name, klass)
13
+ @kind = kind
14
+ @klass_name = klass_name
15
+ @klass = klass
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,63 @@
1
+ module OData
2
+ # The query builder is used to call query operations against the service. This shouldn't be called directly, but rather it is returned from the dynamic methods created for the specific service that you are calling.
3
+ #
4
+ # For example, given the following code snippet:
5
+ # svc = OData::Service.new "http://127.0.0.1:8888/SampleService/Entities.svc"
6
+ # svc.Categories
7
+ # The *Categories* method would return a QueryBuilder
8
+ class QueryBuilder
9
+ # Creates a new instance of the QueryBuilder class
10
+ #
11
+ # ==== Required Attributes
12
+ # - root: The root entity collection to query against
13
+ def initialize(root)
14
+ @root = root.to_s
15
+ @expands = []
16
+ @filters = []
17
+ end
18
+
19
+ # Used to eagerly-load data for nested objects, for example, obtaining a Category for a Product within one call to the server
20
+ # ==== Required Attributes
21
+ # - path: The path of the entity to expand relative to the root
22
+ #
23
+ # ==== Example
24
+ # # Without expanding the query (no Category will be filled in for the Product)
25
+ # svc.Products(1)
26
+ # prod1 = svc.execute
27
+ #
28
+ # # With expanding the query (the Category will be filled in)
29
+ # svc.Products(1).expand('Category')
30
+ # prod1 = svc.execute
31
+ def expand(path)
32
+ @expands << path
33
+ self
34
+ end
35
+
36
+ # Used to filter data being returned
37
+ # ==== Required Attributes
38
+ # - filter: The path of the entity to expand relative to the root
39
+ #
40
+ # ==== Example
41
+ # svc.Products.filter("Name eq 'Product 2'")
42
+ # prod = svc.execute
43
+ def filter(filter)
44
+ @filters << CGI.escape(filter)
45
+ self
46
+ end
47
+
48
+ # Builds the query URI (path, not including root) incorporating expands, filters, etc.
49
+ # This is used internally when the execute method is called on the service
50
+ def query
51
+ q = @root.clone
52
+ query_options = []
53
+ query_options << "$expand=#{@expands.join(',')}" unless @expands.empty?
54
+ query_options << "$filter=#{@filters.join('+and+')}" unless @filters.empty?
55
+ if !query_options.empty?
56
+ q << "?"
57
+ q << query_options.join('&')
58
+ end
59
+ return q
60
+ end
61
+ end
62
+
63
+ end # Module
@@ -0,0 +1,207 @@
1
+ module OData
2
+
3
+ class Service
4
+ attr_reader :classes
5
+ # Creates a new instance of the Service class
6
+ #
7
+ # ==== Required Attributes
8
+ # - service_uri: The root URI of the OData service
9
+ def initialize(service_uri)
10
+ @uri = service_uri
11
+ @collections = get_collections
12
+ build_classes
13
+ end
14
+
15
+ # Handles the dynamic AddTo<EntityName> methods as well as the collections on the service
16
+ def method_missing(name, *args)
17
+ # Queries
18
+ if @collections.include?(name.to_s)
19
+ root = "/#{name.to_s.camelize}"
20
+ root << "(#{args.join(',')})" unless args.empty?
21
+ @query = QueryBuilder.new(root)
22
+ return @query
23
+ # Adds
24
+ elsif name.to_s =~ /^AddTo(.*)/
25
+ type = $1
26
+ if @collections.include?(type)
27
+ @save_operation = Operation.new("Add", $1, args[0])
28
+ else
29
+ super
30
+ end
31
+ else
32
+ super
33
+ end
34
+
35
+ end
36
+
37
+ # Queues an object for deletion. To actually remove it from the server, you must call save_changes as well.
38
+ #
39
+ # ==== Required Attributes
40
+ # - obj: The object to mark for deletion
41
+ #
42
+ # Note: This method will throw an exception if the +obj+ isn't a tracked entity
43
+ def delete_object(obj)
44
+ type = obj.class.to_s
45
+ if obj.respond_to?(:__metadata) && !obj.send(:__metadata).nil?
46
+ @save_operation = Operation.new("Delete", type, obj)
47
+ else
48
+ raise "You cannot delete a non-tracked entity"
49
+ end
50
+ end
51
+
52
+ # Queues an object for update. To actually update it on the server, you must call save_changes as well.
53
+ #
54
+ # ==== Required Attributes
55
+ # - obj: The object to queue for update
56
+ #
57
+ # Note: This method will throw an exception if the +obj+ isn't a tracked entity
58
+ def update_object(obj)
59
+ type = obj.class.to_s
60
+ if obj.respond_to?(:__metadata) && !obj.send(:__metadata).nil?
61
+ @save_operation = Operation.new("Update", type, obj)
62
+ else
63
+ raise "You cannot update a non-tracked entity"
64
+ end
65
+ end
66
+
67
+ # Performs save operations (Create/Update/Delete) against the server
68
+ def save_changes
69
+ return nil if @save_operation.nil?
70
+
71
+ result = nil
72
+
73
+ if @save_operation.kind == "Add"
74
+ save_uri = "#{@uri}/#{@save_operation.klass_name}"
75
+ json_klass = @save_operation.klass.to_json
76
+ post_result = RestClient.post save_uri, json_klass, :content_type => :json
77
+ result = build_classes_from_result(post_result)
78
+ elsif @save_operation.kind == "Update"
79
+ update_uri = @save_operation.klass.send(:__metadata)[:uri]
80
+ json_klass = @save_operation.klass.to_json
81
+ update_result = RestClient.put update_uri, json_klass, :content_type => :json
82
+ return (update_result.code == 204)
83
+ elsif @save_operation.kind == "Delete"
84
+ delete_uri = @save_operation.klass.send(:__metadata)[:uri]
85
+ delete_result = RestClient.delete delete_uri
86
+ return (delete_result.code == 204)
87
+ end
88
+
89
+ @save_operation = nil # Clear out the last operation
90
+ return result
91
+ end
92
+
93
+ # Performs query operations (Read) against the server
94
+ def execute
95
+ result = RestClient.get build_query_uri
96
+ build_classes_from_result(result)
97
+ end
98
+
99
+ # Overridden to identify methods handled by method_missing
100
+ def respond_to?(method)
101
+ if @collections.include?(method.to_s)
102
+ return true
103
+ # Adds
104
+ elsif method.to_s =~ /^AddTo(.*)/
105
+ type = $1
106
+ if @collections.include?(type)
107
+ return true
108
+ else
109
+ super
110
+ end
111
+ else
112
+ super
113
+ end
114
+ end
115
+
116
+ private
117
+ def get_collections
118
+ doc = Nokogiri::XML(open(@uri))
119
+ collections = doc.xpath("//app:collection", "app" => "http://www.w3.org/2007/app")
120
+ collections.collect { |c| c["href"] }
121
+ end
122
+ def build_classes
123
+ @classes = Hash.new
124
+ doc = Nokogiri::XML(open("#{@uri}/$metadata"))
125
+
126
+ # Get the edm namespace
127
+ edm_ns = doc.xpath("edmx:Edmx/edmx:DataServices/*", "edmx" => "http://schemas.microsoft.com/ado/2007/06/edmx").first.namespaces['xmlns'].to_s
128
+
129
+ entity_types = doc.xpath("//edm:EntityType", "edm" => edm_ns)
130
+ entity_types.each do |e|
131
+ name = e['Name']
132
+ props = e.xpath(".//edm:Property", "edm" => edm_ns)
133
+ methods = props.collect { |p| p['Name'] } # Standard Properties
134
+ nprops = e.xpath(".//edm:NavigationProperty", "edm" => edm_ns)
135
+ nav_props = nprops.collect { |p| p['Name'] } # Standard Properties
136
+ @classes[name] = ClassBuilder.new(name, methods, nav_props).build unless @classes.keys.include?(name)
137
+ end
138
+ end
139
+ def build_classes_from_result(result)
140
+ doc = Nokogiri::XML(result)
141
+ entries = doc.xpath("//atom:entry[not(ancestor::atom:entry)]", "atom" => "http://www.w3.org/2005/Atom")
142
+ return entry_to_class(entries[0]) if entries.length == 1
143
+
144
+ results = []
145
+ entries.each do |entry|
146
+ results << entry_to_class(entry)
147
+ end
148
+ return results
149
+ end
150
+ def entry_to_class(entry)
151
+ # Retrieve the class name from the fully qualified name (the last string after the last dot)
152
+ klass_name = entry.xpath("./atom:category/@term", "atom" => "http://www.w3.org/2005/Atom").to_s.split('.')[-1]
153
+ return nil if klass_name.empty?
154
+
155
+ properties = entry.xpath(".//m:properties/*", { "m" => "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" })
156
+
157
+ klass = @classes[klass_name].new
158
+
159
+ # Fill metadata
160
+ meta_id = entry.xpath("./atom:id", "atom" => "http://www.w3.org/2005/Atom")[0].content
161
+ klass.send :__metadata=, { :uri => meta_id }
162
+
163
+ # Fill properties
164
+ for prop in properties
165
+ prop_name = prop.name
166
+ # puts "#{prop_name} - #{prop.content}"
167
+ klass.send "#{prop_name}=", prop.content
168
+ end
169
+
170
+ inline_links = entry.xpath("./atom:link[m:inline]", { "m" => "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata", "atom" => "http://www.w3.org/2005/Atom" })
171
+
172
+ for link in inline_links
173
+ inline_entries = link.xpath(".//atom:entry", "atom" => "http://www.w3.org/2005/Atom")
174
+
175
+ if inline_entries.length == 1
176
+ property_name = link.attributes['title'].to_s
177
+
178
+ build_inline_class(klass, inline_entries[0], property_name)
179
+ else
180
+ # TODO: Test handling multiple children
181
+ for inline_entry in inline_entries
182
+ property_name = link.xpath("atom:link[@rel='edit']/@title", "atom" => "http://www.w3.org/2005/Atom")
183
+
184
+ # Build the class
185
+ inline_klass = entry_to_class(inline_entry)
186
+
187
+ # Add the property
188
+ klass.send "#{property_name}=", inline_klass
189
+ end
190
+ end
191
+ end
192
+
193
+ return klass
194
+ end
195
+ def build_query_uri
196
+ "#{@uri}#{@query.query}"
197
+ end
198
+ def build_inline_class(klass, entry, property_name)
199
+ # Build the class
200
+ inline_klass = entry_to_class(entry)
201
+
202
+ # Add the property
203
+ klass.send "#{property_name}=", inline_klass
204
+ end
205
+ end
206
+
207
+ end # module OData
data/lib/odata_ruby.rb ADDED
@@ -0,0 +1,15 @@
1
+ lib = File.dirname(__FILE__)
2
+ $: << lib + '/odata_ruby/'
3
+
4
+ require 'rubygems'
5
+ require 'active_support' # Used for serializtion to JSON
6
+ require 'active_support/inflector'
7
+ require 'cgi'
8
+ require 'open-uri'
9
+ require 'rest_client'
10
+ require 'nokogiri'
11
+
12
+ require lib + '/odata_ruby/query_builder'
13
+ require lib + '/odata_ruby/class_builder'
14
+ require lib + '/odata_ruby/operation'
15
+ require lib + '/odata_ruby/service'
@@ -0,0 +1,94 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{ruby_odata}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Damien White"]
12
+ s.date = %q{2010-06-11}
13
+ s.description = %q{An OData Client Library for Ruby. Use this to interact with OData services}
14
+ s.email = %q{damien.white@visoftinc.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "LICENSE",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "config/cucumber.yml",
26
+ "doc/classes/OData.html",
27
+ "doc/classes/OData/ClassBuilder.html",
28
+ "doc/classes/OData/Operation.html",
29
+ "doc/classes/OData/QueryBuilder.html",
30
+ "doc/classes/OData/Service.html",
31
+ "doc/created.rid",
32
+ "doc/files/README_rdoc.html",
33
+ "doc/files/lib/odata_ruby/class_builder_rb.html",
34
+ "doc/files/lib/odata_ruby/operation_rb.html",
35
+ "doc/files/lib/odata_ruby/query_builder_rb.html",
36
+ "doc/files/lib/odata_ruby/service_rb.html",
37
+ "doc/files/lib/odata_ruby_rb.html",
38
+ "doc/fr_class_index.html",
39
+ "doc/fr_file_index.html",
40
+ "doc/fr_method_index.html",
41
+ "doc/index.html",
42
+ "doc/rdoc-style.css",
43
+ "features/service.feature",
44
+ "features/service_manage.feature",
45
+ "features/step_definitions/service_steps.rb",
46
+ "features/support/env.rb",
47
+ "features/support/hooks.rb",
48
+ "lib/odata_ruby.rb",
49
+ "lib/odata_ruby/class_builder.rb",
50
+ "lib/odata_ruby/operation.rb",
51
+ "lib/odata_ruby/query_builder.rb",
52
+ "lib/odata_ruby/service.rb",
53
+ "ruby_odata.gemspec",
54
+ "test/Cassini x64.bat",
55
+ "test/Cassini x86.bat",
56
+ "test/SampleService/App_Code/Entities.cs",
57
+ "test/SampleService/App_Code/Model.Designer.cs",
58
+ "test/SampleService/App_Code/Model.edmx",
59
+ "test/SampleService/App_Data/_TestDB.mdf",
60
+ "test/SampleService/App_Data/_TestDB_Log.ldf",
61
+ "test/SampleService/Entities.svc",
62
+ "test/SampleService/web.config",
63
+ "test/blueprints.rb"
64
+ ]
65
+ s.homepage = %q{http://github.com/visoft/ruby_odata}
66
+ s.rdoc_options = ["--charset=UTF-8"]
67
+ s.require_paths = ["lib"]
68
+ s.rubyforge_project = %q{ruby-odata}
69
+ s.rubygems_version = %q{1.3.7}
70
+ s.summary = %q{Ruby consumer of OData services.}
71
+ s.test_files = [
72
+ "test/blueprints.rb"
73
+ ]
74
+
75
+ if s.respond_to? :specification_version then
76
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
77
+ s.specification_version = 3
78
+
79
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
80
+ s.add_runtime_dependency(%q<activesupport>, [">= 2.3.5"])
81
+ s.add_runtime_dependency(%q<rest-client>, [">= 1.5.1"])
82
+ s.add_runtime_dependency(%q<nokogiri>, [">= 1.4.2"])
83
+ else
84
+ s.add_dependency(%q<activesupport>, [">= 2.3.5"])
85
+ s.add_dependency(%q<rest-client>, [">= 1.5.1"])
86
+ s.add_dependency(%q<nokogiri>, [">= 1.4.2"])
87
+ end
88
+ else
89
+ s.add_dependency(%q<activesupport>, [">= 2.3.5"])
90
+ s.add_dependency(%q<rest-client>, [">= 1.5.1"])
91
+ s.add_dependency(%q<nokogiri>, [">= 1.4.2"])
92
+ end
93
+ end
94
+
@@ -0,0 +1 @@
1
+ "%ProgramFiles(x86)%\Common Files\microsoft shared\DevServer\10.0\WebDev.WebServer40.EXE" /port:8888 /path:"%~dp0SampleService" /vpath:"/SampleService"
@@ -0,0 +1 @@
1
+ "%ProgramFiles%\Common Files\microsoft shared\DevServer\10.0\WebDev.WebServer40.EXE" /port:8888 /path:"%~dp0SampleService" /vpath:"/SampleService"
@@ -0,0 +1,39 @@
1
+ using System.Data.Services;
2
+ using System.Data.Services.Common;
3
+ using System.ServiceModel.Web;
4
+ using System.Web;
5
+ using Model;
6
+
7
+ public class Entities : DataService< ModelContainer >
8
+ {
9
+ // This method is called only once to initialize service-wide policies.
10
+ public static void InitializeService(DataServiceConfiguration config)
11
+ {
12
+ config.SetEntitySetAccessRule("*", EntitySetRights.All);
13
+ config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
14
+ config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
15
+ }
16
+
17
+ /// <summary>
18
+ /// Cleans the database for testing.
19
+ /// </summary>
20
+ [WebInvoke]
21
+ public void CleanDatabaseForTesting()
22
+ {
23
+ var context = new ModelContainer();
24
+ context.ExecuteStoreCommand("ALTER TABLE [dbo].[Products] DROP CONSTRAINT [FK_CategoryProduct]");
25
+ context.ExecuteStoreCommand("TRUNCATE TABLE [dbo].[Categories]; TRUNCATE TABLE [dbo].[Products]");
26
+ context.ExecuteStoreCommand("ALTER TABLE [dbo].[Products] ADD CONSTRAINT [FK_CategoryProduct] FOREIGN KEY ([Category_Id]) REFERENCES [dbo].[Categories]([Id])");
27
+
28
+ }
29
+
30
+ protected override void OnStartProcessingRequest(ProcessRequestArgs args)
31
+ {
32
+ base.OnStartProcessingRequest(args);
33
+ if (args.RequestUri.AbsoluteUri.ToLower().EndsWith("cleandatabasefortesting"))
34
+ {
35
+ if (HttpContext.Current.Request.UserHostAddress != "127.0.0.1")
36
+ throw new DataServiceException(401, "Access Denied");
37
+ }
38
+ }
39
+ }