landable 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/CHANGELOG.md +5 -0
  4. data/Gemfile +15 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.md +56 -0
  7. data/Rakefile +22 -0
  8. data/app/controllers/concerns/landable/variables_concern.rb +38 -0
  9. data/app/controllers/landable/api/access_tokens_controller.rb +48 -0
  10. data/app/controllers/landable/api/assets_controller.rb +55 -0
  11. data/app/controllers/landable/api/categories_controller.rb +13 -0
  12. data/app/controllers/landable/api/directories_controller.rb +19 -0
  13. data/app/controllers/landable/api/page_revisions_controller.rb +38 -0
  14. data/app/controllers/landable/api/pages_controller.rb +96 -0
  15. data/app/controllers/landable/api/templates_controller.rb +33 -0
  16. data/app/controllers/landable/api/themes_controller.rb +57 -0
  17. data/app/controllers/landable/api_controller.rb +75 -0
  18. data/app/controllers/landable/application_controller.rb +4 -0
  19. data/app/controllers/landable/public/pages_controller.rb +25 -0
  20. data/app/controllers/landable/public/preview/page_revisions_controller.rb +16 -0
  21. data/app/controllers/landable/public/preview/pages_controller.rb +16 -0
  22. data/app/controllers/landable/public/sitemap_controller.rb +18 -0
  23. data/app/decorators/landable/null_page_decorator.rb +26 -0
  24. data/app/decorators/landable/page_decorator.rb +40 -0
  25. data/app/helpers/landable/application_helper.rb +13 -0
  26. data/app/helpers/landable/pages_helper.rb +20 -0
  27. data/app/models/concerns/landable/has_assets.rb +74 -0
  28. data/app/models/concerns/landable/table_name.rb +12 -0
  29. data/app/models/concerns/landable/traffic/table_name.rb +14 -0
  30. data/app/models/landable/access_token.rb +20 -0
  31. data/app/models/landable/asset.rb +63 -0
  32. data/app/models/landable/asset_search_engine.rb +20 -0
  33. data/app/models/landable/author.rb +12 -0
  34. data/app/models/landable/category.rb +27 -0
  35. data/app/models/landable/directory.rb +23 -0
  36. data/app/models/landable/page.rb +259 -0
  37. data/app/models/landable/page_revision.rb +74 -0
  38. data/app/models/landable/page_search_engine.rb +20 -0
  39. data/app/models/landable/search_engine.rb +39 -0
  40. data/app/models/landable/template.rb +24 -0
  41. data/app/models/landable/theme.rb +20 -0
  42. data/app/models/landable/traffic/access.rb +11 -0
  43. data/app/models/landable/traffic/ad_group.rb +11 -0
  44. data/app/models/landable/traffic/ad_type.rb +11 -0
  45. data/app/models/landable/traffic/attribution.rb +38 -0
  46. data/app/models/landable/traffic/bid_match_type.rb +11 -0
  47. data/app/models/landable/traffic/browser.rb +11 -0
  48. data/app/models/landable/traffic/campaign.rb +11 -0
  49. data/app/models/landable/traffic/city.rb +11 -0
  50. data/app/models/landable/traffic/content.rb +11 -0
  51. data/app/models/landable/traffic/cookie.rb +16 -0
  52. data/app/models/landable/traffic/country.rb +11 -0
  53. data/app/models/landable/traffic/creative.rb +11 -0
  54. data/app/models/landable/traffic/device.rb +11 -0
  55. data/app/models/landable/traffic/device_type.rb +11 -0
  56. data/app/models/landable/traffic/domain.rb +12 -0
  57. data/app/models/landable/traffic/event.rb +12 -0
  58. data/app/models/landable/traffic/event_type.rb +11 -0
  59. data/app/models/landable/traffic/experiment.rb +11 -0
  60. data/app/models/landable/traffic/http_method.rb +11 -0
  61. data/app/models/landable/traffic/ip_address.rb +11 -0
  62. data/app/models/landable/traffic/ip_lookup.rb +12 -0
  63. data/app/models/landable/traffic/keyword.rb +11 -0
  64. data/app/models/landable/traffic/location.rb +11 -0
  65. data/app/models/landable/traffic/match_type.rb +11 -0
  66. data/app/models/landable/traffic/medium.rb +11 -0
  67. data/app/models/landable/traffic/mime_type.rb +11 -0
  68. data/app/models/landable/traffic/network.rb +11 -0
  69. data/app/models/landable/traffic/owner.rb +10 -0
  70. data/app/models/landable/traffic/ownership.rb +10 -0
  71. data/app/models/landable/traffic/page_view.rb +24 -0
  72. data/app/models/landable/traffic/path.rb +13 -0
  73. data/app/models/landable/traffic/placement.rb +11 -0
  74. data/app/models/landable/traffic/platform.rb +11 -0
  75. data/app/models/landable/traffic/position.rb +11 -0
  76. data/app/models/landable/traffic/query_string.rb +12 -0
  77. data/app/models/landable/traffic/referer.rb +11 -0
  78. data/app/models/landable/traffic/region.rb +11 -0
  79. data/app/models/landable/traffic/search_term.rb +11 -0
  80. data/app/models/landable/traffic/source.rb +11 -0
  81. data/app/models/landable/traffic/target.rb +11 -0
  82. data/app/models/landable/traffic/user_agent.rb +28 -0
  83. data/app/models/landable/traffic/user_agent_type.rb +11 -0
  84. data/app/models/landable/traffic/visit.rb +15 -0
  85. data/app/models/landable/traffic/visitor.rb +13 -0
  86. data/app/responders/landable/api_responder.rb +76 -0
  87. data/app/responders/landable/page_render_responder.rb +15 -0
  88. data/app/serializers/landable/access_token_serializer.rb +6 -0
  89. data/app/serializers/landable/asset_serializer.rb +14 -0
  90. data/app/serializers/landable/author_serializer.rb +5 -0
  91. data/app/serializers/landable/category_serializer.rb +5 -0
  92. data/app/serializers/landable/directory_serializer.rb +8 -0
  93. data/app/serializers/landable/page_revision_serializer.rb +15 -0
  94. data/app/serializers/landable/page_serializer.rb +31 -0
  95. data/app/serializers/landable/template_serializer.rb +5 -0
  96. data/app/serializers/landable/theme_serializer.rb +7 -0
  97. data/app/services/landable/authentication_service.rb +44 -0
  98. data/app/services/landable/registration_service.rb +13 -0
  99. data/app/services/landable/render_service.rb +86 -0
  100. data/app/services/landable/tidy_service.rb +155 -0
  101. data/app/uploaders/landable/asset_uploader.rb +9 -0
  102. data/app/validators/path_validator.rb +12 -0
  103. data/app/validators/url_validator.rb +13 -0
  104. data/app/views/templates/preview.liquid +122 -0
  105. data/bin/rails +8 -0
  106. data/bin/redb +7 -0
  107. data/config.ru +7 -0
  108. data/config/cucumber.yml +5 -0
  109. data/config/routes.rb +62 -0
  110. data/db/migrate/20130510221424_create_landable_schema.rb +338 -0
  111. data/db/migrate/20130909182713_landable_pages__add_updated_by.rb +11 -0
  112. data/db/migrate/20130909182715_landable_page_revisions__break_out_snapshot.rb +72 -0
  113. data/db/migrate/20130909191153_landable_pages__add_lock_version.rb +5 -0
  114. data/db/migrate/20131002220041_file_based_themes.rb +12 -0
  115. data/db/migrate/20131008164204_create_head_tag_on_page.rb +19 -0
  116. data/db/migrate/20131008193544_drop_status_codes_model.rb +44 -0
  117. data/db/migrate/20131028145652_add_traffic_schema.rb +276 -0
  118. data/db/migrate/20131101213623_add_dnt_column_to_visits.rb +7 -0
  119. data/db/migrate/20131104224120_add_meta_on_events.rb +7 -0
  120. data/db/migrate/20131106185946_add_index_on_page_revisions_path.rb +6 -0
  121. data/db/migrate/20131106193021_page_revisisons__path_status_code_index.rb +9 -0
  122. data/db/migrate/20131108212501_traffic_owner_ids_are_serials.rb +20 -0
  123. data/db/migrate/20131121150902_add_attribution_id_to_unique_index.rb +10 -0
  124. data/db/migrate/20131216214027_drop_browser_screenshot_tables.rb +6 -0
  125. data/db/migrate/20140128170659_file_backed_templates.rb +8 -0
  126. data/db/migrate/20140205193757_fix_status_codes.rb +24 -0
  127. data/db/migrate/20140206211322_add_response_time_to_traffic_page_views.rb +7 -0
  128. data/db/migrate/20140220170324_add_slug_to_categories.rb +14 -0
  129. data/db/migrate/20140220174630_add_abstract_and_hero_asset_to_pages_and_page_revisions.rb +8 -0
  130. data/db/migrate/20140224205516_rename_traffic_schema.rb +40 -0
  131. data/db/pgtap/pgtap.sql +9034 -0
  132. data/db/test/landable.access_tokens.sql +13 -0
  133. data/db/test/landable.assets.sql +16 -0
  134. data/db/test/landable.authors.sql +22 -0
  135. data/db/test/landable.categories.sql +9 -0
  136. data/db/test/landable.page_revisions.sql +41 -0
  137. data/db/test/landable.pages.sql +19 -0
  138. data/db/test/landable.templates.sql +15 -0
  139. data/db/test/landable.themes.sql +25 -0
  140. data/doc/schema/access_token.json +22 -0
  141. data/doc/schema/asset.json +65 -0
  142. data/doc/schema/author.json +30 -0
  143. data/doc/schema/directory.json +24 -0
  144. data/doc/schema/page.json +95 -0
  145. data/doc/schema/page_revision.json +70 -0
  146. data/doc/schema/theme.json +37 -0
  147. data/doc/schema/uuid.json +6 -0
  148. data/features/api/access_tokens.feature +84 -0
  149. data/features/api/assets.feature +46 -0
  150. data/features/api/cors.feature +25 -0
  151. data/features/api/pages.feature +42 -0
  152. data/features/api/preview.feature +16 -0
  153. data/features/api/templates.feature +33 -0
  154. data/features/api/themes.feature +33 -0
  155. data/features/liquid/body.feature +35 -0
  156. data/features/liquid/drops/categories.feature +54 -0
  157. data/features/liquid/tags.feature +168 -0
  158. data/features/public/content_types.feature +17 -0
  159. data/features/public/publishing.feature +45 -0
  160. data/features/public/status_codes.feature +25 -0
  161. data/features/public/views.feature +17 -0
  162. data/features/step_definitions/asset_steps.rb +60 -0
  163. data/features/step_definitions/core_api_steps.rb +139 -0
  164. data/features/step_definitions/debug_steps.rb +3 -0
  165. data/features/step_definitions/factory_steps.rb +124 -0
  166. data/features/step_definitions/html_steps.rb +9 -0
  167. data/features/step_definitions/liquid_steps.rb +79 -0
  168. data/features/step_definitions/revision_steps.rb +5 -0
  169. data/features/step_definitions/theme_steps.rb +43 -0
  170. data/features/support/env.rb +66 -0
  171. data/features/support/usefulness.rb +13 -0
  172. data/landable.gemspec +54 -0
  173. data/lib/generators/landable/collection/collection_generator.rb +0 -0
  174. data/lib/generators/landable/collection/templates/stylesheets/landable/%file_name%.less +0 -0
  175. data/lib/generators/landable/collection/templates/stylesheets/landable/%file_name%/mixins.less +0 -0
  176. data/lib/generators/landable/collection/templates/stylesheets/landable/%file_name%/variables.less +0 -0
  177. data/lib/generators/landable/component/component_generator.rb +0 -0
  178. data/lib/generators/landable/component/templates/javascripts/landable/%file_name%.less +0 -0
  179. data/lib/generators/landable/component/templates/stylesheets/landable/%file_name%.less +0 -0
  180. data/lib/generators/landable/install_generator.rb +19 -0
  181. data/lib/generators/landable/landable_generator.rb +22 -0
  182. data/lib/generators/templates/landable.rb +34 -0
  183. data/lib/landable.rb +30 -0
  184. data/lib/landable/configuration.rb +115 -0
  185. data/lib/landable/core_ext/ipaddr.rb +18 -0
  186. data/lib/landable/engine.rb +69 -0
  187. data/lib/landable/error.rb +16 -0
  188. data/lib/landable/inflections.rb +4 -0
  189. data/lib/landable/layout.rb +60 -0
  190. data/lib/landable/liquid.rb +27 -0
  191. data/lib/landable/liquid/asset_tags.rb +76 -0
  192. data/lib/landable/liquid/drops.rb +46 -0
  193. data/lib/landable/liquid/filters.rb +11 -0
  194. data/lib/landable/liquid/tags.rb +91 -0
  195. data/lib/landable/migration.rb +40 -0
  196. data/lib/landable/mime_types.rb +15 -0
  197. data/lib/landable/partial.rb +46 -0
  198. data/lib/landable/seeds.rb +36 -0
  199. data/lib/landable/traffic.rb +34 -0
  200. data/lib/landable/traffic/crawl_tracker.rb +9 -0
  201. data/lib/landable/traffic/noop_tracker.rb +8 -0
  202. data/lib/landable/traffic/ping_tracker.rb +9 -0
  203. data/lib/landable/traffic/scan_tracker.rb +9 -0
  204. data/lib/landable/traffic/scrape_tracker.rb +9 -0
  205. data/lib/landable/traffic/tracker.rb +283 -0
  206. data/lib/landable/traffic/user_tracker.rb +65 -0
  207. data/lib/landable/version.rb +10 -0
  208. data/lib/tasks/landable/cucumber.rake +67 -0
  209. data/lib/tasks/landable/data.rake +166 -0
  210. data/lib/tasks/landable/pgtap.rake +26 -0
  211. data/lib/tasks/landable/rdoc.rake +11 -0
  212. data/lib/tasks/landable/seed.rake +16 -0
  213. data/lib/tasks/landable/spec.rake +15 -0
  214. data/script/cucumber +10 -0
  215. data/spec/concerns/landable/has_assets_spec.rb +75 -0
  216. data/spec/concerns/landable/table_name_spec.rb +15 -0
  217. data/spec/concerns/landable/traffic/table_name_spec.rb +16 -0
  218. data/spec/controllers/concerns/landable/variables_concern_spec.rb +66 -0
  219. data/spec/controllers/landable/api/assets_controller_spec.rb +24 -0
  220. data/spec/controllers/landable/api/categories_controller_spec.rb +45 -0
  221. data/spec/controllers/landable/api/directories_controller_spec.rb +56 -0
  222. data/spec/controllers/landable/api/page_revisions_controller_spec.rb +29 -0
  223. data/spec/controllers/landable/api/pages_controller_spec.rb +271 -0
  224. data/spec/controllers/landable/api_controller_spec.rb +189 -0
  225. data/spec/controllers/public/preview/page_revisions_controller_spec.rb +41 -0
  226. data/spec/controllers/public/preview/pages_controller_spec.rb +36 -0
  227. data/spec/controllers/public/sitemap_controller_spec.rb +25 -0
  228. data/spec/decorators/page_decorator_spec.rb +90 -0
  229. data/spec/dummy/README.rdoc +28 -0
  230. data/spec/dummy/Rakefile +6 -0
  231. data/spec/dummy/app/assets/images/foo.jpg +0 -0
  232. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  233. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  234. data/spec/dummy/app/controllers/application_controller.rb +10 -0
  235. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  236. data/spec/dummy/app/controllers/priority_controller.rb +7 -0
  237. data/spec/dummy/app/helpers/application_helper.rb +5 -0
  238. data/spec/dummy/app/mailers/.keep +0 -0
  239. data/spec/dummy/app/models/.keep +0 -0
  240. data/spec/dummy/app/models/concerns/.keep +0 -0
  241. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  242. data/spec/dummy/app/views/layouts/priority.html.erb +18 -0
  243. data/spec/dummy/app/views/partials/_foobazz.html +1 -0
  244. data/spec/dummy/app/views/priority/show.html.erb +11 -0
  245. data/spec/dummy/bin/bundle +3 -0
  246. data/spec/dummy/bin/rails +4 -0
  247. data/spec/dummy/bin/rake +4 -0
  248. data/spec/dummy/config.ru +4 -0
  249. data/spec/dummy/config/application.rb +21 -0
  250. data/spec/dummy/config/boot.rb +5 -0
  251. data/spec/dummy/config/database.yml +60 -0
  252. data/spec/dummy/config/environment.rb +5 -0
  253. data/spec/dummy/config/environments/development.rb +29 -0
  254. data/spec/dummy/config/environments/production.rb +80 -0
  255. data/spec/dummy/config/environments/test.rb +42 -0
  256. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  257. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  258. data/spec/dummy/config/initializers/inflections.rb +16 -0
  259. data/spec/dummy/config/initializers/landable.rb +22 -0
  260. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  261. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  262. data/spec/dummy/config/initializers/session_store.rb +3 -0
  263. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  264. data/spec/dummy/config/locales/en.yml +23 -0
  265. data/spec/dummy/config/routes.rb +4 -0
  266. data/spec/dummy/db/structure.sql +3736 -0
  267. data/spec/dummy/lib/assets/.keep +0 -0
  268. data/spec/dummy/log/.keep +0 -0
  269. data/spec/dummy/public/404.html +58 -0
  270. data/spec/dummy/public/422.html +58 -0
  271. data/spec/dummy/public/500.html +57 -0
  272. data/spec/dummy/public/favicon.ico +0 -0
  273. data/spec/factories/asset.rb +29 -0
  274. data/spec/factories/authors.rb +12 -0
  275. data/spec/factories/category.rb +6 -0
  276. data/spec/factories/page_revision.rb +6 -0
  277. data/spec/factories/pages.rb +33 -0
  278. data/spec/factories/template.rb +13 -0
  279. data/spec/factories/theme.rb +14 -0
  280. data/spec/fixtures/assets/cthulhu.jpg +0 -0
  281. data/spec/fixtures/assets/panda.png +0 -0
  282. data/spec/fixtures/assets/sloth.png +0 -0
  283. data/spec/fixtures/assets/small.pdf +0 -0
  284. data/spec/helpers/pages_helper_spec.rb +35 -0
  285. data/spec/lib/landable/configuration_spec.rb +20 -0
  286. data/spec/lib/landable/layout_spec.rb +25 -0
  287. data/spec/lib/landable/liquid_spec.rb +24 -0
  288. data/spec/lib/landable/migration_spec.rb +51 -0
  289. data/spec/lib/landable/partial_spec.rb +84 -0
  290. data/spec/lib/landable/tracking_spec.rb +62 -0
  291. data/spec/lib/landable/traffic_spec.rb +45 -0
  292. data/spec/models/landable/access_token_spec.rb +13 -0
  293. data/spec/models/landable/asset_spec.rb +48 -0
  294. data/spec/models/landable/directory_spec.rb +36 -0
  295. data/spec/models/landable/page/errors_spec.rb +30 -0
  296. data/spec/models/landable/page_revision_spec.rb +75 -0
  297. data/spec/models/landable/page_spec.rb +377 -0
  298. data/spec/models/landable/template_spec.rb +47 -0
  299. data/spec/models/landable/theme_spec.rb +8 -0
  300. data/spec/responders/page_render_responder_spec.rb +43 -0
  301. data/spec/routing/public_page_route_spec.rb +36 -0
  302. data/spec/services/landable/authentication_service_spec.rb +61 -0
  303. data/spec/services/landable/render_service_spec.rb +103 -0
  304. data/spec/services/landable/tidy_service_spec.rb +157 -0
  305. data/spec/spec_helper.rb +38 -0
  306. data/spec/support/behaviors.rb +107 -0
  307. data/spec/support/carrier_wave.rb +17 -0
  308. data/spec/support/categories.yml +2 -0
  309. data/spec/support/helpers.rb +22 -0
  310. metadata +795 -0
