wrest 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (154) hide show
  1. data/CHANGELOG +34 -0
  2. data/README.rdoc +16 -10
  3. data/Rakefile +361 -123
  4. data/VERSION.yml +2 -2
  5. data/examples/delicious.rb +17 -7
  6. data/examples/facebook.rb +101 -0
  7. data/examples/keep_alive.rb +37 -0
  8. data/examples/twitter.rb +3 -3
  9. data/examples/twitter_public_timeline.rb +11 -4
  10. data/examples/wow_realm_status.rb +8 -2
  11. data/{spec/functional/sample_rails_app/public/favicon.ico → init.rb} +0 -0
  12. data/lib/wrest/components/{attributes_container → container}/alias_accessors.rb +4 -4
  13. data/lib/wrest/components/{attributes_container → container}/typecaster.rb +1 -1
  14. data/lib/wrest/components/{attributes_container.rb → container.rb} +46 -16
  15. data/lib/wrest/components/mutators.rb +4 -4
  16. data/lib/wrest/components/translators/json.rb +2 -2
  17. data/lib/wrest/components/translators/xml.rb +3 -2
  18. data/lib/wrest/components/translators.rb +3 -3
  19. data/lib/wrest/components.rb +3 -3
  20. data/lib/wrest/core_ext/hash.rb +1 -1
  21. data/lib/wrest/core_ext/string.rb +1 -1
  22. data/lib/wrest/curl/delete.rb +23 -0
  23. data/lib/wrest/curl/get.rb +23 -0
  24. data/lib/wrest/curl/options.rb +16 -0
  25. data/lib/wrest/curl/post.rb +23 -0
  26. data/lib/wrest/curl/put.rb +23 -0
  27. data/lib/wrest/curl/request.rb +95 -0
  28. data/lib/wrest/curl/response.rb +63 -0
  29. data/lib/wrest/curl/session.rb +57 -0
  30. data/lib/wrest/curl.rb +49 -0
  31. data/lib/wrest/exceptions.rb +16 -1
  32. data/lib/wrest/http_shared/headers.rb +350 -0
  33. data/lib/wrest/http_shared/standard_headers.rb +21 -0
  34. data/lib/wrest/http_shared/standard_tokens.rb +18 -0
  35. data/lib/wrest/http_shared.rb +24 -0
  36. data/lib/wrest/native/connection_factory.rb +23 -0
  37. data/lib/wrest/{http → native}/delete.rb +1 -1
  38. data/lib/wrest/{http → native}/get.rb +1 -1
  39. data/lib/wrest/{http → native}/options.rb +1 -1
  40. data/lib/wrest/{http → native}/post.rb +1 -1
  41. data/lib/wrest/{http → native}/put.rb +1 -1
  42. data/lib/wrest/{http → native}/redirection.rb +4 -1
  43. data/lib/wrest/{http → native}/request.rb +32 -20
  44. data/lib/wrest/{http → native}/response.rb +12 -4
  45. data/lib/wrest/native/session.rb +57 -0
  46. data/lib/wrest/native.rb +32 -0
  47. data/lib/wrest/resource/base.rb +1 -1
  48. data/lib/wrest/resource.rb +1 -1
  49. data/lib/wrest/test/request_patches.rb +5 -0
  50. data/lib/wrest/test.rb +1 -0
  51. data/lib/wrest/uri.rb +31 -3
  52. data/lib/wrest/version.rb +2 -2
  53. data/lib/wrest.rb +52 -16
  54. data/spec/unit/spec_helper.rb +12 -3
  55. data/spec/unit/wrest/components/attributes_container/alias_accessors_spec.rb +2 -2
  56. data/spec/unit/wrest/components/attributes_container/typecaster_spec.rb +6 -6
  57. data/spec/unit/wrest/components/attributes_container_spec.rb +44 -12
  58. data/spec/unit/wrest/components/translators/xml_spec.rb +7 -3
  59. data/spec/unit/wrest/curl/request_spec.rb +19 -0
  60. data/spec/unit/wrest/curl/response_spec.rb +16 -0
  61. data/spec/unit/wrest/http/response_spec.rb +17 -38
  62. data/spec/unit/wrest/{http → native}/redirection_spec.rb +5 -5
  63. data/spec/unit/wrest/{http → native}/request_spec.rb +15 -14
  64. data/spec/unit/wrest/native/response_spec.rb +72 -0
  65. data/spec/unit/wrest/native/session_spec.rb +74 -0
  66. data/spec/unit/wrest/resource/base_spec.rb +2 -2
  67. data/spec/unit/wrest/uri_spec.rb +51 -11
  68. data/wrest.gemspec +164 -0
  69. metadata +51 -165
  70. data/lib/wrest/http.rb +0 -25
  71. data/spec/functional/sample_rails_app/README +0 -3
  72. data/spec/functional/sample_rails_app/Rakefile +0 -10
  73. data/spec/functional/sample_rails_app/app/controllers/application_controller.rb +0 -10
  74. data/spec/functional/sample_rails_app/app/controllers/lead_bottles_controller.rb +0 -7
  75. data/spec/functional/sample_rails_app/app/helpers/application_helper.rb +0 -3
  76. data/spec/functional/sample_rails_app/app/models/bottle.rb +0 -3
  77. data/spec/functional/sample_rails_app/app/models/glass_bottle.rb +0 -3
  78. data/spec/functional/sample_rails_app/app/models/lead_bottle.rb +0 -3
  79. data/spec/functional/sample_rails_app/config/boot.rb +0 -110
  80. data/spec/functional/sample_rails_app/config/database.yml +0 -16
  81. data/spec/functional/sample_rails_app/config/environment.rb +0 -42
  82. data/spec/functional/sample_rails_app/config/environments/development.rb +0 -17
  83. data/spec/functional/sample_rails_app/config/environments/production.rb +0 -28
  84. data/spec/functional/sample_rails_app/config/environments/test.rb +0 -28
  85. data/spec/functional/sample_rails_app/config/initializers/backtrace_silencers.rb +0 -7
  86. data/spec/functional/sample_rails_app/config/initializers/inflections.rb +0 -10
  87. data/spec/functional/sample_rails_app/config/initializers/mime_types.rb +0 -5
  88. data/spec/functional/sample_rails_app/config/initializers/new_rails_defaults.rb +0 -19
  89. data/spec/functional/sample_rails_app/config/initializers/session_store.rb +0 -15
  90. data/spec/functional/sample_rails_app/config/locales/en.yml +0 -5
  91. data/spec/functional/sample_rails_app/config/routes.rb +0 -3
  92. data/spec/functional/sample_rails_app/db/development.sqlite3 +0 -0
  93. data/spec/functional/sample_rails_app/db/migrate/20090319115628_create_bottle.rb +0 -13
  94. data/spec/functional/sample_rails_app/db/schema.rb +0 -20
  95. data/spec/functional/sample_rails_app/db/test.sqlite3 +0 -0
  96. data/spec/functional/sample_rails_app/log/development.log +0 -1
  97. data/spec/functional/sample_rails_app/public/404.html +0 -30
  98. data/spec/functional/sample_rails_app/public/422.html +0 -30
  99. data/spec/functional/sample_rails_app/public/500.html +0 -30
  100. data/spec/functional/sample_rails_app/public/images/rails.png +0 -0
  101. data/spec/functional/sample_rails_app/public/index.html +0 -275
  102. data/spec/functional/sample_rails_app/public/robots.txt +0 -5
  103. data/spec/functional/sample_rails_app/script/about +0 -4
  104. data/spec/functional/sample_rails_app/script/autospec +0 -6
  105. data/spec/functional/sample_rails_app/script/console +0 -3
  106. data/spec/functional/sample_rails_app/script/dbconsole +0 -3
  107. data/spec/functional/sample_rails_app/script/destroy +0 -3
  108. data/spec/functional/sample_rails_app/script/generate +0 -3
  109. data/spec/functional/sample_rails_app/script/performance/benchmarker +0 -3
  110. data/spec/functional/sample_rails_app/script/performance/profiler +0 -3
  111. data/spec/functional/sample_rails_app/script/plugin +0 -3
  112. data/spec/functional/sample_rails_app/script/runner +0 -3
  113. data/spec/functional/sample_rails_app/script/server +0 -3
  114. data/spec/functional/sample_rails_app/script/spec +0 -10
  115. data/spec/functional/sample_rails_app/script/spec_server +0 -9
  116. data/spec/functional/sample_rails_app/test/performance/browsing_test.rb +0 -9
  117. data/spec/functional/sample_rails_app/test/test_helper.rb +0 -38
  118. data/spec/functional/sample_rails_app/tmtags +0 -2559
  119. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/MIT-LICENSE +0 -20
  120. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/README.rdoc +0 -100
  121. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/Rakefile +0 -18
  122. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/init.rb +0 -5
  123. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/install.rb +0 -1
  124. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/base.rb +0 -140
  125. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/controllers/resources.rb +0 -16
  126. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/controllers/resources_controller.rb +0 -26
  127. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/controllers/routes_controller.rb +0 -16
  128. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/core_extensions/api.rb +0 -26
  129. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/core_extensions/exception.rb +0 -23
  130. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/core_extensions/from_json.rb +0 -15
  131. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/dispatch.rb +0 -235
  132. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/models/resourced_route.rb +0 -84
  133. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/query.rb +0 -337
  134. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/render/html.rb +0 -50
  135. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/render/json.rb +0 -75
  136. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/render/xml.rb +0 -65
  137. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/render.rb +0 -63
  138. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/retrieve.rb +0 -74
  139. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/version.rb +0 -9
  140. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full.rb +0 -14
  141. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/base_spec.rb +0 -88
  142. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/controllers/resources_spec.rb +0 -29
  143. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/dispatch_spec.rb +0 -262
  144. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/models/resourced_route_spec.rb +0 -62
  145. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/query/parameter_spec.rb +0 -57
  146. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/query_spec.rb +0 -462
  147. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/render/html_spec.rb +0 -4
  148. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/render/json_spec.rb +0 -107
  149. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/render/xml_spec.rb +0 -98
  150. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/render_spec.rb +0 -5
  151. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/retrieve_spec.rb +0 -173
  152. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/spec_helper.rb +0 -98
  153. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/uninstall.rb +0 -1
  154. data/spec/functional/spec_helper.rb +0 -0
