Skip to content
Browse files

Merge branch 'master' of git@github.com:sam/dm-more

  • Loading branch information...
2 parents 3888768 + 7c2a30c commit 0489eaaf826343dfb2cc51ebf500479081212200 Adam French committed Jul 20, 2008
Showing with 14,030 additions and 1,750 deletions.
  1. +1 −0 History.txt
  2. +9 −0 Manifest.txt
  3. 0 README → README.txt
  4. +19 −46 Rakefile
  5. +2 −0 adapters/dm-couchdb-adapter/.gitignore
  6. +1 −0 adapters/dm-couchdb-adapter/History.txt
  7. +13 −0 adapters/dm-couchdb-adapter/Manifest.txt
  8. +0 −4 adapters/dm-couchdb-adapter/README
  9. +27 −0 adapters/dm-couchdb-adapter/README.txt
  10. +20 −27 adapters/dm-couchdb-adapter/Rakefile
  11. +122 −101 adapters/dm-couchdb-adapter/lib/couchdb_adapter.rb
  12. +35 −0 adapters/dm-couchdb-adapter/lib/couchdb_adapter/json_object.rb
  13. +7 −0 adapters/dm-couchdb-adapter/lib/couchdb_adapter/version.rb
  14. +55 −0 adapters/dm-couchdb-adapter/lib/couchdb_adapter/view.rb
  15. +0 −87 adapters/dm-couchdb-adapter/lib/couchdb_views.rb
  16. +43 −2 adapters/dm-couchdb-adapter/spec/couchdb_adapter_spec.rb
  17. +0 −13 adapters/dm-couchdb-adapter/spec/couchdb_view_spec.rb
  18. +1 −0 adapters/dm-rest-adapter/History.txt
  19. +26 −0 adapters/dm-rest-adapter/Manifest.txt
  20. +1 −2 adapters/dm-rest-adapter/{README → README.txt}
  21. +19 −25 adapters/dm-rest-adapter/Rakefile
  22. +0 −1 adapters/dm-rest-adapter/TODO
  23. +256 −0 adapters/dm-rest-adapter/fixtures/book_service/README
  24. +10 −0 adapters/dm-rest-adapter/fixtures/book_service/Rakefile
  25. +15 −0 adapters/dm-rest-adapter/fixtures/book_service/app/controllers/application.rb
  26. +85 −0 adapters/dm-rest-adapter/fixtures/book_service/app/controllers/books_controller.rb
  27. +89 −0 adapters/dm-rest-adapter/fixtures/book_service/app/controllers/shelves_controller.rb
  28. +3 −0 adapters/dm-rest-adapter/fixtures/book_service/app/helpers/application_helper.rb
  29. +2 −0 adapters/dm-rest-adapter/fixtures/book_service/app/helpers/books_helper.rb
  30. +2 −0 adapters/dm-rest-adapter/fixtures/book_service/app/helpers/shelf_helper.rb
  31. +6 −0 adapters/dm-rest-adapter/fixtures/book_service/app/models/book.rb
  32. +5 −0 adapters/dm-rest-adapter/fixtures/book_service/app/models/shelf.rb
  33. +20 −0 adapters/dm-rest-adapter/fixtures/book_service/app/views/books/edit.html.erb
  34. +22 −0 adapters/dm-rest-adapter/fixtures/book_service/app/views/books/index.html.erb
  35. +19 −0 adapters/dm-rest-adapter/fixtures/book_service/app/views/books/new.html.erb
  36. +13 −0 adapters/dm-rest-adapter/fixtures/book_service/app/views/books/show.html.erb
  37. +17 −0 adapters/dm-rest-adapter/fixtures/book_service/app/views/layouts/books.html.erb
  38. +16 −0 adapters/dm-rest-adapter/fixtures/book_service/app/views/shelves/edit.html.erb
  39. +20 −0 adapters/dm-rest-adapter/fixtures/book_service/app/views/shelves/index.html.erb
  40. +15 −0 adapters/dm-rest-adapter/fixtures/book_service/app/views/shelves/new.html.erb
  41. +7 −0 adapters/dm-rest-adapter/fixtures/book_service/app/views/shelves/show.html.erb
  42. +109 −0 adapters/dm-rest-adapter/fixtures/book_service/config/boot.rb
  43. +19 −0 adapters/dm-rest-adapter/fixtures/book_service/config/database.yml
  44. +67 −0 adapters/dm-rest-adapter/fixtures/book_service/config/environment.rb
  45. +17 −0 adapters/dm-rest-adapter/fixtures/book_service/config/environments/development.rb
  46. +22 −0 adapters/dm-rest-adapter/fixtures/book_service/config/environments/production.rb
  47. +22 −0 adapters/dm-rest-adapter/fixtures/book_service/config/environments/test.rb
  48. +10 −0 adapters/dm-rest-adapter/fixtures/book_service/config/initializers/inflections.rb
  49. +5 −0 adapters/dm-rest-adapter/fixtures/book_service/config/initializers/mime_types.rb
  50. +15 −0 adapters/dm-rest-adapter/fixtures/book_service/config/initializers/new_rails_defaults.rb
  51. +44 −0 adapters/dm-rest-adapter/fixtures/book_service/config/routes.rb
  52. BIN adapters/dm-rest-adapter/fixtures/book_service/db/development.sqlite3
  53. +15 −0 adapters/dm-rest-adapter/fixtures/book_service/db/migrate/20080608165526_create_books.rb
  54. +13 −0 adapters/dm-rest-adapter/fixtures/book_service/db/migrate/20080621171551_create_shelves.rb
  55. +20 −0 .../dm-rest-adapter/fixtures/book_service/db/migrate/20080629143033_create_fake_books_and_shelves.rb
  56. +28 −0 adapters/dm-rest-adapter/fixtures/book_service/db/schema.rb
  57. +30 −0 adapters/dm-rest-adapter/fixtures/book_service/public/404.html
  58. +30 −0 adapters/dm-rest-adapter/fixtures/book_service/public/422.html
  59. +30 −0 adapters/dm-rest-adapter/fixtures/book_service/public/500.html
  60. +10 −0 adapters/dm-rest-adapter/fixtures/book_service/public/dispatch.cgi
  61. +24 −0 adapters/dm-rest-adapter/fixtures/book_service/public/dispatch.fcgi
  62. +10 −0 adapters/dm-rest-adapter/fixtures/book_service/public/dispatch.rb
  63. 0 adapters/dm-rest-adapter/fixtures/book_service/public/favicon.ico
  64. BIN adapters/dm-rest-adapter/fixtures/book_service/public/images/rails.png
  65. +274 −0 adapters/dm-rest-adapter/fixtures/book_service/public/index.html
  66. +2 −0 adapters/dm-rest-adapter/fixtures/book_service/public/javascripts/application.js
  67. +963 −0 adapters/dm-rest-adapter/fixtures/book_service/public/javascripts/controls.js
  68. +972 −0 adapters/dm-rest-adapter/fixtures/book_service/public/javascripts/dragdrop.js
  69. +1,120 −0 adapters/dm-rest-adapter/fixtures/book_service/public/javascripts/effects.js
  70. +4,225 −0 adapters/dm-rest-adapter/fixtures/book_service/public/javascripts/prototype.js
  71. +5 −0 adapters/dm-rest-adapter/fixtures/book_service/public/robots.txt
  72. +54 −0 adapters/dm-rest-adapter/fixtures/book_service/public/stylesheets/scaffold.css
  73. +3 −0 adapters/dm-rest-adapter/fixtures/book_service/script/about
  74. +3 −0 adapters/dm-rest-adapter/fixtures/book_service/script/console
  75. +3 −0 adapters/dm-rest-adapter/fixtures/book_service/script/dbconsole
  76. +3 −0 adapters/dm-rest-adapter/fixtures/book_service/script/destroy
  77. +3 −0 adapters/dm-rest-adapter/fixtures/book_service/script/generate
  78. +3 −0 adapters/dm-rest-adapter/fixtures/book_service/script/performance/benchmarker
  79. +3 −0 adapters/dm-rest-adapter/fixtures/book_service/script/performance/profiler
  80. +3 −0 adapters/dm-rest-adapter/fixtures/book_service/script/performance/request
  81. +3 −0 adapters/dm-rest-adapter/fixtures/book_service/script/plugin
  82. +3 −0 adapters/dm-rest-adapter/fixtures/book_service/script/process/inspector
  83. +3 −0 adapters/dm-rest-adapter/fixtures/book_service/script/process/reaper
  84. +3 −0 adapters/dm-rest-adapter/fixtures/book_service/script/process/spawner
  85. +3 −0 adapters/dm-rest-adapter/fixtures/book_service/script/runner
  86. +3 −0 adapters/dm-rest-adapter/fixtures/book_service/script/server
  87. +9 −0 adapters/dm-rest-adapter/fixtures/book_service/test/fixtures/books.yml
  88. +7 −0 adapters/dm-rest-adapter/fixtures/book_service/test/fixtures/shelves.yml
  89. +45 −0 adapters/dm-rest-adapter/fixtures/book_service/test/functional/books_controller_test.rb
  90. +8 −0 adapters/dm-rest-adapter/fixtures/book_service/test/functional/shelf_controller_test.rb
  91. +38 −0 adapters/dm-rest-adapter/fixtures/book_service/test/test_helper.rb
  92. +8 −0 adapters/dm-rest-adapter/fixtures/book_service/test/unit/book_test.rb
  93. +8 −0 adapters/dm-rest-adapter/fixtures/book_service/test/unit/shelf_test.rb
  94. +115 −75 adapters/dm-rest-adapter/lib/rest_adapter.rb
  95. +7 −0 adapters/dm-rest-adapter/lib/rest_adapter/version.rb
  96. +21 −0 adapters/dm-rest-adapter/spec/create_spec.rb
  97. +22 −0 adapters/dm-rest-adapter/spec/delete_spec.rb
  98. +22 −74 adapters/dm-rest-adapter/spec/{rest_adapter_spec.rb → read_spec.rb}
  99. +1 −1 adapters/dm-rest-adapter/spec/ruby_forker.rb
  100. +17 −0 adapters/dm-rest-adapter/spec/spec_helper.rb
  101. +36 −0 adapters/dm-rest-adapter/spec/update_spec.rb
  102. +25 −2 adapters/dm-rest-adapter/stories/crud/create
  103. +19 −7 adapters/dm-rest-adapter/stories/crud/read
  104. +15 −4 adapters/dm-rest-adapter/stories/crud/stories.rb
  105. +31 −3 adapters/dm-rest-adapter/stories/crud/update
  106. +1 −1 adapters/dm-rest-adapter/stories/helper.rb
  107. +7 −0 adapters/dm-rest-adapter/stories/resources/helpers/book.rb
  108. +1 −1 adapters/dm-rest-adapter/stories/resources/helpers/story_helper.rb
  109. +35 −0 adapters/dm-rest-adapter/stories/resources/steps/read.rb
  110. +28 −23 adapters/dm-rest-adapter/stories/resources/steps/using_rest_adapter.rb
  111. +1 −0 dm-adjust/History.txt
  112. +15 −0 dm-adjust/Manifest.txt
  113. 0 dm-adjust/{README → README.txt}
  114. +20 −27 dm-adjust/Rakefile
  115. +4 −1 dm-adjust/lib/dm-adjust.rb
  116. +7 −0 dm-adjust/lib/dm-adjust/version.rb
  117. +1 −0 dm-aggregates/History.txt
  118. +17 −0 dm-aggregates/Manifest.txt
  119. 0 dm-aggregates/{README → README.txt}
  120. +21 −28 dm-aggregates/Rakefile
  121. +10 −7 dm-aggregates/lib/dm-aggregates.rb
  122. +44 −31 dm-aggregates/lib/dm-aggregates/adapters/data_objects_adapter.rb
  123. +200 −0 dm-aggregates/lib/dm-aggregates/aggregate_functions.rb
  124. +3 −10 dm-aggregates/lib/dm-aggregates/collection.rb
  125. +0 −118 dm-aggregates/lib/dm-aggregates/functions.rb
  126. +3 −10 dm-aggregates/lib/dm-aggregates/model.rb
  127. +2 −18 dm-aggregates/lib/dm-aggregates/repository.rb
  128. +21 −0 dm-aggregates/lib/dm-aggregates/support/symbol.rb
  129. +7 −0 dm-aggregates/lib/dm-aggregates/version.rb
  130. +71 −12 dm-aggregates/spec/integration/aggregates_spec.rb
  131. +1 −0 dm-ar-finders/History.txt
  132. +11 −0 dm-ar-finders/Manifest.txt
  133. +1 −2 dm-ar-finders/{README → README.txt}
  134. +21 −28 dm-ar-finders/Rakefile
  135. +5 −0 dm-ar-finders/lib/dm-ar-finders/version.rb
  136. +1 −0 dm-cli/History.txt
  137. +13 −0 dm-cli/Manifest.txt
  138. +1 −2 dm-cli/{README → README.txt}
  139. +22 −30 dm-cli/Rakefile
  140. +1 −0 dm-cli/lib/dm-cli.rb
  141. 0 dm-cli/lib/{data_mapper → dm-cli}/cli.rb
  142. +5 −0 dm-cli/lib/dm-cli/version.rb
  143. +1 −1 dm-cli/spec/unit/cli_spec.rb
  144. +1 −0 dm-is-example/History.txt
  145. +12 −0 dm-is-example/Manifest.txt
  146. +1 −2 dm-is-example/{README → README.txt}
  147. +20 −27 dm-is-example/Rakefile
  148. +7 −0 dm-is-example/lib/dm-is-example/is/version.rb
  149. +1 −0 dm-is-list/History.txt
  150. +12 −0 dm-is-list/Manifest.txt
  151. +1 −2 dm-is-list/{README → README.txt}
  152. +22 −29 dm-is-list/Rakefile
  153. +1 −1 dm-is-list/lib/dm-is-list/is/list.rb
  154. +7 −0 dm-is-list/lib/dm-is-list/is/version.rb
  155. +1 −0 dm-is-nested_set/History.txt
  156. +12 −0 dm-is-nested_set/Manifest.txt
  157. +1 −2 dm-is-nested_set/{README → README.txt}
  158. +21 −28 dm-is-nested_set/Rakefile
  159. +16 −27 dm-is-nested_set/lib/dm-is-nested_set/is/nested_set.rb
  160. +7 −0 dm-is-nested_set/lib/dm-is-nested_set/is/version.rb
  161. +79 −67 dm-is-nested_set/spec/integration/nested_set_spec.rb
  162. +1 −0 dm-is-nested_set/spec/spec_helper.rb
  163. +1 −0 dm-is-state_machine/History.txt
  164. +20 −0 dm-is-state_machine/LICENSE
  165. +31 −0 dm-is-state_machine/Manifest.txt
  166. +12 −0 dm-is-state_machine/README.txt
  167. +51 −0 dm-is-state_machine/Rakefile
  168. +11 −0 dm-is-state_machine/TODO
  169. +27 −0 dm-is-state_machine/lib/dm-is-state_machine.rb
  170. +25 −0 dm-is-state_machine/lib/dm-is-state_machine/is/data/event.rb
  171. +69 −0 dm-is-state_machine/lib/dm-is-state_machine/is/data/machine.rb
  172. +21 −0 dm-is-state_machine/lib/dm-is-state_machine/is/data/state.rb
  173. +73 −0 dm-is-state_machine/lib/dm-is-state_machine/is/dsl/event_dsl.rb
  174. +40 −0 dm-is-state_machine/lib/dm-is-state_machine/is/dsl/state_dsl.rb
  175. +107 −0 dm-is-state_machine/lib/dm-is-state_machine/is/state_machine.rb
  176. +7 −0 dm-is-state_machine/lib/dm-is-state_machine/is/version.rb
  177. +20 −0 dm-is-state_machine/spec/examples/invalid_events.rb
  178. +20 −0 dm-is-state_machine/spec/examples/invalid_states.rb
  179. +22 −0 dm-is-state_machine/spec/examples/invalid_transitions_1.rb
  180. +22 −0 dm-is-state_machine/spec/examples/invalid_transitions_2.rb
  181. +45 −0 dm-is-state_machine/spec/examples/traffic_light.rb
  182. +12 −0 dm-is-state_machine/spec/integration/invalid_events_spec.rb
  183. +12 −0 dm-is-state_machine/spec/integration/invalid_states_spec.rb
  184. +22 −0 dm-is-state_machine/spec/integration/invalid_transitions_spec.rb
  185. +150 −0 dm-is-state_machine/spec/integration/traffic_light_spec.rb
  186. +2 −0 dm-is-state_machine/spec/spec.opts
  187. +28 −0 dm-is-state_machine/spec/spec_helper.rb
  188. +28 −0 dm-is-state_machine/spec/unit/data/event_spec.rb
  189. +97 −0 dm-is-state_machine/spec/unit/data/machine_spec.rb
  190. +22 −0 dm-is-state_machine/spec/unit/data/state_spec.rb
  191. +56 −0 dm-is-state_machine/spec/unit/dsl/event_dsl_spec.rb
  192. +25 −0 dm-is-state_machine/spec/unit/dsl/state_dsl_spec.rb
  193. +34 −0 dm-is-state_machine/spec/unit/state_machine_spec.rb
  194. +1 −0 dm-is-tree/History.txt
  195. +10 −0 dm-is-tree/Manifest.txt
  196. +1 −2 dm-is-tree/{README → README.txt}
  197. +21 −28 dm-is-tree/Rakefile
  198. +7 −0 dm-is-tree/lib/dm-is-tree/is/version.rb
  199. +1 −0 dm-is-versioned/History.txt
  200. +12 −0 dm-is-versioned/Manifest.txt
  201. +1 −2 dm-is-versioned/{README → README.txt}
  202. +21 −28 dm-is-versioned/Rakefile
  203. +7 −0 dm-is-versioned/lib/dm-is-versioned/is/version.rb
  204. +1 −0 dm-migrations/History.txt
  205. +38 −0 dm-migrations/Manifest.txt
  206. +1 −2 dm-migrations/{README → README.txt}
  207. +22 −29 dm-migrations/Rakefile
  208. +5 −0 dm-migrations/lib/dm-migrations/version.rb
  209. +9 −11 dm-migrations/lib/migration.rb
  210. +3 −103 dm-migrations/lib/sql.rb
  211. +10 −10 dm-migrations/lib/sql/postgresql.rb
  212. +1 −8 dm-migrations/lib/sql/sqlite3.rb
  213. +55 −0 dm-migrations/lib/sql/table_creator.rb
  214. +53 −0 dm-migrations/lib/sql/table_modifier.rb
  215. +58 −55 dm-migrations/spec/integration/migration_runner_spec.rb
  216. +99 −99 dm-migrations/spec/integration/migration_spec.rb
  217. +118 −108 dm-migrations/spec/integration/sql_spec.rb
  218. +2 −1 dm-migrations/spec/spec.opts
  219. +3 −10 dm-migrations/spec/spec_helper.rb
  220. +447 −0 dm-migrations/spec/unit/migration_spec.rb
  221. +18 −0 dm-migrations/spec/unit/sql/column_spec.rb
  222. +99 −0 dm-migrations/spec/unit/sql/postgresql_spec.rb
  223. +109 −0 dm-migrations/spec/unit/sql/sqlite3_extensions_spec.rb
  224. +93 −0 dm-migrations/spec/unit/sql/table_creator_spec.rb
  225. +52 −0 dm-migrations/spec/unit/sql/table_modifier_spec.rb
  226. +31 −0 dm-migrations/spec/unit/sql/table_spec.rb
  227. +10 −0 dm-migrations/spec/unit/sql_spec.rb
  228. +1 −0 dm-observer/History.txt
  229. +11 −0 dm-observer/Manifest.txt
  230. +2 −2 dm-observer/{README → README.txt}
  231. +21 −28 dm-observer/Rakefile
  232. +5 −0 dm-observer/lib/dm-observer/version.rb
  233. +1 −0 dm-querizer/History.txt
  234. +14 −0 dm-querizer/Manifest.txt
  235. +1 −2 dm-querizer/{README → README.txt}
  236. +20 −27 dm-querizer/Rakefile
  237. +1 −1 dm-querizer/lib/dm-querizer.rb
  238. 0 dm-querizer/lib/{dm-core → dm-querizer}/collection.rb
  239. 0 dm-querizer/lib/{dm-core → dm-querizer}/model.rb
  240. +13 −2 dm-querizer/lib/{dm-core → dm-querizer}/querizer.rb
  241. +5 −0 dm-querizer/lib/dm-querizer/version.rb
  242. +1 −0 dm-serializer/History.txt
  243. +20 −0 dm-serializer/Manifest.txt
  244. +1 −2 dm-serializer/{README → README.txt}
  245. +21 −28 dm-serializer/Rakefile
  246. +13 −11 dm-serializer/lib/dm-serializer.rb
  247. +5 −0 dm-serializer/lib/dm-serializer/version.rb
  248. +4 −0 dm-serializer/spec/fixtures/cow.rb
  249. +11 −0 dm-serializer/spec/fixtures/quatum_cat.rb
  250. +1 −0 dm-serializer/spec/spec_helper.rb
  251. +14 −0 dm-serializer/spec/unit/to_csv_spec.rb
  252. +22 −1 dm-serializer/spec/unit/to_json_spec.rb
  253. +15 −0 dm-serializer/spec/unit/to_xml_spec.rb
  254. +14 −0 dm-serializer/spec/unit/to_yaml_spec.rb
  255. +1 −0 dm-shorthand/History.txt
  256. +11 −0 dm-shorthand/Manifest.txt
  257. +2 −3 dm-shorthand/{README → README.txt}
  258. +21 −28 dm-shorthand/Rakefile
  259. +5 −0 dm-shorthand/lib/dm-shorthand/version.rb
  260. +1 −0 dm-timestamps/History.txt
  261. +11 −0 dm-timestamps/Manifest.txt
  262. +1 −2 dm-timestamps/{README → README.txt}
  263. +21 −28 dm-timestamps/Rakefile
  264. +4 −4 dm-timestamps/lib/dm-timestamps.rb
  265. +5 −0 dm-timestamps/lib/dm-timestamps/version.rb
  266. +1 −0 dm-types/History.txt
  267. +39 −0 dm-types/Manifest.txt
  268. +1 −2 dm-types/{README → README.txt}
  269. +21 −28 dm-types/Rakefile
  270. +7 −0 dm-types/lib/dm-types.rb
  271. +31 −0 dm-types/lib/dm-types/bcrypt_hash.rb
  272. +10 −0 dm-types/lib/dm-types/enum.rb
  273. +5 −0 dm-types/lib/dm-types/file_path.rb
  274. +4 −0 dm-types/lib/dm-types/ip_address.rb
  275. +9 −0 dm-types/lib/dm-types/json.rb
  276. +4 −0 dm-types/lib/dm-types/uri.rb
  277. +5 −0 dm-types/lib/dm-types/version.rb
  278. +5 −0 dm-types/lib/dm-types/yaml.rb
  279. +50 −0 dm-types/spec/integration/bcrypt_hash_spec.rb
  280. +5 −0 dm-types/spec/integration/enum_spec.rb
  281. +26 −0 dm-types/spec/integration/file_path_spec.rb
  282. +4 −0 dm-types/spec/integration/flag_spec.rb
  283. +26 −0 dm-types/spec/integration/ip_address_spec.rb
  284. +26 −0 dm-types/spec/integration/json_spec.rb
  285. +26 −0 dm-types/spec/integration/uri_spec.rb
  286. +37 −0 dm-types/spec/integration/yaml_spec.rb
  287. +50 −0 dm-types/spec/unit/bcrypt_hash_spec.rb
  288. +37 −0 dm-types/spec/unit/csv_spec.rb
  289. +19 −0 dm-types/spec/unit/enum_spec.rb
  290. +11 −0 dm-types/spec/unit/file_path_spec.rb
  291. +7 −7 dm-types/spec/unit/flag_spec.rb
  292. +17 −0 dm-types/spec/unit/ip_address_spec.rb
  293. +53 −0 dm-types/spec/unit/json_spec.rb
  294. +11 −0 dm-types/spec/unit/uri_spec.rb
  295. +58 −0 dm-types/spec/unit/yaml_spec.rb
  296. +1 −0 dm-validations/History.txt
  297. +45 −0 dm-validations/Manifest.txt
  298. 0 dm-validations/{README → README.txt}
  299. +22 −30 dm-validations/Rakefile
  300. +7 −9 dm-validations/lib/dm-validations.rb
