landable 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +15 -0
- data/MIT-LICENSE +20 -0
- data/README.md +56 -0
- data/Rakefile +22 -0
- data/app/controllers/concerns/landable/variables_concern.rb +38 -0
- data/app/controllers/landable/api/access_tokens_controller.rb +48 -0
- data/app/controllers/landable/api/assets_controller.rb +55 -0
- data/app/controllers/landable/api/categories_controller.rb +13 -0
- data/app/controllers/landable/api/directories_controller.rb +19 -0
- data/app/controllers/landable/api/page_revisions_controller.rb +38 -0
- data/app/controllers/landable/api/pages_controller.rb +96 -0
- data/app/controllers/landable/api/templates_controller.rb +33 -0
- data/app/controllers/landable/api/themes_controller.rb +57 -0
- data/app/controllers/landable/api_controller.rb +75 -0
- data/app/controllers/landable/application_controller.rb +4 -0
- data/app/controllers/landable/public/pages_controller.rb +25 -0
- data/app/controllers/landable/public/preview/page_revisions_controller.rb +16 -0
- data/app/controllers/landable/public/preview/pages_controller.rb +16 -0
- data/app/controllers/landable/public/sitemap_controller.rb +18 -0
- data/app/decorators/landable/null_page_decorator.rb +26 -0
- data/app/decorators/landable/page_decorator.rb +40 -0
- data/app/helpers/landable/application_helper.rb +13 -0
- data/app/helpers/landable/pages_helper.rb +20 -0
- data/app/models/concerns/landable/has_assets.rb +74 -0
- data/app/models/concerns/landable/table_name.rb +12 -0
- data/app/models/concerns/landable/traffic/table_name.rb +14 -0
- data/app/models/landable/access_token.rb +20 -0
- data/app/models/landable/asset.rb +63 -0
- data/app/models/landable/asset_search_engine.rb +20 -0
- data/app/models/landable/author.rb +12 -0
- data/app/models/landable/category.rb +27 -0
- data/app/models/landable/directory.rb +23 -0
- data/app/models/landable/page.rb +259 -0
- data/app/models/landable/page_revision.rb +74 -0
- data/app/models/landable/page_search_engine.rb +20 -0
- data/app/models/landable/search_engine.rb +39 -0
- data/app/models/landable/template.rb +24 -0
- data/app/models/landable/theme.rb +20 -0
- data/app/models/landable/traffic/access.rb +11 -0
- data/app/models/landable/traffic/ad_group.rb +11 -0
- data/app/models/landable/traffic/ad_type.rb +11 -0
- data/app/models/landable/traffic/attribution.rb +38 -0
- data/app/models/landable/traffic/bid_match_type.rb +11 -0
- data/app/models/landable/traffic/browser.rb +11 -0
- data/app/models/landable/traffic/campaign.rb +11 -0
- data/app/models/landable/traffic/city.rb +11 -0
- data/app/models/landable/traffic/content.rb +11 -0
- data/app/models/landable/traffic/cookie.rb +16 -0
- data/app/models/landable/traffic/country.rb +11 -0
- data/app/models/landable/traffic/creative.rb +11 -0
- data/app/models/landable/traffic/device.rb +11 -0
- data/app/models/landable/traffic/device_type.rb +11 -0
- data/app/models/landable/traffic/domain.rb +12 -0
- data/app/models/landable/traffic/event.rb +12 -0
- data/app/models/landable/traffic/event_type.rb +11 -0
- data/app/models/landable/traffic/experiment.rb +11 -0
- data/app/models/landable/traffic/http_method.rb +11 -0
- data/app/models/landable/traffic/ip_address.rb +11 -0
- data/app/models/landable/traffic/ip_lookup.rb +12 -0
- data/app/models/landable/traffic/keyword.rb +11 -0
- data/app/models/landable/traffic/location.rb +11 -0
- data/app/models/landable/traffic/match_type.rb +11 -0
- data/app/models/landable/traffic/medium.rb +11 -0
- data/app/models/landable/traffic/mime_type.rb +11 -0
- data/app/models/landable/traffic/network.rb +11 -0
- data/app/models/landable/traffic/owner.rb +10 -0
- data/app/models/landable/traffic/ownership.rb +10 -0
- data/app/models/landable/traffic/page_view.rb +24 -0
- data/app/models/landable/traffic/path.rb +13 -0
- data/app/models/landable/traffic/placement.rb +11 -0
- data/app/models/landable/traffic/platform.rb +11 -0
- data/app/models/landable/traffic/position.rb +11 -0
- data/app/models/landable/traffic/query_string.rb +12 -0
- data/app/models/landable/traffic/referer.rb +11 -0
- data/app/models/landable/traffic/region.rb +11 -0
- data/app/models/landable/traffic/search_term.rb +11 -0
- data/app/models/landable/traffic/source.rb +11 -0
- data/app/models/landable/traffic/target.rb +11 -0
- data/app/models/landable/traffic/user_agent.rb +28 -0
- data/app/models/landable/traffic/user_agent_type.rb +11 -0
- data/app/models/landable/traffic/visit.rb +15 -0
- data/app/models/landable/traffic/visitor.rb +13 -0
- data/app/responders/landable/api_responder.rb +76 -0
- data/app/responders/landable/page_render_responder.rb +15 -0
- data/app/serializers/landable/access_token_serializer.rb +6 -0
- data/app/serializers/landable/asset_serializer.rb +14 -0
- data/app/serializers/landable/author_serializer.rb +5 -0
- data/app/serializers/landable/category_serializer.rb +5 -0
- data/app/serializers/landable/directory_serializer.rb +8 -0
- data/app/serializers/landable/page_revision_serializer.rb +15 -0
- data/app/serializers/landable/page_serializer.rb +31 -0
- data/app/serializers/landable/template_serializer.rb +5 -0
- data/app/serializers/landable/theme_serializer.rb +7 -0
- data/app/services/landable/authentication_service.rb +44 -0
- data/app/services/landable/registration_service.rb +13 -0
- data/app/services/landable/render_service.rb +86 -0
- data/app/services/landable/tidy_service.rb +155 -0
- data/app/uploaders/landable/asset_uploader.rb +9 -0
- data/app/validators/path_validator.rb +12 -0
- data/app/validators/url_validator.rb +13 -0
- data/app/views/templates/preview.liquid +122 -0
- data/bin/rails +8 -0
- data/bin/redb +7 -0
- data/config.ru +7 -0
- data/config/cucumber.yml +5 -0
- data/config/routes.rb +62 -0
- data/db/migrate/20130510221424_create_landable_schema.rb +338 -0
- data/db/migrate/20130909182713_landable_pages__add_updated_by.rb +11 -0
- data/db/migrate/20130909182715_landable_page_revisions__break_out_snapshot.rb +72 -0
- data/db/migrate/20130909191153_landable_pages__add_lock_version.rb +5 -0
- data/db/migrate/20131002220041_file_based_themes.rb +12 -0
- data/db/migrate/20131008164204_create_head_tag_on_page.rb +19 -0
- data/db/migrate/20131008193544_drop_status_codes_model.rb +44 -0
- data/db/migrate/20131028145652_add_traffic_schema.rb +276 -0
- data/db/migrate/20131101213623_add_dnt_column_to_visits.rb +7 -0
- data/db/migrate/20131104224120_add_meta_on_events.rb +7 -0
- data/db/migrate/20131106185946_add_index_on_page_revisions_path.rb +6 -0
- data/db/migrate/20131106193021_page_revisisons__path_status_code_index.rb +9 -0
- data/db/migrate/20131108212501_traffic_owner_ids_are_serials.rb +20 -0
- data/db/migrate/20131121150902_add_attribution_id_to_unique_index.rb +10 -0
- data/db/migrate/20131216214027_drop_browser_screenshot_tables.rb +6 -0
- data/db/migrate/20140128170659_file_backed_templates.rb +8 -0
- data/db/migrate/20140205193757_fix_status_codes.rb +24 -0
- data/db/migrate/20140206211322_add_response_time_to_traffic_page_views.rb +7 -0
- data/db/migrate/20140220170324_add_slug_to_categories.rb +14 -0
- data/db/migrate/20140220174630_add_abstract_and_hero_asset_to_pages_and_page_revisions.rb +8 -0
- data/db/migrate/20140224205516_rename_traffic_schema.rb +40 -0
- data/db/pgtap/pgtap.sql +9034 -0
- data/db/test/landable.access_tokens.sql +13 -0
- data/db/test/landable.assets.sql +16 -0
- data/db/test/landable.authors.sql +22 -0
- data/db/test/landable.categories.sql +9 -0
- data/db/test/landable.page_revisions.sql +41 -0
- data/db/test/landable.pages.sql +19 -0
- data/db/test/landable.templates.sql +15 -0
- data/db/test/landable.themes.sql +25 -0
- data/doc/schema/access_token.json +22 -0
- data/doc/schema/asset.json +65 -0
- data/doc/schema/author.json +30 -0
- data/doc/schema/directory.json +24 -0
- data/doc/schema/page.json +95 -0
- data/doc/schema/page_revision.json +70 -0
- data/doc/schema/theme.json +37 -0
- data/doc/schema/uuid.json +6 -0
- data/features/api/access_tokens.feature +84 -0
- data/features/api/assets.feature +46 -0
- data/features/api/cors.feature +25 -0
- data/features/api/pages.feature +42 -0
- data/features/api/preview.feature +16 -0
- data/features/api/templates.feature +33 -0
- data/features/api/themes.feature +33 -0
- data/features/liquid/body.feature +35 -0
- data/features/liquid/drops/categories.feature +54 -0
- data/features/liquid/tags.feature +168 -0
- data/features/public/content_types.feature +17 -0
- data/features/public/publishing.feature +45 -0
- data/features/public/status_codes.feature +25 -0
- data/features/public/views.feature +17 -0
- data/features/step_definitions/asset_steps.rb +60 -0
- data/features/step_definitions/core_api_steps.rb +139 -0
- data/features/step_definitions/debug_steps.rb +3 -0
- data/features/step_definitions/factory_steps.rb +124 -0
- data/features/step_definitions/html_steps.rb +9 -0
- data/features/step_definitions/liquid_steps.rb +79 -0
- data/features/step_definitions/revision_steps.rb +5 -0
- data/features/step_definitions/theme_steps.rb +43 -0
- data/features/support/env.rb +66 -0
- data/features/support/usefulness.rb +13 -0
- data/landable.gemspec +54 -0
- data/lib/generators/landable/collection/collection_generator.rb +0 -0
- data/lib/generators/landable/collection/templates/stylesheets/landable/%file_name%.less +0 -0
- data/lib/generators/landable/collection/templates/stylesheets/landable/%file_name%/mixins.less +0 -0
- data/lib/generators/landable/collection/templates/stylesheets/landable/%file_name%/variables.less +0 -0
- data/lib/generators/landable/component/component_generator.rb +0 -0
- data/lib/generators/landable/component/templates/javascripts/landable/%file_name%.less +0 -0
- data/lib/generators/landable/component/templates/stylesheets/landable/%file_name%.less +0 -0
- data/lib/generators/landable/install_generator.rb +19 -0
- data/lib/generators/landable/landable_generator.rb +22 -0
- data/lib/generators/templates/landable.rb +34 -0
- data/lib/landable.rb +30 -0
- data/lib/landable/configuration.rb +115 -0
- data/lib/landable/core_ext/ipaddr.rb +18 -0
- data/lib/landable/engine.rb +69 -0
- data/lib/landable/error.rb +16 -0
- data/lib/landable/inflections.rb +4 -0
- data/lib/landable/layout.rb +60 -0
- data/lib/landable/liquid.rb +27 -0
- data/lib/landable/liquid/asset_tags.rb +76 -0
- data/lib/landable/liquid/drops.rb +46 -0
- data/lib/landable/liquid/filters.rb +11 -0
- data/lib/landable/liquid/tags.rb +91 -0
- data/lib/landable/migration.rb +40 -0
- data/lib/landable/mime_types.rb +15 -0
- data/lib/landable/partial.rb +46 -0
- data/lib/landable/seeds.rb +36 -0
- data/lib/landable/traffic.rb +34 -0
- data/lib/landable/traffic/crawl_tracker.rb +9 -0
- data/lib/landable/traffic/noop_tracker.rb +8 -0
- data/lib/landable/traffic/ping_tracker.rb +9 -0
- data/lib/landable/traffic/scan_tracker.rb +9 -0
- data/lib/landable/traffic/scrape_tracker.rb +9 -0
- data/lib/landable/traffic/tracker.rb +283 -0
- data/lib/landable/traffic/user_tracker.rb +65 -0
- data/lib/landable/version.rb +10 -0
- data/lib/tasks/landable/cucumber.rake +67 -0
- data/lib/tasks/landable/data.rake +166 -0
- data/lib/tasks/landable/pgtap.rake +26 -0
- data/lib/tasks/landable/rdoc.rake +11 -0
- data/lib/tasks/landable/seed.rake +16 -0
- data/lib/tasks/landable/spec.rake +15 -0
- data/script/cucumber +10 -0
- data/spec/concerns/landable/has_assets_spec.rb +75 -0
- data/spec/concerns/landable/table_name_spec.rb +15 -0
- data/spec/concerns/landable/traffic/table_name_spec.rb +16 -0
- data/spec/controllers/concerns/landable/variables_concern_spec.rb +66 -0
- data/spec/controllers/landable/api/assets_controller_spec.rb +24 -0
- data/spec/controllers/landable/api/categories_controller_spec.rb +45 -0
- data/spec/controllers/landable/api/directories_controller_spec.rb +56 -0
- data/spec/controllers/landable/api/page_revisions_controller_spec.rb +29 -0
- data/spec/controllers/landable/api/pages_controller_spec.rb +271 -0
- data/spec/controllers/landable/api_controller_spec.rb +189 -0
- data/spec/controllers/public/preview/page_revisions_controller_spec.rb +41 -0
- data/spec/controllers/public/preview/pages_controller_spec.rb +36 -0
- data/spec/controllers/public/sitemap_controller_spec.rb +25 -0
- data/spec/decorators/page_decorator_spec.rb +90 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/images/foo.jpg +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +10 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/controllers/priority_controller.rb +7 -0
- data/spec/dummy/app/helpers/application_helper.rb +5 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/app/views/layouts/priority.html.erb +18 -0
- data/spec/dummy/app/views/partials/_foobazz.html +1 -0
- data/spec/dummy/app/views/priority/show.html.erb +11 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +21 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +60 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +29 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/landable.rb +22 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/db/structure.sql +3736 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/public/404.html +58 -0
- data/spec/dummy/public/422.html +58 -0
- data/spec/dummy/public/500.html +57 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/asset.rb +29 -0
- data/spec/factories/authors.rb +12 -0
- data/spec/factories/category.rb +6 -0
- data/spec/factories/page_revision.rb +6 -0
- data/spec/factories/pages.rb +33 -0
- data/spec/factories/template.rb +13 -0
- data/spec/factories/theme.rb +14 -0
- data/spec/fixtures/assets/cthulhu.jpg +0 -0
- data/spec/fixtures/assets/panda.png +0 -0
- data/spec/fixtures/assets/sloth.png +0 -0
- data/spec/fixtures/assets/small.pdf +0 -0
- data/spec/helpers/pages_helper_spec.rb +35 -0
- data/spec/lib/landable/configuration_spec.rb +20 -0
- data/spec/lib/landable/layout_spec.rb +25 -0
- data/spec/lib/landable/liquid_spec.rb +24 -0
- data/spec/lib/landable/migration_spec.rb +51 -0
- data/spec/lib/landable/partial_spec.rb +84 -0
- data/spec/lib/landable/tracking_spec.rb +62 -0
- data/spec/lib/landable/traffic_spec.rb +45 -0
- data/spec/models/landable/access_token_spec.rb +13 -0
- data/spec/models/landable/asset_spec.rb +48 -0
- data/spec/models/landable/directory_spec.rb +36 -0
- data/spec/models/landable/page/errors_spec.rb +30 -0
- data/spec/models/landable/page_revision_spec.rb +75 -0
- data/spec/models/landable/page_spec.rb +377 -0
- data/spec/models/landable/template_spec.rb +47 -0
- data/spec/models/landable/theme_spec.rb +8 -0
- data/spec/responders/page_render_responder_spec.rb +43 -0
- data/spec/routing/public_page_route_spec.rb +36 -0
- data/spec/services/landable/authentication_service_spec.rb +61 -0
- data/spec/services/landable/render_service_spec.rb +103 -0
- data/spec/services/landable/tidy_service_spec.rb +157 -0
- data/spec/spec_helper.rb +38 -0
- data/spec/support/behaviors.rb +107 -0
- data/spec/support/carrier_wave.rb +17 -0
- data/spec/support/categories.yml +2 -0
- data/spec/support/helpers.rb +22 -0
- metadata +795 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
require "rack/cors"
|
2
|
+
require "active_model_serializers"
|
3
|
+
require "carrierwave"
|
4
|
+
require "rake"
|
5
|
+
|
6
|
+
module Landable
|
7
|
+
class Engine < ::Rails::Engine
|
8
|
+
isolate_namespace Landable
|
9
|
+
|
10
|
+
config.generators do |g|
|
11
|
+
g.test_framework :rspec
|
12
|
+
g.fixture_replacement :factory_girl, :dir => 'spec/factories'
|
13
|
+
end
|
14
|
+
|
15
|
+
initializer "landable.enable_cors" do |app|
|
16
|
+
config = Landable.configuration
|
17
|
+
if config.cors.enabled?
|
18
|
+
app.middleware.insert 0, Rack::Cors do
|
19
|
+
allow do
|
20
|
+
origins config.cors.origins
|
21
|
+
resource "#{config.api_namespace}/*",
|
22
|
+
methods: [:get, :post, :put, :patch, :delete],
|
23
|
+
headers: :any,
|
24
|
+
expose: 'X-Landable-Media-Type',
|
25
|
+
credentials: false,
|
26
|
+
max_age: 15.minutes
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
initializer "landable.json_schema" do |app|
|
33
|
+
if ENV['LANDABLE_VALIDATE_JSON']
|
34
|
+
require 'rack/schema'
|
35
|
+
app.middleware.use Rack::Schema
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
initializer "landable.seed_required" do |app|
|
40
|
+
Landable::Seeds.seed(:required) rescue nil
|
41
|
+
end
|
42
|
+
|
43
|
+
initializer "landable.create_themes" do |app|
|
44
|
+
Theme.create_from_layouts! rescue nil
|
45
|
+
end
|
46
|
+
|
47
|
+
initializer 'landable.create_templates' do |app|
|
48
|
+
Template.create_from_partials! rescue nil
|
49
|
+
end
|
50
|
+
|
51
|
+
initializer "landable.action_controller" do
|
52
|
+
ActiveSupport.on_load :action_controller do
|
53
|
+
# includes
|
54
|
+
include Landable::Traffic
|
55
|
+
include Landable::VariablesConcern
|
56
|
+
|
57
|
+
# helpers
|
58
|
+
helper Landable::PagesHelper
|
59
|
+
|
60
|
+
# tracking
|
61
|
+
if Landable.configuration.traffic_enabled
|
62
|
+
prepend_around_action :track_with_landable!
|
63
|
+
end
|
64
|
+
|
65
|
+
# end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Landable
|
2
|
+
class Error < StandardError
|
3
|
+
|
4
|
+
STATUS_CODE = 500
|
5
|
+
|
6
|
+
def initialize message = nil
|
7
|
+
message ||= "Status code: #{status_code} (Hint: rescue this in your ApplicationController)"
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def status_code
|
12
|
+
self.class::STATUS_CODE
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# TODO: Custom resolver for db themes: http://blog.jgarciam.net/post/21098440864/database-stored-templates-on-ruby-on-rails
|
2
|
+
# TODO: Multiple extentions with tilt
|
3
|
+
# TODO: Allow converting db-backed Theme to file-backed Theme
|
4
|
+
|
5
|
+
module Landable
|
6
|
+
class Layout
|
7
|
+
def initialize(file)
|
8
|
+
@file = file
|
9
|
+
end
|
10
|
+
|
11
|
+
def process
|
12
|
+
return if @processed
|
13
|
+
|
14
|
+
path = @file.dup
|
15
|
+
self.class.paths.each { |p| path.sub!(p, '') }
|
16
|
+
|
17
|
+
path.sub!(/^\//, '')
|
18
|
+
|
19
|
+
@path, @extension = path.split('.html.', 2)
|
20
|
+
|
21
|
+
@body = File.read(@file)
|
22
|
+
|
23
|
+
@processed = true
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_theme
|
27
|
+
process unless @processed
|
28
|
+
|
29
|
+
theme = Theme.where(file: @path).first_or_initialize
|
30
|
+
theme.name ||= @path.gsub('/', ' ').titlecase
|
31
|
+
theme.extension = @extension
|
32
|
+
theme.description = description if theme.description.blank? || theme.description =~ /^Defined in/
|
33
|
+
theme.body = @body
|
34
|
+
theme.editable = false
|
35
|
+
theme.thumbnail_url ||= "http://placehold.it/300x200"
|
36
|
+
|
37
|
+
theme.save!
|
38
|
+
|
39
|
+
theme
|
40
|
+
end
|
41
|
+
|
42
|
+
def description
|
43
|
+
"Defined in #@path.html.#@extension"
|
44
|
+
end
|
45
|
+
|
46
|
+
class << self
|
47
|
+
def all
|
48
|
+
files.map { |file| new(file) }
|
49
|
+
end
|
50
|
+
|
51
|
+
def files
|
52
|
+
paths.map { |path| Dir[path + "/**/[^_]*.html.*"] }.flatten
|
53
|
+
end
|
54
|
+
|
55
|
+
def paths
|
56
|
+
@paths ||= Dir[Rails.root.join('app/views/layouts').to_s]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'liquid'
|
2
|
+
|
3
|
+
require 'landable/liquid/tags'
|
4
|
+
require 'landable/liquid/asset_tags'
|
5
|
+
require 'landable/liquid/filters'
|
6
|
+
require 'landable/liquid/drops'
|
7
|
+
|
8
|
+
# Tag generators
|
9
|
+
Liquid::Template.register_tag('title_tag', Landable::Liquid::TitleTag)
|
10
|
+
Liquid::Template.register_tag('meta_tags', Landable::Liquid::MetaTag)
|
11
|
+
Liquid::Template.register_tag('head_content', Landable::Liquid::HeadContent)
|
12
|
+
Liquid::Template.register_tag('head', Landable::Liquid::Head)
|
13
|
+
Liquid::Template.register_tag('body', Landable::Liquid::Body)
|
14
|
+
|
15
|
+
%w(img_tag image_tag javascript_include_tag stylesheet_link_tag).each do |tag|
|
16
|
+
Liquid::Template.register_tag(tag, Landable::Liquid::AssetTag)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Only called tags so we can use a function-like syntax
|
20
|
+
Liquid::Template.register_tag('asset_url', Landable::Liquid::AssetAttributeTag)
|
21
|
+
Liquid::Template.register_tag('asset_description', Landable::Liquid::AssetAttributeTag)
|
22
|
+
|
23
|
+
# Template references
|
24
|
+
Liquid::Template.register_tag('template', Landable::Liquid::TemplateTag)
|
25
|
+
|
26
|
+
# Helpers
|
27
|
+
Liquid::Template.register_filter(Landable::Liquid::DefaultFilter)
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'action_view'
|
2
|
+
|
3
|
+
module Landable
|
4
|
+
module Liquid
|
5
|
+
|
6
|
+
class AssetTag < ::Liquid::Tag
|
7
|
+
attr_accessor :tag_name, :asset_name
|
8
|
+
|
9
|
+
# we'll be calling up to methods in here
|
10
|
+
include ActionView::Helpers::AssetTagHelper
|
11
|
+
|
12
|
+
# included for asset digest support
|
13
|
+
include Sprockets::Rails::Helper
|
14
|
+
|
15
|
+
def initialize(tag_name, param, tokens)
|
16
|
+
@tag_name = tag_name
|
17
|
+
@asset_name = param.strip
|
18
|
+
@tokens = tokens
|
19
|
+
end
|
20
|
+
|
21
|
+
def render(context)
|
22
|
+
tag_method = tag_name.to_sym
|
23
|
+
tag_method = :image_tag if tag_method == :img_tag
|
24
|
+
|
25
|
+
# if this matches an application asset, use that
|
26
|
+
if assets_environment[asset_name]
|
27
|
+
send tag_method, asset_name
|
28
|
+
|
29
|
+
# otherwise, find an asset of our own
|
30
|
+
else
|
31
|
+
asset = lookup_asset context, asset_name
|
32
|
+
|
33
|
+
options = {}
|
34
|
+
options[:alt] = asset.description if tag_method == :image_tag
|
35
|
+
|
36
|
+
send tag_method, asset.public_url, options
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
def lookup_asset(context, name)
|
43
|
+
assets = context.registers.fetch(:assets) do
|
44
|
+
raise ArgumentError.new("`assets' value was never registered with the template")
|
45
|
+
end
|
46
|
+
|
47
|
+
assets.fetch(name) do
|
48
|
+
raise ArgumentError.new("No `#{name}' asset available in #{assets.inspect}")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# stuff for sprockets
|
53
|
+
delegate :assets_prefix, :digest_assets, to: 'ActionView::Base'
|
54
|
+
|
55
|
+
# ActionView::Base.assets_environment will be nil if the pipeline is
|
56
|
+
# disabled - use this instead
|
57
|
+
def assets_environment
|
58
|
+
Rails.application.assets
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class AssetAttributeTag < AssetTag
|
63
|
+
def render(context)
|
64
|
+
asset = lookup_asset context, asset_name
|
65
|
+
attribute = tag_name.sub /^asset_/, ''
|
66
|
+
|
67
|
+
if attribute == 'url'
|
68
|
+
asset.public_url
|
69
|
+
else
|
70
|
+
asset.send attribute
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Drops are for lazy-loading content.
|
2
|
+
# - http://www.rubydoc.info/github/Shopify/liquid/Liquid/Drop
|
3
|
+
# - https://github.com/Shopify/liquid/blob/master/lib/liquid/drop.rb
|
4
|
+
|
5
|
+
module Landable
|
6
|
+
module Liquid
|
7
|
+
|
8
|
+
# CategoryProxy gives us these:
|
9
|
+
#
|
10
|
+
# {{ categories.size }}
|
11
|
+
#
|
12
|
+
# {% for category in categories %}
|
13
|
+
# {{ category.name }}: {{ category.pages.size }} pages
|
14
|
+
# {% endfor %}
|
15
|
+
#
|
16
|
+
# <h1>Blog posts</h1>
|
17
|
+
# <ul>
|
18
|
+
# {% for page in categories.blog.pages %}
|
19
|
+
# <li><a href="{{ page.url }}">{{ page.name }}</a></li>
|
20
|
+
# {% endfor %}
|
21
|
+
# </ul>
|
22
|
+
class CategoriesDrop < ::Liquid::Drop
|
23
|
+
|
24
|
+
def before_method method_name
|
25
|
+
category_cache[method_name] ||= ::Landable::Category.find_by_slug method_name
|
26
|
+
end
|
27
|
+
|
28
|
+
def size
|
29
|
+
@size ||= Category.count
|
30
|
+
end
|
31
|
+
|
32
|
+
def each &block
|
33
|
+
::Landable::Category.all.each &block
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
def category_cache
|
40
|
+
@category_cache ||= {}
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'action_view'
|
2
|
+
|
3
|
+
module Landable
|
4
|
+
module Liquid
|
5
|
+
|
6
|
+
class Tag < ::Liquid::Tag
|
7
|
+
include ActionView::Helpers::TagHelper
|
8
|
+
|
9
|
+
protected
|
10
|
+
def lookup_page(context)
|
11
|
+
context.registers.fetch(:page) do
|
12
|
+
raise ArgumentError.new("`page' value was never registered with the template")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class TitleTag < Tag
|
18
|
+
def render(context)
|
19
|
+
page = lookup_page context
|
20
|
+
content_tag(:title, page.title)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class MetaTag < Tag
|
25
|
+
def render(context)
|
26
|
+
page = lookup_page context
|
27
|
+
tags = page.meta_tags || {}
|
28
|
+
|
29
|
+
tags.map { |name, value|
|
30
|
+
tag(:meta, name: name, content: value)
|
31
|
+
}.join("\n")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class HeadContent < Tag
|
36
|
+
def render(context)
|
37
|
+
page = lookup_page context
|
38
|
+
|
39
|
+
page.head_content
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Head < Tag
|
44
|
+
def render(context)
|
45
|
+
page = lookup_page context
|
46
|
+
|
47
|
+
head = []
|
48
|
+
|
49
|
+
['title_tag', 'meta_tags', 'head_content'].each do |tag_name|
|
50
|
+
tag = eval("Landable::Liquid::#{tag_name.classify}").new(tag_name, nil, nil)
|
51
|
+
head << tag.render(context) if tag.render(context).present?
|
52
|
+
end
|
53
|
+
|
54
|
+
head.join("\n")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class Body < Tag
|
59
|
+
def render(context)
|
60
|
+
context.environments.first.fetch('body')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class TemplateTag < Tag
|
65
|
+
def initialize(tag, param, tokens)
|
66
|
+
param_tokens = param.split(/\s+/)
|
67
|
+
@template_slug = param_tokens.shift
|
68
|
+
@variables = Hash[param_tokens.join(' ').scan(/([\w_]+):\s+"([^"]*)"/)]
|
69
|
+
end
|
70
|
+
|
71
|
+
def render(context)
|
72
|
+
template = Landable::Template.find_by_slug @template_slug
|
73
|
+
|
74
|
+
if template
|
75
|
+
if template.partial?
|
76
|
+
if context.registers[:responder].present?
|
77
|
+
context.registers[:responder].controller.render_to_string(partial: template.file)
|
78
|
+
else
|
79
|
+
"<!-- render error: unable to render \"#{@template_slug}\", no controller/responder present -->"
|
80
|
+
end
|
81
|
+
else
|
82
|
+
::Liquid::Template.parse(template.body).render @variables
|
83
|
+
end
|
84
|
+
else
|
85
|
+
"<!-- render error: missing template \"#{@template_slug}\" -->"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Landable::Migration < ActiveRecord::Migration
|
2
|
+
class << self
|
3
|
+
def connection_search_path(conn)
|
4
|
+
conn.execute("SHOW SEARCH_PATH")[0]["search_path"]
|
5
|
+
end
|
6
|
+
|
7
|
+
def models
|
8
|
+
@models ||= begin
|
9
|
+
c = Landable.constants.map { |c| "Landable::#{c.to_s}".constantize }
|
10
|
+
c += Landable::Traffic.constants.map { |c| "Landable::Traffic::#{c.to_s}".constantize }
|
11
|
+
c.select { |c| c.kind_of? Class and c.ancestors.include? ActiveRecord::Base }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def clear_cache!
|
16
|
+
models.each &:reset_primary_key
|
17
|
+
ActiveRecord::Base.connection.schema_cache.clear!
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def exec_migration(conn, direction)
|
22
|
+
# come what may, keep the connection's schema search path intact
|
23
|
+
with_clean_connection(conn) do
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
# reset a few things, lest we pollute the way for those who follow
|
28
|
+
self.class.clear_cache!
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
def with_clean_connection(conn)
|
35
|
+
original_search_path = self.class.connection_search_path conn
|
36
|
+
yield
|
37
|
+
conn.schema_search_path = original_search_path
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|