@@ -0,0 +1,11 @@
1
+ class LandablePagesAddUpdatedBy < Landable::Migration
2
+ def change
3
+ add_column "#{Landable.configuration.database_schema_prefix}landable.pages", :updated_by_author_id, :uuid
4
+
5
+ execute <<-SQL
6
+ ALTER TABLE #{Landable.configuration.database_schema_prefix}landable.pages
7
+ ADD CONSTRAINT updated_author_fk FOREIGN KEY(updated_by_author_id)
8
+ REFERENCES #{Landable.configuration.database_schema_prefix}landable.authors(author_id)
9
+ SQL
10
+ end
11
+ end
@@ -0,0 +1,72 @@
1
+ require_dependency 'landable/page_revision'
2
+ class LandablePageRevisionsBreakOutSnapshot < Landable::Migration
3
+
4
+ class Landable::PageRevision < ActiveRecord::Base
5
+ store :snapshot_attributes, accessors: [:body]
6
+ end
7
+
8
+ def up
9
+
10
+ # Setup new columns
11
+ add_column "#{Landable.configuration.database_schema_prefix}landable.page_revisions", :theme_id, :uuid
12
+ add_column "#{Landable.configuration.database_schema_prefix}landable.page_revisions", :status_code_id, :uuid
13
+ add_column "#{Landable.configuration.database_schema_prefix}landable.page_revisions", :category_id, :uuid
14
+ add_column "#{Landable.configuration.database_schema_prefix}landable.page_revisions", :redirect_url, :text
15
+ add_column "#{Landable.configuration.database_schema_prefix}landable.page_revisions", :body, :text
16
+ add_column "#{Landable.configuration.database_schema_prefix}landable.page_revisions", :title, :text
17
+ add_column "#{Landable.configuration.database_schema_prefix}landable.page_revisions", :path, :text
18
+ add_column "#{Landable.configuration.database_schema_prefix}landable.page_revisions", :meta_tags, :hstore
19
+ add_column "#{Landable.configuration.database_schema_prefix}landable.page_revisions", :head_tags, :hstore
20
+
21
+ execute <<-SQL
22
+ ALTER TABLE #{Landable.configuration.database_schema_prefix}landable.page_revisions
23
+ ADD CONSTRAINT theme_id_fk FOREIGN KEY(theme_id)
24
+ REFERENCES #{Landable.configuration.database_schema_prefix}landable.themes(theme_id);
25
+
26
+ ALTER TABLE #{Landable.configuration.database_schema_prefix}landable.page_revisions
27
+ ADD CONSTRAINT status_code_id_fk FOREIGN KEY(status_code_id)
28
+ REFERENCES #{Landable.configuration.database_schema_prefix}landable.status_codes(status_code_id);
29
+
30
+ ALTER TABLE #{Landable.configuration.database_schema_prefix}landable.page_revisions
31
+ ADD CONSTRAINT category_id_fk FOREIGN KEY(category_id)
32
+ REFERENCES #{Landable.configuration.database_schema_prefix}landable.categories(category_id);
33
+ SQL
34
+
35
+ # Go through each record and copy snapshot into new, broken-out columns
36
+ Landable::PageRevision.all.each do |rev|
37
+ head_tags = {}
38
+ rev.title = rev.snapshot_attributes['title']
39
+ rev.body = rev.snapshot_attributes['body']
40
+ rev.status_code_id = rev.snapshot_attributes['status_code_id']
41
+ rev.category_id = rev.snapshot_attributes['category_id']
42
+ rev.theme_id = rev.snapshot_attributes['theme_id']
43
+ rev.redirect_url = rev.snapshot_attributes['redirect_url']
44
+ rev.path = rev.snapshot_attributes['path']
45
+ rev.meta_tags = rev.snapshot_attributes['meta_tags']
46
+ rev.snapshot_attributes['head_tags'].each do |tag|
47
+ head_tags[tag['head_tag_id']] = tag['content']
48
+ end
49
+ rev.head_tags = head_tags
50
+ rev.save!
51
+ end
52
+
53
+ # Remove snapshot column
54
+ remove_column "#{Landable.configuration.database_schema_prefix}landable.page_revisions", :snapshot_attributes
55
+
56
+ execute <<-SQL
57
+ DROP TRIGGER #{Landable.configuration.database_schema_prefix}landable_page_revisions__no_update ON #{Landable.configuration.database_schema_prefix}landable.page_revisions;
58
+
59
+ CREATE TRIGGER #{Landable.configuration.database_schema_prefix}landable_page_revisions__no_update
60
+ BEFORE UPDATE OF notes, is_minor, page_id, author_id, created_at, ordinal
61
+ , theme_id, status_code_id, category_id, redirect_url, body
62
+ , title, path, meta_tags, head_tags
63
+ ON #{Landable.configuration.database_schema_prefix}landable.page_revisions
64
+ FOR EACH STATEMENT EXECUTE PROCEDURE #{Landable.configuration.database_schema_prefix}landable.tg_disallow();
65
+ SQL
66
+
67
+ end
68
+
69
+ def down
70
+ raise ActiveRecord::IrreversibleMigration
71
+ end
72
+ end
@@ -0,0 +1,5 @@
1
+ class LandablePagesAddLockVersion < Landable::Migration
2
+ def change
3
+ add_column "#{Landable.configuration.database_schema_prefix}landable.pages", :lock_version, :integer, default: 0, null: false
4
+ end
5
+ end
@@ -0,0 +1,12 @@
1
+ class FileBasedThemes < Landable::Migration
2
+ def up
3
+ change_table "#{Landable.configuration.database_schema_prefix}landable.themes" do |t|
4
+ t.text :file
5
+ t.text :extension
6
+ t.boolean :editable, null: false, default: true
7
+ end
8
+
9
+ execute "CREATE UNIQUE INDEX #{Landable.configuration.database_schema_prefix}landable_themes__u_file
10
+ ON #{Landable.configuration.database_schema_prefix}landable.themes(lower(file))"
11
+ end
12
+ end
@@ -0,0 +1,19 @@
1
+ class CreateHeadTagOnPage < Landable::Migration
2
+ def up
3
+ execute "DROP TRIGGER #{Landable.configuration.database_schema_prefix}landable_page_revisions__no_update
4
+ ON #{Landable.configuration.database_schema_prefix}landable.page_revisions"
5
+
6
+ drop_table "#{Landable.configuration.database_schema_prefix}landable.head_tags"
7
+ remove_column "#{Landable.configuration.database_schema_prefix}landable.page_revisions", :head_tags
8
+
9
+ add_column "#{Landable.configuration.database_schema_prefix}landable.pages", :head_content, :text
10
+ add_column "#{Landable.configuration.database_schema_prefix}landable.page_revisions", :head_content, :text
11
+
12
+ execute "CREATE TRIGGER #{Landable.configuration.database_schema_prefix}landable_page_revisions__no_update
13
+ BEFORE UPDATE OF notes, is_minor, page_id, author_id, created_at, ordinal
14
+ , theme_id, status_code_id, category_id, redirect_url, body
15
+ , title, path, meta_tags, head_content
16
+ ON #{Landable.configuration.database_schema_prefix}landable.page_revisions
17
+ FOR EACH STATEMENT EXECUTE PROCEDURE #{Landable.configuration.database_schema_prefix}landable.tg_disallow();"
18
+ end
19
+ end
@@ -0,0 +1,44 @@
1
+ require_dependency 'landable/page'
2
+ class DropStatusCodesModel < Landable::Migration
3
+
4
+ class Landable::StatusCode < ActiveRecord::Base
5
+ self.table_name = "#{Landable.configuration.database_schema_prefix}landable.status_codes"
6
+ end
7
+
8
+ def change
9
+ # Add the column
10
+ add_column "#{Landable.configuration.database_schema_prefix}landable.pages", :status_code, :integer, null: false, default: 200, limit: 2
11
+ add_column "#{Landable.configuration.database_schema_prefix}landable.page_revisions", :status_code, :integer, limit: 2
12
+
13
+ # Backfill existing pages
14
+ Landable::Page.all.each do |page|
15
+ page.status_code = Landable::StatusCode.where(status_code_id: page.status_code_id).first.code
16
+ page.save!
17
+ end
18
+
19
+ # Backfill existing pages
20
+ Landable::PageRevision.all.each do |rev|
21
+ rev.status_code = Landable::StatusCode.where(status_code_id: rev.status_code_id).first.code
22
+ rev.save!
23
+ end
24
+
25
+ # Remove constraints, update trigger
26
+ execute <<-SQL
27
+ ALTER TABLE #{Landable.configuration.database_schema_prefix}landable.pages DROP CONSTRAINT status_code_fk;
28
+ ALTER TABLE #{Landable.configuration.database_schema_prefix}landable.page_revisions DROP CONSTRAINT status_code_id_fk;
29
+ DROP TRIGGER #{Landable.configuration.database_schema_prefix}landable_page_revisions__no_update
30
+ ON #{Landable.configuration.database_schema_prefix}landable.page_revisions;
31
+ CREATE TRIGGER #{Landable.configuration.database_schema_prefix}landable_page_revisions__no_update
32
+ BEFORE UPDATE OF notes, is_minor, page_id, author_id, created_at, ordinal
33
+ , theme_id, status_code, category_id, redirect_url, body
34
+ ON #{Landable.configuration.database_schema_prefix}landable.page_revisions
35
+ FOR EACH STATEMENT EXECUTE PROCEDURE #{Landable.configuration.database_schema_prefix}landable.tg_disallow();
36
+ SQL
37
+
38
+ # Remove tables, columns
39
+ remove_column "#{Landable.configuration.database_schema_prefix}landable.pages", :status_code_id
40
+ remove_column "#{Landable.configuration.database_schema_prefix}landable.page_revisions", :status_code_id
41
+ drop_table "#{Landable.configuration.database_schema_prefix}landable.status_codes"
42
+ drop_table "#{Landable.configuration.database_schema_prefix}landable.status_code_categories"
43
+ end
44
+ end
@@ -0,0 +1,276 @@
1
+ class AddTrafficSchema < Landable::Migration
2
+ # "owners"."owner" records your application's user/account/person identifier.
3
+ # Change the following line if your identifiers' data type is not INTEGER.
4
+
5
+ OWNER_TYPE = 'INTEGER'
6
+
7
+ QUERY_PARAMS = %w[
8
+ ad_type
9
+ ad_group
10
+ bid_match_type
11
+ campaign
12
+ content
13
+ creative
14
+ device_type
15
+ experiment
16
+ keyword
17
+ match_type
18
+ medium
19
+ network
20
+ placement
21
+ position
22
+ search_term
23
+ source
24
+ target
25
+ ]
26
+
27
+ def up
28
+ # Resources
29
+ #
30
+ # Measuring and Tracking Success: http://moz.com/beginners-guide-to-seo/measuring-and-tracking-success
31
+
32
+ # Query String
33
+ #
34
+ # keywords: http://cyrusshepard.com/7-fantastic-seo-tips-for-googles-not-provided-keywords/
35
+
36
+ execute "CREATE SCHEMA #{Landable.configuration.database_schema_prefix}landable_traffic;"
37
+
38
+ with_options schema: "#{Landable.configuration.database_schema_prefix}landable_traffic" do |t|
39
+ # Query Params
40
+ t.create_lookup_tables(*QUERY_PARAMS.map(&:pluralize))
41
+
42
+ # User Agent
43
+ t.create_lookup_tables :user_agent_types, :browsers, :devices, :platforms
44
+
45
+ # HTTP
46
+ t.create_lookup_tables :domains, :paths, :query_strings
47
+ t.create_lookup_tables :http_methods, :mime_types
48
+
49
+ t.create_lookup_table :event_types
50
+
51
+ # IP / Geolocation
52
+ t.create_lookup_table :ip_addresses, lookup_type: :inet
53
+ t.create_lookup_tables :countries, :regions, :cities
54
+ end
55
+
56
+ execute <<-SQL
57
+ SET search_path TO #{Landable.configuration.database_schema_prefix}landable_traffic,public;
58
+
59
+ ALTER TABLE mime_types ALTER COLUMN mime_type_id SET DATA TYPE SMALLINT;
60
+ ALTER TABLE http_methods ALTER COLUMN http_method_id SET DATA TYPE SMALLINT;
61
+
62
+ ALTER TABLE user_agent_types ALTER COLUMN user_agent_type_id SET DATA TYPE SMALLINT;
63
+ ALTER TABLE platforms ALTER COLUMN platform_id SET DATA TYPE SMALLINT;
64
+ ALTER TABLE browsers ALTER COLUMN browser_id SET DATA TYPE SMALLINT;
65
+
66
+ INSERT INTO user_agent_types (user_agent_type) VALUES ('user'), ('ping'), ('crawl'), ('scrape'), ('scan');
67
+
68
+ CREATE TABLE user_agents (
69
+ user_agent_id SERIAL PRIMARY KEY
70
+
71
+ , user_agent_type_id SMALLINT REFERENCES user_agent_types
72
+
73
+ , device_id INTEGER REFERENCES devices
74
+ , platform_id SMALLINT REFERENCES platforms
75
+ , browser_id SMALLINT REFERENCES browsers
76
+ , browser_version TEXT
77
+
78
+ , user_agent TEXT NOT NULL UNIQUE
79
+
80
+ , created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
81
+ );
82
+
83
+ CREATE INDEX ON user_agents (device_id);
84
+ CREATE INDEX ON user_agents (platform_id);
85
+ CREATE INDEX ON user_agents (browser_id);
86
+
87
+ ALTER TABLE ad_types ALTER COLUMN ad_type_id SET DATA TYPE SMALLINT;
88
+ ALTER TABLE bid_match_types ALTER COLUMN bid_match_type_id SET DATA TYPE SMALLINT;
89
+ ALTER TABLE device_types ALTER COLUMN device_type_id SET DATA TYPE SMALLINT;
90
+ ALTER TABLE match_types ALTER COLUMN match_type_id SET DATA TYPE SMALLINT;
91
+ ALTER TABLE positions ALTER COLUMN position_id SET DATA TYPE SMALLINT;
92
+
93
+ -- TODO: aceid AdWords Campaign Experiment ID
94
+ CREATE TABLE attributions (
95
+ attribution_id SERIAL PRIMARY KEY
96
+
97
+ , #{QUERY_PARAMS.map { |name| "%s INTEGER REFERENCES %s" % [name.foreign_key, name.pluralize] }.join(',') }
98
+
99
+ , created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
100
+
101
+ , UNIQUE (#{QUERY_PARAMS.map(&:foreign_key).join(',')})
102
+ );
103
+
104
+ ALTER TABLE attributions
105
+ ALTER COLUMN ad_type_id SET DATA TYPE SMALLINT
106
+ , ALTER COLUMN bid_match_type_id SET DATA TYPE SMALLINT
107
+ , ALTER COLUMN device_type_id SET DATA TYPE SMALLINT
108
+ , ALTER COLUMN match_type_id SET DATA TYPE SMALLINT
109
+ , ALTER COLUMN position_id SET DATA TYPE SMALLINT
110
+ ;
111
+
112
+ #{QUERY_PARAMS.map { |p| "CREATE INDEX ON attributions (#{p.foreign_key});" }.join("\n")}
113
+
114
+ CREATE TABLE referers (
115
+ referer_id SERIAL PRIMARY KEY
116
+
117
+ , domain_id INTEGER NOT NULL REFERENCES domains
118
+ , path_id INTEGER NOT NULL REFERENCES paths
119
+ , query_string_id INTEGER NOT NULL REFERENCES query_strings
120
+
121
+ , attribution_id INTEGER NOT NULL REFERENCES attributions
122
+
123
+ , UNIQUE (domain_id, path_id, query_string_id)
124
+ );
125
+
126
+ CREATE INDEX ON referers (domain_id);
127
+ CREATE INDEX ON referers (path_id);
128
+ CREATE INDEX ON referers (query_string_id);
129
+
130
+ CREATE TABLE locations (
131
+ location_id SERIAL PRIMARY KEY
132
+
133
+ , country_id INTEGER REFERENCES countries
134
+ , region_id INTEGER REFERENCES regions
135
+ , city_id INTEGER REFERENCES cities
136
+
137
+ , UNIQUE (country_id, region_id, city_id)
138
+ );
139
+
140
+ CREATE INDEX ON locations (country_id);
141
+ CREATE INDEX ON locations (region_id);
142
+ CREATE INDEX ON locations (city_id);
143
+
144
+ CREATE TABLE ip_lookups (
145
+ ip_lookup_id SERIAL PRIMARY KEY
146
+
147
+ , ip_address_id INTEGER NOT NULL REFERENCES ip_addresses
148
+ , domain_id INTEGER REFERENCES domains
149
+ , location_id INTEGER REFERENCES locations
150
+
151
+ , latitude REAL
152
+ , longitude REAL
153
+
154
+ , created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
155
+ );
156
+
157
+ CREATE INDEX ON ip_lookups (ip_address_id);
158
+ CREATE INDEX ON ip_lookups (domain_id);
159
+ CREATE INDEX ON ip_lookups (location_id);
160
+
161
+
162
+ -- User Traffic
163
+
164
+ CREATE TABLE cookies (
165
+ cookie_id UUID PRIMARY KEY DEFAULT uuid_generate_v4()
166
+ );
167
+
168
+ CREATE TABLE owners (
169
+ owner_id INTEGER PRIMARY KEY
170
+ , owner #{OWNER_TYPE} NOT NULL UNIQUE
171
+ );
172
+
173
+ CREATE TABLE ownerships (
174
+ owner_id INTEGER NOT NULL REFERENCES owners
175
+ , cookie_id UUID NOT NULL REFERENCES cookies
176
+
177
+ , PRIMARY KEY (owner_id, cookie_id)
178
+ );
179
+
180
+ CREATE TABLE visitors (
181
+ visitor_id SERIAL PRIMARY KEY
182
+
183
+ , ip_address_id INTEGER NOT NULL REFERENCES ip_addresses
184
+ , user_agent_id INTEGER NOT NULL REFERENCES user_agents
185
+
186
+ , UNIQUE (ip_address_id, user_agent_id)
187
+ );
188
+
189
+ CREATE INDEX ON visitors (user_agent_id);
190
+
191
+ CREATE TABLE visits (
192
+ visit_id SERIAL PRIMARY KEY
193
+
194
+ , cookie_id UUID NOT NULL REFERENCES cookies
195
+
196
+ , visitor_id INTEGER NOT NULL REFERENCES visitors
197
+ , attribution_id INTEGER NOT NULL REFERENCES attributions
198
+
199
+ , referer_id INTEGER REFERENCES referers
200
+ , owner_id INTEGER REFERENCES owners
201
+
202
+ , created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
203
+ );
204
+
205
+ CREATE INDEX ON visits (cookie_id);
206
+ CREATE INDEX ON visits (visitor_id);
207
+ CREATE INDEX ON visits (attribution_id);
208
+ CREATE INDEX ON visits (referer_id);
209
+ CREATE INDEX ON visits (owner_id);
210
+
211
+ CREATE TABLE page_views (
212
+ page_view_id SERIAL PRIMARY KEY
213
+
214
+ , visit_id INTEGER NOT NULL REFERENCES visits
215
+ , path_id INTEGER NOT NULL REFERENCES paths
216
+ , query_string_id INTEGER NOT NULL REFERENCES query_strings
217
+
218
+ , mime_type_id SMALLINT NOT NULL REFERENCES mime_types
219
+ , http_method_id SMALLINT NOT NULL REFERENCES http_methods
220
+
221
+ , page_revision_id UUID REFERENCES #{Landable.configuration.database_schema_prefix}landable.page_revisions
222
+ , request_id UUID
223
+
224
+ , click_id TEXT
225
+
226
+ , content_length INTEGER
227
+ , http_status INTEGER
228
+
229
+ , created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
230
+ );
231
+
232
+ CREATE INDEX ON page_views (visit_id);
233
+ CREATE INDEX ON page_views (path_id);
234
+ CREATE INDEX ON page_views (query_string_id);
235
+ CREATE INDEX ON page_views (page_revision_id);
236
+ CREATE INDEX ON page_views (request_id);
237
+ CREATE INDEX ON page_views (click_id);
238
+
239
+ CREATE TABLE events (
240
+ event_id SERIAL PRIMARY KEY
241
+
242
+ , event_type_id INTEGER NOT NULL REFERENCES event_types
243
+ , visit_id INTEGER NOT NULL REFERENCES visits
244
+
245
+ , created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
246
+ );
247
+
248
+ CREATE INDEX ON events (event_type_id);
249
+ CREATE INDEX ON events (visit_id);
250
+
251
+
252
+ -- TODO: visit frequency
253
+ CREATE TABLE accesses (
254
+ access_id SERIAL PRIMARY KEY
255
+
256
+ , path_id INTEGER NOT NULL REFERENCES paths
257
+ , visitor_id INTEGER NOT NULL REFERENCES visitors
258
+
259
+ , last_accessed_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
260
+
261
+ , UNIQUE (path_id, visitor_id)
262
+ );
263
+
264
+ CREATE INDEX ON accesses (visitor_id);
265
+
266
+ INSERT INTO bid_match_types (bid_match_type) VALUES ('bidded broad'), ('bidded content'), ('bidded exact'), ('bidded phrase');
267
+ INSERT INTO device_types (device_type) VALUES ('computer'), ('mobile'), ('tablet');
268
+ INSERT INTO match_types (match_type) VALUES ('broad'), ('phrase'), ('exact');
269
+ INSERT INTO networks (network) VALUES ('google_search'), ('search_partner'), ('display_network');
270
+
271
+ -- Views
272
+ -- * visits from non-user user_agents
273
+ -- * visits from real user_agents on ips with non-user visits
274
+ SQL
275
+ end
276
+ end