Sorry, we could not display the entire diff because too many files (323) changed.
View
1 History.txt
@@ -0,0 +1 @@
+
View
9 Manifest.txt
@@ -0,0 +1,9 @@
+History.txt
+MIT-LICENSE
+Manifest.txt
+README.textile
+README.txt
+Rakefile
+TODO
+lib/dm-more.rb
+lib/dm-more/version.rb
View
0 README → README.txt
File renamed without changes.
View
65 Rakefile
@@ -1,22 +1,10 @@
-module DataMapper
- # Set this to the version of dm-core that you are building against/for
- VERSION = "0.9.3"
-
- # Set this to the version of dm-more you plan to release
- MORE_VERSION = "0.9.3"
-end
-
require 'pathname'
-require 'rake/clean'
-require 'rake/gempackagetask'
-require 'rake/contrib/rubyforgepublisher'
require 'spec/rake/spectask'
require 'rake/rdoctask'
require 'fileutils'
+require 'lib/dm-more/version.rb'
include FileUtils
-DIR = Pathname(__FILE__).dirname.expand_path.to_s
-
## ORDER IS IMPORTANT
# gems may depend on other member gems of dm-more
gem_paths = %w[
@@ -41,48 +29,34 @@ gem_paths = %w[
]
gems = gem_paths.map { |p| File.basename(p) }
-PROJECT = "dm-more"
-
-dm_more_spec = Gem::Specification.new do |s|
- s.platform = Gem::Platform::RUBY
- s.name = PROJECT
- s.summary = "An Object/Relational Mapper for Ruby"
- s.description = "Faster, Better, Simpler."
- s.version = DataMapper::MORE_VERSION
-
- s.authors = "Sam Smoot"
- s.email = "ssmoot@gmail.com"
- s.rubyforge_project = PROJECT
- s.homepage = "http://datamapper.org"
-
- s.files = %w[ MIT-LICENSE README Rakefile TODO lib/dm-more.rb ]
- s.add_dependency('dm-core', "=#{DataMapper::VERSION}")
- s.add_dependency('merb_datamapper', '=0.9.3')
- (gems - %w[ merb_datamapper ]).each do |gem|
- s.add_dependency gem, "=#{DataMapper::VERSION}"
- end
-end
+ROOT = Pathname(__FILE__).dirname.expand_path
-Rake::GemPackageTask.new(dm_more_spec) do |p|
- p.gem_spec = dm_more_spec
- p.need_tar = true
- p.need_zip = true
-end
+AUTHOR = "Sam Smoot"
+EMAIL = "ssmoot@gmail.com"
+GEM_NAME = "dm-more"
+GEM_VERSION = DataMapper::More::VERSION
+GEM_DEPENDENCIES = [["dm-core", GEM_VERSION], *(gems - %w[ merb_datamapper ]).collect { |g| [g, GEM_VERSION] }]
+GEM_CLEAN = ['**/*.{gem,DS_Store}', '*.db', "doc/rdoc", ".config", "coverage", "cache", "lib/merb-more.rb"]
+GEM_EXTRAS = { :has_rdoc => false }
+
+PROJECT_NAME = "dm-more"
+PROJECT_URL = "http://datamapper.org"
+PROJECT_DESCRIPTION = "Faster, Better, Simpler."
+PROJECT_SUMMARY = "An Object/Relational Mapper for Ruby"
-CLEAN.include ["**/.*.sw?", "pkg", "lib/*.bundle", "*.gem", "doc/rdoc", ".config", "coverage", "cache", "lib/merb-more.rb"]
+require ROOT + 'tasks/hoe'
WIN32 = (RUBY_PLATFORM =~ /win32|mingw|cygwin/) rescue nil
SUDO = WIN32 ? '' : ('sudo' unless ENV['SUDOLESS'])
desc "Install it all"
task :install => [:install_gems, :package] do
- sh %{#{SUDO} gem install --local pkg/dm-more-#{DataMapper::MORE_VERSION}.gem --no-update-sources}
-# sh %{#{SUDO} gem install --local pkg/dm-#{DataMapper::MORE_VERSION}.gem --no-update-sources}
+ sh %{#{SUDO} gem install --local pkg/dm-more-#{DataMapper::More::VERSION}.gem --no-update-sources}
end
desc "Uninstall it all"
task :uninstall => [ :uninstall_gems, :clobber ] do
- sh "#{SUDO} gem uninstall dm-more -v#{DataMapper::MORE_VERSION} -I -x", :verbose => false rescue "dm-more not installed"
+ sh "#{SUDO} gem uninstall dm-more -v#{DataMapper::More::VERSION} -I -x", :verbose => false rescue "dm-more not installed"
end
desc "Build the dm-more gems"
@@ -122,8 +96,7 @@ end
desc "Bundle up all the dm-more gems"
task :bundle => [:package, :build_gems] do
mkdir_p "bundle"
-# cp "pkg/dm-#{DataMapper::MORE_VERSION}.gem", "bundle"
- cp "pkg/dm-more-#{DataMapper::MORE_VERSION}.gem", "bundle"
+ cp "pkg/dm-more-#{DataMapper::More::VERSION}.gem", "bundle"
gem_paths.each do |gem|
File.open("#{gem}/Rakefile") do |rakefile|
rakefile.read.detect {|l| l =~ /^VERSION\s*=\s*"(.*)"$/ }
@@ -176,7 +149,7 @@ namespace :ci do
gem_names.each do |gem_name|
Spec::Rake::SpecTask.new("#{gem_name}:spec") do |t|
t.spec_opts = ["--format", "specdoc", "--format", "html:rspec_report.html", "--diff"]
- t.spec_files = Pathname.glob(ENV['FILES'] || DIR + "/#{gem_name}/spec/**/*_spec.rb")
+ t.spec_files = Pathname.glob(ENV['FILES'] || ROOT + "/#{gem_name}/spec/**/*_spec.rb")
unless ENV['NO_RCOV']
t.rcov = true
t.rcov_opts << '--exclude' << "spec,gems,#{(gems - [gem_name]).join(',')}"
View
2 adapters/dm-couchdb-adapter/.gitignore
@@ -0,0 +1,2 @@
+couchdb.stderr
+couchdb.stdout
View
1 adapters/dm-couchdb-adapter/History.txt
@@ -0,0 +1 @@
+
View
13 adapters/dm-couchdb-adapter/Manifest.txt
@@ -0,0 +1,13 @@
+History.txt
+LICENSE
+Manifest.txt
+README.txt
+Rakefile
+TODO
+lib/couchdb_adapter.rb
+lib/couchdb_adapter/json_object.rb
+lib/couchdb_adapter/version.rb
+lib/couchdb_adapter/view.rb
+spec/couchdb_adapter_spec.rb
+spec/couchdb_view_spec.rb
+spec/spec.opts
View
4 adapters/dm-couchdb-adapter/README
@@ -1,4 +0,0 @@
-dm-couchdb-adapter
-==================
-
-A DataMapper adapter for CouchDB
View
27 adapters/dm-couchdb-adapter/README.txt
@@ -0,0 +1,27 @@
+This is a datamapper adapter to couchdb.
+
+== Setup
+Install with the rest of the dm-more package, using:
+ gem install dm-more
+
+Then when initializing datamapper:
+ - adapter should be :couchdb
+ - database should be the name of the couch adapter
+ - host (probably localhost)
+ - port should be specified (couchdb defaults to port 5984)
+
+You should now be able to use resources and their properties and have them stored to couchdb.
+
+== Views
+Special consideration has been made to help work with couch views. You can define them in the model using the view function and then use Model.auto_migrate! to add the views for Model to the database, or DataMapper.auto_migrate! to add the views for all models to the database.
+
+An example class with views defined:
+
+class User
+ include DataMapper::Resource
+
+ property :name, String
+ view :by_name, "function(doc) { if (doc.type == 'user') map(doc.name, doc) }"
+end
+
+You could then call User.by_name to get a listing of users ordered by name, or pass a key to try and find a specific user by their name, ie User.by_name(:key => 'username').
View
47 adapters/dm-couchdb-adapter/Rakefile
@@ -1,45 +1,38 @@
require 'rubygems'
require 'spec'
-require 'rake/clean'
-require 'rake/gempackagetask'
require 'spec/rake/spectask'
require 'pathname'
-CLEAN.include '{log,pkg}/'
-
-spec = Gem::Specification.new do |s|
- s.name = 'dm-couchdb-adapter'
- s.version = '0.9.3'
- s.platform = Gem::Platform::RUBY
- s.has_rdoc = true
- s.extra_rdoc_files = %w[ README LICENSE TODO ]
- s.summary = 'CouchDB Adapter for DataMapper'
- s.description = s.summary
- s.author = 'Bernerd Schaefer'
- s.email = 'bj.schaefer@gmail.com'
- s.homepage = 'http://github.com/sam/dm-more/tree/master/adapters/dm-couchdb-adapter'
- s.require_path = 'lib'
- s.files = FileList[ '{lib,spec}/**/*.rb', 'spec/spec.opts', 'Rakefile', *s.extra_rdoc_files ]
- s.add_dependency('dm-core', "=#{s.version}")
-end
+ROOT = Pathname(__FILE__).dirname.expand_path
+require ROOT + 'lib/couchdb_adapter/version'
+
+AUTHOR = "Bernerd Schaefer"
+EMAIL = "bj.schaefer@gmail.com"
+GEM_NAME = "dm-couchdb-adapter"
+GEM_VERSION = DataMapper::More::CouchDBAdapter::VERSION
+GEM_DEPENDENCIES = [["dm-core", GEM_VERSION]]
+GEM_CLEAN = ["log", "pkg"]
+GEM_EXTRAS = { :has_rdoc => true, :extra_rdoc_files => %w[ README.txt LICENSE TODO ] }
+
+PROJECT_NAME = "dm-more"
+PROJECT_URL = "http://github.com/sam/dm-more/tree/master/adapters/dm-couchdb-adapter"
+PROJECT_DESCRIPTION = PROJECT_SUMMARY = "CouchDB Adapter for DataMapper"
+
+require ROOT.parent.parent + 'tasks/hoe'
task :default => [ :spec ]
WIN32 = (RUBY_PLATFORM =~ /win32|mingw|cygwin/) rescue nil
SUDO = WIN32 ? '' : ('sudo' unless ENV['SUDOLESS'])
-Rake::GemPackageTask.new(spec) do |pkg|
- pkg.gem_spec = spec
-end
-
-desc "Install #{spec.name} #{spec.version}"
+desc "Install #{GEM_NAME} #{GEM_VERSION}"
task :install => [ :package ] do
- sh "#{SUDO} gem install --local pkg/#{spec.name}-#{spec.version} --no-update-sources", :verbose => false
+ sh "#{SUDO} gem install --local pkg/#{GEM_NAME}-#{GEM_VERSION} --no-update-sources", :verbose => false
end
-desc "Uninstall #{spec.name} #{spec.version} (default ruby)"
+desc "Uninstall #{GEM_NAME} #{GEM_VERSION} (default ruby)"
task :uninstall => [ :clobber ] do
- sh "#{SUDO} gem uninstall #{spec.name} -v#{spec.version} -I -x", :verbose => false
+ sh "#{SUDO} gem uninstall #{GEM_NAME} -v#{GEM_VERSION} -I -x", :verbose => false
end
desc 'Run specifications'
View
223 adapters/dm-couchdb-adapter/lib/couchdb_adapter.rb
@@ -1,12 +1,14 @@
require 'rubygems'
-gem 'dm-core', '=0.9.3'
-require 'base64'
+require 'pathname'
+require Pathname(__FILE__).dirname + 'couchdb_adapter/version'
+gem 'dm-core', DataMapper::More::CouchDBAdapter::VERSION
require 'dm-core'
+require 'base64'
require 'json'
require 'net/http'
-require 'pathname'
require 'uri'
-require Pathname(__FILE__).dirname + 'couchdb_views'
+require Pathname(__FILE__).dirname + 'couchdb_adapter/json_object'
+require Pathname(__FILE__).dirname + 'couchdb_adapter/view'
module DataMapper
module Resource
@@ -15,23 +17,19 @@ def to_json(dirty = false)
property_list = self.class.properties.select { |key, value| dirty ? self.dirty_attributes.key?(key) : true }
inferred_fields = {:type => self.class.name.downcase}
return (property_list.inject(inferred_fields) do |accumulator, property|
- accumulator[property.field] = instance_variable_get(property.instance_variable_name)
- if property.type == Object
- accumulator[property.field] = Base64.encode64(Marshal.dump(accumulator[property.field]))
- end
+ accumulator[property.field] =
+ unless property.type.respond_to?(:dump)
+ property.get!(self)
+ else
+ property.type.dump(property.get!(self), property)
+ end
accumulator
end).to_json
end
end
end
module DataMapper
- class Query
- attr_accessor :view
- end
-end
-
-module DataMapper
module Adapters
class CouchDBAdapter < AbstractAdapter
# Returns the name of the CouchDB database.
@@ -56,7 +54,14 @@ def escaped_db_name
def create(resources)
created = 0
resources.each do |resource|
- result = http_post("/#{self.escaped_db_name}", resource.to_json(true))
+ key = resource.class.key(self.name).map do |property|
+ resource.instance_variable_get(property.instance_variable_name)
+ end
+ if key.compact.empty?
+ result = http_post("/#{self.escaped_db_name}", resource.to_json(true))
+ else
+ result = http_put("/#{self.escaped_db_name}/#{key}", resource.to_json(true))
+ end
if result["ok"]
key = resource.class.key(self.name)
if key.size == 1
@@ -113,11 +118,29 @@ def read_many(query)
doc = request do |http|
http.request(build_request(query))
end
- Collection.new(query) do |collection|
- doc['rows'].each do |doc|
+ if doc['rows']
+ if doc['rows'].empty?
+ []
+ elsif query.view && query.model.views[query.view.to_sym].has_key?('reduce')
+ doc['rows']
+ else
+ Collection.new(query) do |collection|
+ doc['rows'].each do |doc|
+ data = doc["value"]
+ collection.load(
+ query.fields.map do |property|
+ data[property.field.to_s]
+ end
+ )
+ end
+ end
+ end
+ elsif doc['type'] && doc['type'].downcase == query.model.name.downcase
+ data = doc
+ Collection.new(query) do |collection|
collection.load(
query.fields.map do |property|
- property.typecast(doc["value"][property.field.to_s])
+ data[property.field.to_s]
end
)
end
@@ -128,52 +151,46 @@ def read_one(query)
doc = request do |http|
http.request(build_request(query))
end
- unless doc["total_rows"] == 0
- data = doc['rows'].first
+ if doc['rows'] && !doc['rows'].empty?
+ data = doc['rows'].first['value']
+ elsif !doc['rows']
+ data = doc if doc['type'] && doc['type'].downcase == query.model.name.downcase
+ end
+ if data
query.model.load(
query.fields.map do |property|
- data["value"][property.field.to_s]
+ data[property.field.to_s]
end,
- query)
+ query
+ )
end
end
- # Reads in a set from a stored view.
- def view(resource, proc_name, options = {})
- query = Query.new(repository, resource)
- query.view = { :name => proc_name }.merge!(options)
- read_many(query)
- end
-
protected
- # Converts the URI's scheme into a parsed HTTP identifier.
- def normalize_uri(uri_or_options)
- if String === uri_or_options
- uri_or_options = Addressable::URI.parse(uri_or_options)
- end
- if Addressable::URI === uri_or_options
- return uri_or_options.normalize
+ def build_request(query)
+ if query.view
+ view_request(query)
+ elsif query.conditions.length == 1 &&
+ query.conditions.first[0] == :eql &&
+ query.conditions.first[1].key?
+ get_request(query)
+ else
+ ad_hoc_request(query)
end
+ end
- user = uri_or_options.delete(:username)
- password = uri_or_options.delete(:password)
- host = (uri_or_options.delete(:host) || "")
- port = uri_or_options.delete(:port)
- database = uri_or_options.delete(:database)
- query = uri_or_options.to_a.map { |pair| pair.join('=') }.join('&')
- query = nil if query == ""
-
- return Addressable::URI.new(
- "http", user, password, host, port, database, query, nil
- )
+ def view_request(query)
+ uri = "/#{self.escaped_db_name}/" +
+ "_view/" +
+ "#{query.model.storage_name(self.name)}/" +
+ "#{query.view}" +
+ "#{query_string(query)}"
+ request = Net::HTTP::Get.new(uri)
end
- def build_request(query)
- unless query.view
- ad_hoc_request(query)
- else
- view_request(query)
- end
+ def get_request(query)
+ uri = "/#{self.escaped_db_name}/#{query.conditions.first[2]}"
+ request = Net::HTTP::Get.new(uri)
end
def ad_hoc_request(query)
@@ -186,65 +203,69 @@ def ad_hoc_request(query)
key = "[#{key}]"
end
- options = []
- options << "count=#{query.limit}" if query.limit
- options << "skip=#{query.offset}" if query.offset
- options = options.empty? ? nil : "?#{options.join('&')}"
-
- request = Net::HTTP::Post.new("/#{self.escaped_db_name}/_temp_view#{options}")
- request["Content-Type"] = "text/javascript"
+ request = Net::HTTP::Post.new("/#{self.escaped_db_name}/_temp_view#{query_string(query)}")
+ request["Content-Type"] = "application/json"
if query.conditions.empty?
request.body =
- "function(doc) {\n" +
- " if (doc.type == '#{query.model.name.downcase}') {\n" +
- " map(#{key}, doc);\n" +
- " }\n" +
- "}\n"
+%Q({"map":
+ "function(doc) {
+ if (doc.type == '#{query.model.name.downcase}') {
+ emit(#{key}, doc);
+ }
+ }"
+}
+)
else
conditions = query.conditions.map do |operator, property, value|
- condition = "doc.#{property.field}"
- condition << case operator
- when :eql then " == #{value.to_json}"
- when :not then " != #{value.to_json}"
- when :gt then " > #{value.to_json}"
- when :gte then " >= #{value.to_json}"
- when :lt then " < #{value.to_json}"
- when :lte then " <= #{value.to_json}"
- when :like then like_operator(value)
+ if operator == :eql && value.is_a?(Array)
+ value.map do |sub_value|
+ json_sub_value = sub_value.to_json.gsub("\"", "'")
+ "doc.#{property.field} == #{json_sub_value}"
+ end.join(" || ")
+ else
+ json_value = value.to_json.gsub("\"", "'")
+ condition = "doc.#{property.field}"
+ condition << case operator
+ when :eql then " == #{json_value}"
+ when :not then " != #{json_value}"
+ when :gt then " > #{json_value}"
+ when :gte then " >= #{json_value}"
+ when :lt then " < #{json_value}"
+ when :lte then " <= #{json_value}"
+ when :like then like_operator(value)
+ end
end
end
- body = <<-JS
- function(doc) {
- if (doc.type == '#{query.model.name.downcase}') {
- if (#{conditions.join(" && ")}) {
- map(#{key}, doc);
- }
- }
- }
- JS
- space = body.split("\n")[0].to_s[/^(\s+)/, 0]
- request.body = body.gsub(/^#{space}/, '')
+ request.body =
+%Q({"map":
+ "function(doc) {
+ if (doc.type == '#{query.model.name.downcase}' && #{conditions.join(" && ")}) {
+ emit(#{key}, doc);
+ }
+ }"
+}
+)
end
request
end
- def view_request(query)
- options = query.view.dup
- proc_name = options.delete(:name)
- options[:count] = query.limit if query.limit
- options[:skip] = query.offset if query.offset
- if options.empty?
- options = ''
- else
- options = "?" + options.to_a.map {|option| "#{option[0]}=#{option[1].to_json}"}.join("&")
+ def query_string(query)
+ query_string = []
+ if query.view_options
+ query_string +=
+ query.view_options.map do |key, value|
+ if [:endkey, :key, :startkey].include? key
+ URI.escape(%Q(#{key}=#{value.to_json}))
+ else
+ URI.escape("#{key}=#{value}")
+ end
+ end
end
- uri = "/#{self.escaped_db_name}/" +
- "_view/" +
- "#{query.model.storage_name(self.name)}/" +
- "#{proc_name}" +
- "#{options}"
- request = Net::HTTP::Get.new(uri)
+ query_string << "count=#{query.limit}" if query.limit
+ query_string << "descending=#{query.add_reversed?}" if query.add_reversed?
+ query_string << "skip=#{query.offset}" if query.offset != 0
+ query_string.empty? ? nil : "?#{query_string.join('&')}"
end
def like_operator(value)
@@ -290,7 +311,7 @@ def create_model_storage(repository, model)
view = Net::HTTP::Put.new(uri)
view['content-type'] = "text/javascript"
views = model.views.reject {|key, value| value.nil?}
- view.body = { :views => model.views }.to_json
+ view.body = { :views => views }.to_json
request do |http|
http.request(view)
View
35 adapters/dm-couchdb-adapter/lib/couchdb_adapter/json_object.rb
@@ -0,0 +1,35 @@
+require 'json'
+
+# Non-lazy objects that serialize to/from JSON, for use with couchdb
+module DataMapper
+ module Types
+ class JsonObject < DataMapper::Type
+ primitive String
+ size 65535
+
+ def self.load(value, property)
+ if value.nil?
+ nil
+ elsif value.is_a?(String)
+ ::JSON.load(value)
+ else
+ raise ArgumentError.new("+value+ must be nil or a String")
+ end
+ end
+
+ def self.dump(value, property)
+ if value.nil?
+ nil
+ elsif value.is_a?(String)
+ value
+ else
+ ::JSON.dump(value)
+ end
+ end
+
+ def self.typecast(value, property)
+ value
+ end
+ end # class JsonObject
+ end # module Types
+end # module DataMapper
View
7 adapters/dm-couchdb-adapter/lib/couchdb_adapter/version.rb
@@ -0,0 +1,7 @@
+module DataMapper
+ module More
+ class CouchDBAdapter
+ VERSION = "0.9.3"
+ end
+ end
+end
View
55 adapters/dm-couchdb-adapter/lib/couchdb_adapter/view.rb
@@ -0,0 +1,55 @@
+module DataMapper
+ class Query
+ attr_accessor :view, :view_options
+ end
+end
+
+module DataMapper
+ class View
+ attr_reader :model, :name
+
+ def initialize(model, name)
+ @model = model
+ @name = name
+
+ create_getter
+ end
+
+ def create_getter
+ @model.class_eval <<-EOS, __FILE__, __LINE__
+ def self.#{@name}(*args)
+ options = {}
+ if args.size == 1 && !args.first.is_a?(Hash)
+ options[:key] = args.shift
+ else
+ options = args.pop
+ end
+ query = Query.new(repository, self)
+ query.view_options = options
+ query.view = '#{@name}'
+ if options.is_a?(Hash) && options.has_key?(:repository)
+ repository(options.delete(:repository)).read_many(query)
+ else
+ repository.read_many(query)
+ end
+ end
+ EOS
+ end
+ end
+end
+
+module DataMapper
+ module Model
+ def view(name, body = nil)
+ @views ||= Hash.new { |h,k| h[k] = {} }
+ proc = View.new(self, name)
+ @views[repository.name][name] = body
+ proc
+ end
+
+ def views(repository_name = default_repository_name)
+ @views ||= Hash.new { |h,k| h[k] = {} }
+ @views[repository_name]
+ end
+ end
+end
View
87 adapters/dm-couchdb-adapter/lib/couchdb_views.rb
@@ -1,87 +0,0 @@
-# This provides a mechanism for accessing stored and indexed views
-# in the CouchDB database.
-#
-# Here's a sample model:
-#
-# class User
-# include DataMapper::Resource
-#
-# property :id, String, :key => true, :field => :_id
-# property :rev, String, :field => :_rev
-#
-# view :by_name
-# end
-#
-# And here's the DM code to generate the view:
-#
-# view = Net::HTTP::Put.new("/example_db/_design/users")
-# view["content-type"] = "text/javascript"
-# view.body = {
-# "language" => "text/javascript",
-# "views" => {
-# "by_name" => "function(doc) { map(doc.name, doc); }"
-# }
-# }.to_json
-# @adapter.send(:request, false) do |http|
-# http.request(view)
-# end
-#
-
-module DataMapper
- class Repository
- def view(model, name, options = {})
- adapter.view(model, name, options)
- end
- end
-end
-
-module DataMapper
- module Adapters
- class AbstractAdapter
- def view(resource, proc_name, options = {})
- raise NotImplementedError
- end
- end
- end
-end
-
-module DataMapper
- class View
- attr_reader :model, :name
-
- def initialize(model, name)
- @model = model
- @name = name
-
- create_getter
- end
-
- def create_getter
- @model.class_eval <<-EOS, __FILE__, __LINE__
- def self.#{@name}(options = {})
- if Hash === options && options.has_key?(:repository)
- repository(options.delete(:repository)).view(self, :#{@name}, options)
- else
- repository.view(self, :#{@name}, options)
- end
- end
- EOS
- end
- end
-end
-
-module DataMapper
- module Model
- def view(name, body = nil)
- @views ||= Hash.new { |h,k| h[k] = {} }
- proc = View.new(self, name)
- @views[repository.name][name] = body
- proc
- end
-
- def views(repository_name = default_repository_name)
- @views ||= Hash.new { |h,k| h[k] = {} }
- @views[repository_name]
- end
- end
-end
View
45 adapters/dm-couchdb-adapter/spec/couchdb_adapter_spec.rb
@@ -19,10 +19,13 @@ class User
property :wealth, Float
property :created_at, DateTime
property :created_on, Date
+ property :location, JsonObject
# creates methods for accessing stored/indexed views in the CouchDB database
- view :by_name, "function(doc) { if (doc.type == 'user') { map(doc.name, doc); } }"
- view :by_age, "function(doc) { if (doc.type == 'user') { map(doc.age, doc); } }"
+ view :by_name, { "map" => "function(doc) { if (doc.type == 'user') { emit(doc.name, doc); } }" }
+ view :by_age, { "map" => "function(doc) { if (doc.type == 'user') { emit(doc.age, doc); } }" }
+ view :count, { "map" => "function(doc) { if (doc.type == 'user') { emit(null, 1); } }",
+ "reduce" => "function(keys, values) { return sum(values); }" }
before :create do
self.created_at = DateTime.now
@@ -73,6 +76,15 @@ class Company
company.id.should_not == nil
end
+ it "should create a record with a specified id" do
+ pending("No CouchDB connection.") if @no_connection
+ user_with_id = new_user
+ user_with_id.id = 'user_id'
+ user_with_id.save.should == true
+ User.get!('user_id').should == user_with_id
+ user_with_id.destroy
+ end
+
it "should get a record" do
pending("No CouchDB connection.") if @no_connection
created_user = new_user
@@ -83,6 +95,12 @@ class Company
user.age.should == 67
end
+ it "should not get records of the wrong type by id" do
+ pending("No CouchDB connection.") if @no_connection
+ Company.get(new_user.id).should == nil
+ lambda { Company.get!(new_user.id) }.should raise_error(DataMapper::ObjectNotFoundError)
+ end
+
it "should update a record" do
pending("No CouchDB connection.") if @no_connection
created_user = new_user
@@ -182,14 +200,37 @@ class Company
User.get!(user.id).created_on.should == date
end
+ it "should handle JsonObject" do
+ pending("No CouchDB connection.") if @no_connection
+ user = new_user
+ location = { 'city' => 'San Francisco', 'state' => 'California' }
+ user.location = location
+ user.save
+ User.get!(user.id).location.should == location
+ end
+
it "should be able to call stored views" do
pending("No CouchDB connection.") if @no_connection
User.by_name.first.should == User.all(:order => [:name]).first
User.by_age.first.should == User.all(:order => [:age]).first
end
+ it "should be able to call stored views with keys" do
+ pending("No CouchDB connection.") if @no_connection
+ User.by_name("Aaron").first == User.all(:name => "Aaron").first
+ User.by_age(30).first == User.all(:age => 30).first
+ User.by_name("Aaron").first == User.by_name(:key => "Aaron").first
+ User.by_age(30).first == User.by_age(:key => 30).first
+ end
+
+ it "should return a value from a view with reduce defined" do
+ pending("No CouchDB connection.") if @no_connection
+ User.count.should == [ { "value" => User.all.length, "key" => nil } ]
+ end
+
def create_procedures
DataMapper.auto_migrate!
+ DataMapper.auto_migrate!
end
def new_user(options = {})
View
13 adapters/dm-couchdb-adapter/spec/couchdb_view_spec.rb
@@ -38,16 +38,3 @@ def self.default_repository_name
Zoo.should respond_to(:open)
end
end
-
-describe DataMapper::Repository do
- it "should define a view method" do
- repository(:couchdb).should respond_to(:view)
- end
-end
-
-describe DataMapper::Adapters::AbstractAdapter do
- it "should have a view method" do
- DataMapper::Adapters::AbstractAdapter.
- instance_methods.should include("view")
- end
-end
View
1 adapters/dm-rest-adapter/History.txt
@@ -0,0 +1 @@
+
View
26 adapters/dm-rest-adapter/Manifest.txt
@@ -0,0 +1,26 @@
+History.txt
+LICENSE
+Manifest.txt
+README.txt
+Rakefile
+TODO
+lib/rest_adapter.rb
+lib/rest_adapter/version.rb
+spec/create_spec.rb
+spec/delete_spec.rb
+spec/read_spec.rb
+spec/ruby_forker.rb
+spec/spec.opts
+spec/spec_helper.rb
+spec/update_spec.rb
+stories/all.rb
+stories/crud/create
+stories/crud/delete
+stories/crud/read
+stories/crud/stories.rb
+stories/crud/update
+stories/helper.rb
+stories/resources/helpers/book.rb
+stories/resources/helpers/story_helper.rb
+stories/resources/steps/read.rb
+stories/resources/steps/using_rest_adapter.rb
View
3 adapters/dm-rest-adapter/README → adapters/dm-rest-adapter/README.txt
@@ -1,4 +1,3 @@
-dm-rest-adapter
-==================
+= dm-rest-adapter
A DataMapper adapter for REST Web Services
View
44 adapters/dm-rest-adapter/Rakefile
@@ -1,40 +1,33 @@
require 'rubygems'
require 'spec'
-require 'rake/clean'
-require 'rake/gempackagetask'
require 'spec/rake/spectask'
require 'pathname'
-CLEAN.include '{log,pkg}/'
-
-spec = Gem::Specification.new do |s|
- s.name = 'dm-rest-adapter'
- s.version = '0.9.3'
- s.platform = Gem::Platform::RUBY
- s.has_rdoc = true
- s.extra_rdoc_files = %w[ README LICENSE TODO ]
- s.summary = 'REST Adapter for DataMapper'
- s.description = s.summary
- s.author = 'Potomac Ruby Hackers'
- s.email = 'potomac-ruby-hackers@googlegroups.com'
- s.homepage = 'http://github.com/pjb3/dm-more/tree/master/adapters/dm-rest-adapter'
- s.require_path = 'lib'
- s.files = FileList[ '{lib,spec}/**/*.rb', 'spec/spec.opts', 'Rakefile', *s.extra_rdoc_files ]
- s.add_dependency('dm-core', "=#{s.version}")
-end
+ROOT = Pathname(__FILE__).dirname.expand_path
+require ROOT + 'lib/rest_adapter/version'
+
+AUTHOR = "Potomac Ruby Hackers"
+EMAIL = "potomac-ruby-hackers@googlegroups.com"
+GEM_NAME = "dm-rest-adapter"
+GEM_VERSION = DataMapper::More::RestAdapter::VERSION
+GEM_DEPENDENCIES = [["dm-core", GEM_VERSION]]
+GEM_CLEAN = ["log", "pkg"]
+GEM_EXTRAS = { :has_rdoc => true, :extra_rdoc_files => %w[ README.txt LICENSE TODO ] }
+
+PROJECT_NAME = "dm-more"
+PROJECT_URL = "http://github.com/pjb3/dm-more/tree/master/adapters/dm-rest-adapter"
+PROJECT_DESCRIPTION = PROJECT_SUMMARY = "REST Adapter for DataMapper"
+
+require ROOT.parent.parent + 'tasks/hoe'
task :default => [ :spec ]
WIN32 = (RUBY_PLATFORM =~ /win32|mingw|cygwin/) rescue nil
SUDO = WIN32 ? '' : ('sudo' unless ENV['SUDOLESS'])
-Rake::GemPackageTask.new(spec) do |pkg|
- pkg.gem_spec = spec
-end
-
-desc "Install #{spec.name} #{spec.version}"
+desc "Install #{GEM_NAME} #{GEM_VERSION}"
task :install => [ :package ] do
- sh "#{SUDO} gem install pkg/#{spec.name}-#{spec.version} --no-update-sources", :verbose => false
+ sh "#{SUDO} gem install pkg/#{GEM_NAME}-#{GEM_VERSION} --no-update-sources", :verbose => false
end
desc 'Run specifications'
@@ -48,5 +41,6 @@ end
desc "Run all stories"
task :stories do
+ # TODO Re-migrate the book service or else you won't have test data!
ruby "stories/all.rb --colour --format plain"
end
View
1 adapters/dm-rest-adapter/TODO
@@ -1,2 +1 @@
TODO
-====
View
256 adapters/dm-rest-adapter/fixtures/book_service/README
@@ -0,0 +1,256 @@
+== Welcome to Rails
+
+Rails is a web-application framework that includes everything needed to create
+database-backed web applications according to the Model-View-Control pattern.
+
+This pattern splits the view (also called the presentation) into "dumb" templates
+that are primarily responsible for inserting pre-built data in between HTML tags.
+The model contains the "smart" domain objects (such as Account, Product, Person,
+Post) that holds all the business logic and knows how to persist themselves to
+a database. The controller handles the incoming requests (such as Save New Account,
+Update Product, Show Post) by manipulating the model and directing data to the view.
+
+In Rails, the model is handled by what's called an object-relational mapping
+layer entitled Active Record. This layer allows you to present the data from
+database rows as objects and embellish these data objects with business logic
+methods. You can read more about Active Record in
+link:files/vendor/rails/activerecord/README.html.
+
+The controller and view are handled by the Action Pack, which handles both
+layers by its two parts: Action View and Action Controller. These two layers
+are bundled in a single package due to their heavy interdependence. This is
+unlike the relationship between the Active Record and Action Pack that is much
+more separate. Each of these packages can be used independently outside of
+Rails. You can read more about Action Pack in
+link:files/vendor/rails/actionpack/README.html.
+
+
+== Getting Started
+
+1. At the command prompt, start a new Rails application using the <tt>rails</tt> command
+ and your application name. Ex: rails myapp
+2. Change directory into myapp and start the web server: <tt>script/server</tt> (run with --help for options)
+3. Go to http://localhost:3000/ and get "Welcome aboard: You're riding the Rails!"
+4. Follow the guidelines to start developing your application
+
+
+== Web Servers
+
+By default, Rails will try to use Mongrel and lighttpd if they are installed, otherwise
+Rails will use WEBrick, the webserver that ships with Ruby. When you run script/server,
+Rails will check if Mongrel exists, then lighttpd and finally fall back to WEBrick. This ensures
+that you can always get up and running quickly.
+
+Mongrel is a Ruby-based webserver with a C component (which requires compilation) that is
+suitable for development and deployment of Rails applications. If you have Ruby Gems installed,
+getting up and running with mongrel is as easy as: <tt>gem install mongrel</tt>.
+More info at: http://mongrel.rubyforge.org
+
+If Mongrel is not installed, Rails will look for lighttpd. It's considerably faster than
+Mongrel and WEBrick and also suited for production use, but requires additional
+installation and currently only works well on OS X/Unix (Windows users are encouraged
+to start with Mongrel). We recommend version 1.4.11 and higher. You can download it from
+http://www.lighttpd.net.
+
+And finally, if neither Mongrel or lighttpd are installed, Rails will use the built-in Ruby
+web server, WEBrick. WEBrick is a small Ruby web server suitable for development, but not
+for production.
+
+But of course its also possible to run Rails on any platform that supports FCGI.
+Apache, LiteSpeed, IIS are just a few. For more information on FCGI,
+please visit: http://wiki.rubyonrails.com/rails/pages/FastCGI
+
+
+== Apache .htaccess example
+
+# General Apache options
+AddHandler fastcgi-script .fcgi
+AddHandler cgi-script .cgi
+Options +FollowSymLinks +ExecCGI
+
+# If you don't want Rails to look in certain directories,
+# use the following rewrite rules so that Apache won't rewrite certain requests
+#
+# Example:
+# RewriteCond %{REQUEST_URI} ^/notrails.*
+# RewriteRule .* - [L]
+
+# Redirect all requests not available on the filesystem to Rails
+# By default the cgi dispatcher is used which is very slow
+#
+# For better performance replace the dispatcher with the fastcgi one
+#
+# Example:
+# RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
+RewriteEngine On
+
+# If your Rails application is accessed via an Alias directive,
+# then you MUST also set the RewriteBase in this htaccess file.
+#
+# Example:
+# Alias /myrailsapp /path/to/myrailsapp/public
+# RewriteBase /myrailsapp
+
+RewriteRule ^$ index.html [QSA]
+RewriteRule ^([^.]+)$ $1.html [QSA]
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteRule ^(.*)$ dispatch.cgi [QSA,L]
+
+# In case Rails experiences terminal errors
+# Instead of displaying this message you can supply a file here which will be rendered instead
+#
+# Example:
+# ErrorDocument 500 /500.html
+
+ErrorDocument 500 "<h2>Application error</h2>Rails application failed to start properly"
+
+
+== Debugging Rails
+
+Sometimes your application goes wrong. Fortunately there are a lot of tools that
+will help you debug it and get it back on the rails.
+
+First area to check is the application log files. Have "tail -f" commands running
+on the server.log and development.log. Rails will automatically display debugging
+and runtime information to these files. Debugging info will also be shown in the
+browser on requests from 127.0.0.1.
+
+You can also log your own messages directly into the log file from your code using
+the Ruby logger class from inside your controllers. Example:
+
+ class WeblogController < ActionController::Base
+ def destroy
+ @weblog = Weblog.find(params[:id])
+ @weblog.destroy
+ logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
+ end
+ end
+
+The result will be a message in your log file along the lines of:
+
+ Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1
+
+More information on how to use the logger is at http://www.ruby-doc.org/core/
+
+Also, Ruby documentation can be found at http://www.ruby-lang.org/ including:
+
+* The Learning Ruby (Pickaxe) Book: http://www.ruby-doc.org/docs/ProgrammingRuby/
+* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
+
+These two online (and free) books will bring you up to speed on the Ruby language
+and also on programming in general.
+
+
+== Debugger
+
+Debugger support is available through the debugger command when you start your Mongrel or
+Webrick server with --debugger. This means that you can break out of execution at any point
+in the code, investigate and change the model, AND then resume execution!
+You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug'
+Example:
+
+ class WeblogController < ActionController::Base
+ def index
+ @posts = Post.find(:all)
+ debugger
+ end
+ end
+
+So the controller will accept the action, run the first line, then present you
+with a IRB prompt in the server window. Here you can do things like:
+
+ >> @posts.inspect
+ => "[#<Post:0x14a6be8 @attributes={\"title\"=>nil, \"body\"=>nil, \"id\"=>\"1\"}>,
+ #<Post:0x14a6620 @attributes={\"title\"=>\"Rails you know!\", \"body\"=>\"Only ten..\", \"id\"=>\"2\"}>]"
+ >> @posts.first.title = "hello from a debugger"
+ => "hello from a debugger"
+
+...and even better is that you can examine how your runtime objects actually work:
+
+ >> f = @posts.first
+ => #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>
+ >> f.
+ Display all 152 possibilities? (y or n)
+
+Finally, when you're ready to resume execution, you enter "cont"
+
+
+== Console
+
+You can interact with the domain model by starting the console through <tt>script/console</tt>.
+Here you'll have all parts of the application configured, just like it is when the
+application is running. You can inspect domain models, change values, and save to the
+database. Starting the script without arguments will launch it in the development environment.
+Passing an argument will specify a different environment, like <tt>script/console production</tt>.
+
+To reload your controllers and models after launching the console run <tt>reload!</tt>
+
+== dbconsole
+
+You can go to the command line of your database directly through <tt>script/dbconsole</tt>.
+You would be connected to the database with the credentials defined in database.yml.
+Starting the script without arguments will connect you to the development database. Passing an
+argument will connect you to a different database, like <tt>script/dbconsole production</tt>.
+Currently works for mysql, postgresql and sqlite.
+
+== Description of Contents
+
+app
+ Holds all the code that's specific to this particular application.
+
+app/controllers
+ Holds controllers that should be named like weblogs_controller.rb for
+ automated URL mapping. All controllers should descend from ApplicationController
+ which itself descends from ActionController::Base.
+
+app/models
+ Holds models that should be named like post.rb.
+ Most models will descend from ActiveRecord::Base.
+
+app/views
+ Holds the template files for the view that should be named like
+ weblogs/index.html.erb for the WeblogsController#index action. All views use eRuby
+ syntax.
+
+app/views/layouts
+ Holds the template files for layouts to be used with views. This models the common
+ header/footer method of wrapping views. In your views, define a layout using the
+ <tt>layout :default</tt> and create a file named default.html.erb. Inside default.html.erb,
+ call <% yield %> to render the view using this layout.
+
+app/helpers
+ Holds view helpers that should be named like weblogs_helper.rb. These are generated
+ for you automatically when using script/generate for controllers. Helpers can be used to
+ wrap functionality for your views into methods.
+
+config
+ Configuration files for the Rails environment, the routing map, the database, and other dependencies.
+
+db
+ Contains the database schema in schema.rb. db/migrate contains all
+ the sequence of Migrations for your schema.
+
+doc
+ This directory is where your application documentation will be stored when generated
+ using <tt>rake doc:app</tt>
+
+lib
+ Application specific libraries. Basically, any kind of custom code that doesn't
+ belong under controllers, models, or helpers. This directory is in the load path.
+
+public
+ The directory available for the web server. Contains subdirectories for images, stylesheets,
+ and javascripts. Also contains the dispatchers and the default HTML files. This should be
+ set as the DOCUMENT_ROOT of your web server.
+
+script
+ Helper scripts for automation and generation.
+
+test
+ Unit and functional tests along with fixtures. When using the script/generate scripts, template
+ test files will be generated for you and placed in this directory.
+
+vendor
+ External libraries that the application depends on. Also includes the plugins subdirectory.
+ If the app has frozen rails, those gems also go here, under vendor/rails/.
+ This directory is in the load path.
View
10 adapters/dm-rest-adapter/fixtures/book_service/Rakefile
@@ -0,0 +1,10 @@
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require(File.join(File.dirname(__FILE__), 'config', 'boot'))
+
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+require 'tasks/rails'
View
15 adapters/dm-rest-adapter/fixtures/book_service/app/controllers/application.rb
@@ -0,0 +1,15 @@
+# Filters added to this controller apply to all controllers in the application.
+# Likewise, all the methods added will be available for all controllers.
+
+class ApplicationController < ActionController::Base
+ helper :all # include all helpers, all the time
+
+ # See ActionController::RequestForgeryProtection for details
+ # Uncomment the :secret if you're not using the cookie session store
+ protect_from_forgery # :secret => 'fb23937b455a775732b021a8db838ba7'
+
+ # See ActionController::Base for details
+ # Uncomment this to filter the contents of submitted sensitive data parameters
+ # from your application log (in this case, all fields with names like "password").
+ # filter_parameter_logging :password
+end
View
85 adapters/dm-rest-adapter/fixtures/book_service/app/controllers/books_controller.rb
@@ -0,0 +1,85 @@
+class BooksController < ApplicationController
+ # GET /books
+ # GET /books.xml
+ def index
+ @books = Book.find(:all)
+
+ respond_to do |format|
+ format.html # index.html.erb
+ format.xml { render :xml => @books }
+ end
+ end
+
+ # GET /books/1
+ # GET /books/1.xml
+ def show
+ @book = Book.find(params[:id])
+
+ respond_to do |format|
+ format.html # show.html.erb
+ format.xml { render :xml => @book }
+ end
+ end
+
+ # GET /books/new
+ # GET /books/new.xml
+ def new
+ @book = Book.new
+
+ respond_to do |format|
+ format.html # new.html.erb
+ format.xml { render :xml => @book }
+ end
+ end
+
+ # GET /books/1/edit
+ def edit
+ @book = Book.find(params[:id])
+ end
+
+ # POST /books
+ # POST /books.xml
+ def create
+ @book = Book.new(params[:book])
+
+ respond_to do |format|
+ if @book.save
+ flash[:notice] = 'Book was successfully created.'
+ format.html { redirect_to(@book) }
+ format.xml { render :xml => @book, :status => :created, :location => @book }
+ else
+ format.html { render :action => "new" }
+ format.xml { render :xml => @book.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # PUT /books/1
+ # PUT /books/1.xml
+ def update
+ @book = Book.find(params[:id])
+
+ respond_to do |format|
+ if @book.update_attributes(params[:book])
+ flash[:notice] = 'Book was successfully updated.'
+ format.html { redirect_to(@book) }
+ format.xml { head :ok }
+ else
+ format.html { render :action => "edit" }
+ format.xml { render :xml => @book.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /books/1
+ # DELETE /books/1.xml
+ def destroy
+ @book = Book.find(params[:id])
+ @book.destroy
+
+ respond_to do |format|
+ format.html { redirect_to(books_url) }
+ format.xml { head :ok }
+ end
+ end
+end
View
89 adapters/dm-rest-adapter/fixtures/book_service/app/controllers/shelves_controller.rb
@@ -0,0 +1,89 @@
+class ShelvesController < ApplicationController
+ # GET /shelves
+ # GET /shelves.xml
+ def index
+ @shelves = Shelf.find(:all)
+
+ respond_to do |format|
+ format.html # index.html.erb
+ format.xml { render :xml => @shelves.to_xml(:include => :books) }
+ end
+ end
+
+ # GET /shelves/1
+ # GET /shelves/1.xml
+ def show
+ @shelf = Shelf.find(params[:id])
+
+ respond_to do |format|
+ format.html # show.html.erb
+ format.xml { render :xml => @shelf.to_xml(:include => :books) }
+ end
+ end
+
+ # GET /shelves/new
+ # GET /shelves/new.xml
+ def new
+ @shelf = Shelf.new
+
+ respond_to do |format|
+ format.html # new.html.erb
+ format.xml { render :xml => @shelf }
+ end
+ end
+
+ # GET /shelves/1/edit
+ def edit
+ @shelf = Shelf.find(params[:id], :include => :books)
+ respond_to do |format|
+ format.xml { render :xml => @shelf }
+ format.html
+ end
+ end
+
+ # POST /shelves
+ # POST /shelves.xml
+ def create
+ @shelf = Shelf.new(params[:shelf])
+
+ respond_to do |format|
+ if @shelf.save
+ flash[:notice] = 'Shelf was successfully created.'
+ format.html { redirect_to(@shelf) }
+ format.xml { render :xml => @shelf, :status => :created, :location => @shelf }
+ else
+ format.html { render :action => "new" }
+ format.xml { render :xml => @shelf.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # PUT /shelves/1
+ # PUT /shelves/1.xml
+ def update
+ @shelf = Shelf.find(params[:id])
+
+ respond_to do |format|
+ if @shelf.update_attributes(params[:shelf])
+ flash[:notice] = 'Shelf was successfully updated.'
+ format.html { redirect_to(@shelf) }
+ format.xml { head :ok }
+ else
+ format.html { render :action => "edit" }
+ format.xml { render :xml => @shelf.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /shelves/1
+ # DELETE /shelves/1.xml
+ def destroy
+ @shelf = Shelf.find(params[:id])
+ @shelf.destroy
+
+ respond_to do |format|
+ format.html { redirect_to(shelves_url) }
+ format.xml { head :ok }
+ end
+ end
+end
View
3 adapters/dm-rest-adapter/fixtures/book_service/app/helpers/application_helper.rb
@@ -0,0 +1,3 @@
+# Methods added to this helper will be available to all templates in the application.
+module ApplicationHelper
+end
View
2 adapters/dm-rest-adapter/fixtures/book_service/app/helpers/books_helper.rb
@@ -0,0 +1,2 @@
+module BooksHelper
+end
View
2 adapters/dm-rest-adapter/fixtures/book_service/app/helpers/shelf_helper.rb
@@ -0,0 +1,2 @@
+module ShelfHelper
+end
View
6 adapters/dm-rest-adapter/fixtures/book_service/app/models/book.rb
@@ -0,0 +1,6 @@
+class Book < ActiveRecord::Base
+ validates_presence_of :title
+ validates_presence_of :author
+
+ belongs_to :shelf
+end
View
5 adapters/dm-rest-adapter/fixtures/book_service/app/models/shelf.rb
@@ -0,0 +1,5 @@
+class Shelf < ActiveRecord::Base
+ validates_presence_of :name
+
+ has_many :books
+end
View
20 adapters/dm-rest-adapter/fixtures/book_service/app/views/books/edit.html.erb
@@ -0,0 +1,20 @@
+<h1>Editing book</h1>
+
+<% form_for(@book) do |f| %>
+ <%= f.error_messages %>
+
+ <p>
+ <%= f.label :title %><br />
+ <%= f.text_field :title %>
+ </p>
+ <p>
+ <%= f.label :author %><br />
+ <%= f.text_field :author %>
+ </p>
+ <p>
+ <%= f.submit "Update" %>
+ </p>
+<% end %>
+
+<%= link_to 'Show', @book %> |
+<%= link_to 'Back', books_path %>
View
22 adapters/dm-rest-adapter/fixtures/book_service/app/views/books/index.html.erb
@@ -0,0 +1,22 @@
+<h1>Listing books</h1>
+
+<table>
+ <tr>
+ <th>Title</th>
+ <th>Author</th>
+ </tr>
+
+<% for book in @books %>
+ <tr>
+ <td><%=h book.title %></td>
+ <td><%=h book.author %></td>
+ <td><%= link_to 'Show', book %></td>
+ <td><%= link_to 'Edit', edit_book_path(book) %></td>
+ <td><%= link_to 'Destroy', book, :confirm => 'Are you sure?', :method => :delete %></td>
+ </tr>
+<% end %>
+</table>
+
+<br />
+
+<%= link_to 'New book', new_book_path %>
View
19 adapters/dm-rest-adapter/fixtures/book_service/app/views/books/new.html.erb
@@ -0,0 +1,19 @@
+<h1>New book</h1>
+
+<% form_for(@book) do |f| %>
+ <%= f.error_messages %>
+
+ <p>
+ <%= f.label :title %><br />
+ <%= f.text_field :title %>
+ </p>
+ <p>
+ <%= f.label :author %><br />
+ <%= f.text_field :author %>
+ </p>
+ <p>
+ <%= f.submit "Create" %>
+ </p>
+<% end %>
+
+<%= link_to 'Back', books_path %>
View
13 adapters/dm-rest-adapter/fixtures/book_service/app/views/books/show.html.erb
@@ -0,0 +1,13 @@
+<p>
+ <b>Title:</b>
+ <%=h @book.title %>
+</p>
+
+<p>
+ <b>Author:</b>
+ <%=h @book.author %>
+</p>
+
+
+<%= link_to 'Edit', edit_book_path(@book) %> |
+<%= link_to 'Back', books_path %>
View
17 adapters/dm-rest-adapter/fixtures/book_service/app/views/layouts/books.html.erb
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+ <title>Books: <%= controller.action_name %></title>
+ <%= stylesheet_link_tag 'scaffold' %>
+</head>
+<body>
+
+<p style="color: green"><%= flash[:notice] %></p>
+
+<%= yield %>
+
+</body>