@@ -1,84 +0,0 @@
1
- module ResourceFull
2
- module Models
3
- class RouteNotFound < Exception
4
- end
5
-
6
- class ResourcedRoute
7
- attr_reader :verb, :name, :pattern, :action, :controller
8
-
9
- class << self
10
- def find(what, opts={})
11
- case what
12
- when :all
13
- find_all_routes(opts)
14
- else
15
- find_named_route(what)
16
- end
17
- end
18
-
19
- def find_named_route(name)
20
- all_named_routes.find {|route| route.name == name} or raise ResourceFull::Models::RouteNotFound, "Could not find route #{name}"
21
- end
22
-
23
- def find_all_routes(opts={})
24
- all_named_routes(opts).reject do |route|
25
- opts.has_key?(:resource_id) && opts[:resource_id].to_s != route.resource.to_s
26
- end.sort_by {|r| r.name.to_s}
27
- end
28
-
29
- private
30
-
31
- # Translates an AR route into something a little more human-friendly, adding some extra
32
- # relationships as it goes and cutting out the stuff we're not interested in--for example,
33
- # formatted variants of regular routes.
34
- def all_named_routes(opts={})
35
- @all_named_routes ||= ActionController::Routing::Routes.named_routes.routes.collect do |name, route|
36
- verb = route.conditions[:method].to_s.upcase
37
- segs = route.segments.join
38
- new(
39
- :name => name,
40
- :verb => verb,
41
- :pattern => segs,
42
- :action => route.requirements[:action],
43
- :controller => route.requirements[:controller]
44
- )
45
- end.reject do |route|
46
- route.formatted?
47
- end
48
- end
49
-
50
- end
51
-
52
- def initialize(opts={})
53
- @verb = opts[:verb]
54
- @name = opts[:name]
55
- @pattern = opts[:pattern]
56
- @action = opts[:action]
57
- @controller = ResourceFull::Base.controller_for(opts[:controller])
58
- end
59
-
60
- def to_xml(opts={})
61
- {
62
- :resource => resource,
63
- :verb => verb,
64
- :name => name,
65
- :pattern => pattern,
66
- :action => action
67
- }.to_xml(opts.merge(:root => "route"))
68
- end
69
-
70
- def formatted?
71
- name.to_s =~ /^formatted/
72
- end
73
-
74
- def resource
75
- controller.controller_name
76
- end
77
-
78
- def resourced?
79
- controller.ancestors.include?(ResourceFull::Base)
80
- end
81
-
82
- end
83
- end
84
- end
@@ -1,337 +0,0 @@
1
- module ResourceFull
2
- module Query
3
- class << self
4
- def included(base)
5
- super(base)
6
- base.send :extend, ClassMethods
7
- base.queryable_with :limit, :scope => lambda {|limit| { :limit => limit }}
8
- base.queryable_with :offset, :scope => lambda {|offset| { :offset => offset }}
9
- base.queryable_with_order
10
- end
11
- end
12
-
13
- # A Parameter represents the information necessary to describe a query relationship. It's inherently
14
- # tied to ActiveRecord at the moment, unfortunately. Objects of this class should not be instantiated
15
- # directly; instead, use the +queryable_with+ method.
16
- class Parameter
17
- attr_reader :name, :resource
18
-
19
- def initialize(name, resource, opts={})
20
- @name = name
21
- @resource = resource
22
- @fuzzy = opts[:fuzzy] || false
23
- @allow_nil = opts[:allow_nil] || false
24
- @default_value = opts[:default]
25
- end
26
-
27
- def fuzzy?; @fuzzy; end
28
- def allow_nil?; @allow_nil; end
29
-
30
- def to_xml(opts={})
31
- {
32
- :name => name.to_s,
33
- :resource => resource.model_name.pluralize,
34
- :fuzzy => fuzzy?,
35
- }.to_xml(opts.merge(:root => "parameter"))
36
- end
37
-
38
- def applicable_to?(request_params)
39
- if allow_nil?
40
- request_params.has_key?(self.name.to_s) || request_params.has_key?(self.name.to_s.pluralize)
41
- else
42
- not param_values_for(request_params).blank?
43
- end
44
- end
45
-
46
- def find(finder, request_params)
47
- raise NotImplementedError, "Subclasses implement this behavior."
48
- end
49
-
50
- def subclass(new_resource)
51
- raise NotImplementedError, "Subclasses implement this behavior."
52
- end
53
-
54
- protected
55
-
56
- def param_values_for(params)
57
- values = (params[self.name.to_s] || params[self.name.to_s.pluralize] || @default_value || '')
58
- values = values.to_s.split(',') unless values.is_a?(Array)
59
- values.map! {|value| "%#{value}%" } if fuzzy?
60
- values
61
- end
62
-
63
- def table_for(opts={})
64
- if opts.has_key?(:table)
65
- opts[:table]
66
- elsif opts.has_key?(:from)
67
- infer_model_from(resource.model_class, opts[:from]).table_name
68
- else
69
- resource.model_class.table_name
70
- end
71
- end
72
-
73
- def infer_model_from(model, join)
74
- if join.is_a? Symbol
75
- model.reflect_on_association(join).klass
76
- elsif join.is_a? Hash
77
- new_model = model.reflect_on_association(join.keys.first).klass
78
- infer_model_from new_model, join.values.first
79
- end
80
- end
81
-
82
- end
83
-
84
- class CustomParameter < Parameter
85
- attr_reader :table, :columns, :include
86
-
87
- def initialize(name, resource, opts={})
88
- super(name, resource, opts)
89
-
90
- @table = table_for(opts)
91
- @columns = columns_for(name, resource, opts)
92
- @negated = opts[:negated] || false
93
- @include = opts[:from] || []
94
- end
95
-
96
- def allow_nil?; @allow_nil; end
97
- def negated?; @negated; end
98
-
99
- def find(finder, request_params)
100
- return finder unless applicable_to?(request_params)
101
- finder.scoped :conditions => conditions_for(request_params), :include => @include
102
- end
103
-
104
- def subclass(new_resource)
105
- new_table = if @table == @resource.model_class.table_name
106
- new_resource.model_class.table_name
107
- else @table end
108
-
109
- self.class.new(@name, new_resource,
110
- :fuzzy => @fuzzy,
111
- :allow_nil => @allow_nil,
112
- :table => new_table,
113
- :columns => @columns,
114
- :from => @include,
115
- :negated => @negated
116
- )
117
- end
118
-
119
- private
120
-
121
- def conditions_for(params)
122
- values = param_values_for(params)
123
- unless values.empty?
124
- final_query_string = if negated?
125
- values.collect { |value| negated_query_string(value) }.join(" AND ")
126
- else
127
- values.collect { |value| query_string(value) }.join(" OR ")
128
- end
129
-
130
- final_values = values.sum([]) { |value| Array.new(columns.size, value) }
131
-
132
- [ final_query_string ] + final_values
133
- else
134
- if (allow_nil? && params.has_key?(self.name) && params[self.name].blank?)
135
- [query_string(params[self.name])]
136
- else
137
- []
138
- end
139
- end
140
- end
141
-
142
- def columns_for(name, resource, opts={})
143
- if opts.has_key?(:columns)
144
- opts[:columns]
145
- elsif opts.has_key?(:column)
146
- [ opts[:column] ]
147
- elsif opts[:resource_identifier] && opts.has_key?(:from)
148
- [ ResourceFull::Base.controller_for(infer_model_from(resource.model_class, opts[:from]).name.pluralize).resource_identifier ]
149
- else
150
- [ name ]
151
- end
152
- end
153
-
154
- def query_string(value)
155
- columns.collect do |column|
156
- # Convert to a column name if column is a proc. TODO There must be a cleaner way to do this.
157
- column = column.call(value) if column.is_a?(Proc)
158
- if fuzzy?
159
- "(#{table}.#{column} LIKE ?)"
160
- elsif !value.blank?
161
- "(#{table}.#{column} = ?)"
162
- elsif allow_nil?
163
- "(COALESCE(#{table}.#{column},'')='')"
164
- end
165
- end.join(" OR ")
166
- end
167
-
168
- def negated_query_string(value)
169
- columns.collect do |column|
170
- # Convert to a column name if column is a proc. TODO There must be a cleaner way to do this.
171
- column = column.call(value) if column.is_a?(Proc)
172
- if fuzzy?
173
- "(#{table}.#{column} NOT LIKE ? OR #{table}.#{column} IS NULL)"
174
- elsif !value.blank?
175
- "(#{table}.#{column} != ? OR #{table}.#{column} IS NULL)"
176
- end
177
- end.join(" AND ")
178
- end
179
- end
180
-
181
- class ScopedParameter < Parameter
182
- attr_reader :scope
183
-
184
- def initialize(name, resource, opts={})
185
- super(name, resource, opts)
186
- @scope = opts[:scope]
187
- end
188
-
189
- def method_scoped?; @scope.is_a?(Symbol); end
190
- def proc_scoped?; @scope.is_a?(Proc); end
191
- def hash_scoped?; @scope.is_a?(Hash); end
192
-
193
- def find(finder, request_params)
194
- return finder unless applicable_to?(request_params)
195
-
196
- if proc_scoped?
197
- finder.scoped scope.call(*param_values_for(request_params))
198
- elsif hash_scoped?
199
- finder.scoped scope
200
- else
201
- finder.send(scope, *param_values_for(request_params))
202
- end
203
- end
204
-
205
- def subclass(new_resource)
206
- self.class.new @name, new_resource, :scope => @scope
207
- end
208
-
209
- end
210
-
211
- class OrderParameter < Parameter
212
-
213
- def applicable_to?(request_params)
214
- request_params.has_key?(:order_by)
215
- end
216
-
217
- def natural_sort_for(opts)
218
- if opts.has_key?(:natural_sort)
219
- opts[:natural_sort]
220
- else
221
- false
222
- end
223
- end
224
-
225
- def find(finder, request_params)
226
- return finder unless applicable_to?(request_params)
227
-
228
- order_by = request_params[:order_by]
229
- order_direction = request_params[:order_direction] || "asc"
230
- sort_params = resource.orderables[order_by.to_sym] || {}
231
- table = table_for(sort_params)
232
- column = sort_params[:column] || order_by
233
-
234
- order_params = returning({}) do |hash|
235
- hash[:include] = sort_params[:from]
236
- end
237
-
238
- if natural_sort_for(sort_params)
239
- # to use this natural sort you must follow these instructions: http://www.ciarpame.com/2008/06/28/true-mysql-natural-order-by-trick/
240
- finder.scoped order_params.merge( :order => "natsort_canon(#{table}.#{column}, 'natural') #{order_direction}" )
241
- else
242
- finder.scoped order_params.merge( :order => "#{table}.#{column} #{order_direction}" )
243
- end
244
- end
245
-
246
- def subclass(new_resource)
247
- self.class.new(@name, new_resource)
248
- end
249
-
250
- end
251
-
252
- module ClassMethods
253
- # Indicates that the resource should be queryable with the given parameters, which will be pulled from
254
- # the params hash on an index or count call. Accepts the following options:
255
- #
256
- # * :fuzzy => true : Use a LIKE query instead of =.
257
- # * :columns / :column => ... : Override the default column, or provide a list of columns to query for this value.
258
- # * :from => :join_name : Indicate that this value should be queried by joining on another model. Should use
259
- # a valid relationship from this controller's exposed model (e.g., :account if belongs_to :account is specified.)
260
- # * :resource_identifier => true : Try to look up the resource controller for this value and honor its
261
- # specified resource identifier. Useful for nesting relationships.
262
- # * :allow_nils => true : Indicates that a nil value for a parameter should be taken to literally indicate
263
- # that null values should be returned. This may be changed in the future to expect the literal string 'null'
264
- # or some other reasonable standin.
265
- #
266
- # Examples:
267
- #
268
- # queryable_with :user_id
269
- # queryable_with :description, :fuzzy => true
270
- # queryable_with :name, :columns => [:first_name, :last_name]
271
- # queryable_with :street_address, :from => :address, :column => :street
272
- #
273
- # TODO No full-text search support.
274
- def queryable_with(*args)
275
- opts = args.extract_options!
276
- opts.assert_valid_keys :default, :fuzzy, :column, :columns, :from, :table, :resource_identifier, :allow_nil, :negated, :scope
277
- args.each do |param|
278
- self.queryable_params << if opts.has_key?(:scope)
279
- ResourceFull::Query::ScopedParameter.new(param, self, opts)
280
- else
281
- ResourceFull::Query::CustomParameter.new(param, self, opts)
282
- end
283
- end
284
- end
285
-
286
- # :nodoc:
287
- def clear_queryable_params!
288
- @queryable_params = []
289
- end
290
-
291
- # All queryable parameters. Objects are of type +ResourceFull::Query::Parameter+ or one of its subclasses.
292
- def queryable_params
293
- unless defined?(@queryable_params) && !@queryable_params.nil?
294
- @queryable_params = []
295
- if superclass.respond_to?(:queryable_params)
296
- @queryable_params += superclass.queryable_params.collect {|param| param.subclass(self)}
297
- end
298
- end
299
- @queryable_params
300
- end
301
-
302
- # Returns true if the controller is queryable with all of the named parameters.
303
- def queryable_with?(*params)
304
- (queryable_params.collect(&:name) & params.collect(&:to_sym)).size == params.size
305
- end
306
-
307
- # :nodoc:
308
- def queryable_params=(params)
309
- @queryable_params = params
310
- end
311
-
312
- def nests_within(*resources)
313
- resources.each do |resource|
314
- expected_nest_id = "#{resource.to_s.singularize}_id"
315
- queryable_with expected_nest_id, :from => resource.to_sym, :resource_identifier => true
316
- end
317
- end
318
-
319
- def orderable_by(*params)
320
- opts = params.extract_options!
321
- params.each do |param|
322
- orderables[param] = opts
323
- end
324
- end
325
-
326
- def queryable_with_order
327
- unless queryable_with?(:order_by)
328
- queryable_params << ResourceFull::Query::OrderParameter.new(:order_by, self)
329
- end
330
- end
331
-
332
- def orderables
333
- read_inheritable_attribute(:orderables) || write_inheritable_hash(:orderables, {})
334
- end
335
- end
336
- end
337
- end
@@ -1,50 +0,0 @@
1
- module ResourceFull
2
- module Render
3
- module HTML
4
- protected
5
-
6
- def show_html
7
- self.model_object = send("find_#{model_name}")
8
- rescue ActiveRecord::RecordNotFound => e
9
- flash[:error] = e.message
10
- end
11
-
12
- def index_html
13
- self.model_objects = send("find_all_#{model_name.pluralize}")
14
- end
15
-
16
- def create_html
17
- self.model_object = send("create_#{model_name}")
18
- if model_object.errors.empty?
19
- flash[:info] = "Successfully created #{model_name.humanize} with ID of #{model_object.id}."
20
- redirect_to :action => :index, :format => :html
21
- else
22
- render :action => "new"
23
- end
24
- end
25
-
26
- def update_html
27
- self.model_object = send("update_#{model_name}")
28
- if model_object.errors.empty?
29
- flash[:info] = "Successfully updated #{model_name.humanize} with ID of #{model_object.id}."
30
- redirect_to :action => :index, :format => :html
31
- else
32
- render :action => "edit"
33
- end
34
- end
35
-
36
- def destroy_html
37
- self.model_object = send("destroy_#{model_name}")
38
- flash[:info] = "Successfully destroyed #{model_name.humanize} with ID of #{params[:id]}."
39
- redirect_to :action => :index, :format => :html
40
- rescue ActiveRecord::RecordNotFound => e
41
- flash[:error] = e.message
42
- redirect_to :back
43
- end
44
-
45
- def new_html
46
- self.model_object = send("new_#{model_name}")
47
- end
48
- end
49
- end
50
- end
@@ -1,75 +0,0 @@
1
- module ResourceFull
2
- module Render
3
- module JSON
4
- protected
5
-
6
- def json_class_name(obj)
7
- obj.class.name.demodulize.underscore
8
- end
9
-
10
- def show_json_options
11
- {}
12
- end
13
- def show_json
14
- self.model_object = send("find_#{model_name}")
15
- render :json => model_object.to_json(show_json_options)
16
- rescue ActiveRecord::RecordNotFound => e
17
- render :json => e.to_json , :status => :not_found
18
- end
19
-
20
- def index_json_options
21
- {}
22
- end
23
- def index_json
24
- self.model_objects = send("find_all_#{model_name.pluralize}")
25
- render :json => model_objects.to_json(index_json_options)
26
- end
27
-
28
- def create_json_options
29
- {}
30
- end
31
- def create_json
32
- self.model_object = send("create_#{model_name}")
33
- if model_object.errors.empty?
34
- render :json => model_object.to_json(create_json_options), :status => :created, :location => send("#{model_name}_url", model_object.id)
35
- else
36
- json_data = model_object.attributes
37
- json_data[:errors] = {:list => model_object.errors,
38
- :full_messages => model_object.errors.full_messages}
39
- render :json => {json_class_name(model_object) => json_data}.to_json , :status => status_for(model_object.errors)
40
- end
41
- end
42
-
43
- def update_json_options
44
- {}
45
- end
46
- def update_json
47
- self.model_object = send("update_#{model_name}")
48
- if model_object.errors.empty?
49
- render :json => model_object.to_json(update_json_options)
50
- else
51
- json_data = model_object.attributes
52
- json_data[:errors] = {:list => model_object.errors,
53
- :full_messages => model_object.errors.full_messages}
54
- render :json => {json_class_name(model_object) => json_data}.to_json , :status => status_for(model_object.errors)
55
- end
56
- rescue ActiveRecord::RecordNotFound => e
57
- render :json => e.to_json , :status => :not_found
58
- end
59
-
60
- def destroy_json
61
- self.model_object = send("destroy_#{model_name}")
62
- head :ok
63
- rescue ActiveRecord::RecordNotFound => e
64
- render :json => e.to_json , :status => :not_found
65
- end
66
-
67
- def new_json_options
68
- {}
69
- end
70
- def new_json
71
- render :json => send("new_#{model_name}").to_json(new_json_options)
72
- end
73
- end
74
- end
75
- end
@@ -1,65 +0,0 @@
1
- module ResourceFull
2
- module Render
3
- module XML
4
- protected
5
-
6
- def show_xml_options
7
- {}
8
- end
9
- def show_xml
10
- self.model_object = send("find_#{model_name}")
11
- render :xml => model_object.to_xml(show_xml_options)
12
- rescue ActiveRecord::RecordNotFound => e
13
- render :xml => e.to_xml, :status => :not_found
14
- end
15
-
16
- def index_xml_options
17
- {}
18
- end
19
- def index_xml
20
- self.model_objects = send("find_all_#{model_name.pluralize}")
21
- render :xml => model_objects.to_xml(index_xml_options)
22
- end
23
-
24
- def create_xml_options
25
- {}
26
- end
27
- def create_xml
28
- self.model_object = send("create_#{model_name}")
29
- if model_object.errors.empty?
30
- render :xml => model_object.to_xml(create_xml_options), :status => :created, :location => send("#{model_name}_url", model_object.id)
31
- else
32
- render :xml => model_object.errors.to_xml, :status => status_for(model_object.errors)
33
- end
34
- end
35
-
36
- def update_xml_options
37
- {}
38
- end
39
- def update_xml
40
- self.model_object = send("update_#{model_name}")
41
- if model_object.errors.empty?
42
- render :xml => model_object.to_xml(update_xml_options)
43
- else
44
- render :xml => model_object.errors.to_xml, :status => status_for(model_object.errors)
45
- end
46
- rescue ActiveRecord::RecordNotFound => e
47
- render :xml => e.to_xml, :status => :not_found
48
- end
49
-
50
- def destroy_xml
51
- self.model_object = send("destroy_#{model_name}")
52
- head :ok
53
- rescue ActiveRecord::RecordNotFound => e
54
- render :xml => e.to_xml, :status => :not_found
55
- end
56
-
57
- def new_xml_options
58
- {}
59
- end
60
- def new_xml
61
- render :xml => send("new_#{model_name}").to_xml(new_xml_options)
62
- end
63
- end
64
- end
65
- end
@@ -1,63 +0,0 @@
1
- module ResourceFull
2
- module Render
3
- include ResourceFull::Render::HTML
4
- include ResourceFull::Render::JSON
5
- include ResourceFull::Render::XML
6
-
7
- def self.included(controller)
8
- controller.rescue_from Exception, :with => :handle_generic_exception_with_correct_response_format
9
- end
10
-
11
- private
12
-
13
- CONFLICT_MESSAGE = if defined?(ActiveRecord::Errors)
14
- if ([Rails::VERSION::MAJOR, Rails::VERSION::MINOR] <=> [2,1]) >= 0 # if the rails version is 2.1 or greater...Í
15
- (I18n.translate 'activerecord.errors.messages')[:taken]
16
- else
17
- ActiveRecord::Errors.default_error_messages[:taken]
18
- end
19
- else
20
- "has already been taken"
21
- end
22
-
23
- def status_for(errors)
24
- if errors.any? { |message| message.include? CONFLICT_MESSAGE }
25
- :conflict
26
- else :unprocessable_entity end
27
- end
28
-
29
- def handle_generic_exception_with_correct_response_format(exception)
30
- if request.format.xml?
31
- if defined?(ExceptionNotifiable) && defined?(ExceptionNotifier) && self.is_a?(ExceptionNotifiable) && !(consider_all_requests_local || local_request?)
32
- deliverer = self.class.exception_data
33
- data = case deliverer
34
- when nil then {}
35
- when Symbol then send(deliverer)
36
- when Proc then deliverer.call(self)
37
- end
38
-
39
- ExceptionNotifier.deliver_exception_notification(exception, self,
40
- request, data)
41
- end
42
- logger.error exception.message + "\n" + exception.clean_backtrace.collect {|s| "\t#{s}\n"}.join
43
- render :xml => exception.to_xml, :status => :server_error
44
- elsif request.format.json?
45
- if defined?(ExceptionNotifiable) && defined?(ExceptionNotifier) && self.is_a?(ExceptionNotifiable) && !(consider_all_requests_local || local_request?)
46
- deliverer = self.class.exception_data
47
- data = case deliverer
48
- when nil then {}
49
- when Symbol then send(deliverer)
50
- when Proc then deliverer.call(self)
51
- end
52
-
53
- ExceptionNotifier.deliver_exception_notification(exception, self,
54
- request, data)
55
- end
56
- logger.error exception.message + "\n" + exception.clean_backtrace.collect {|s| "\t#{s}\n"}.join
57
- render :json => exception.to_json, :status => :server_error
58
- else
59
- raise exception
60
- end
61
- end
62
- end
63
- end