instructure/lti_template_builder

View on GitHub
lib/lti_template_builder/recipes/lti_extension/template.erb

Summary

Maintainability
Test Coverage
inject_into_file "app/controllers/#{name}/lti_controller.rb", after: "def index\n" do <<-"RUBY"
      @launch_params = params.reject!{ |k,v| ['controller','action'].include? k }
    end

    def launch
      url = params[:url]
      if url && url =~ /\\Ahttps?:\\/\\/.+\\..+\\Z/
        redirect_to url
      else
        head 500
      end
    end

    def embed
      launch_params = JSON.parse(params[:launch_params] || "{}")

      tp = IMS::LTI::ToolProvider.new(nil, nil, launch_params)
      tp.extend IMS::LTI::Extensions::Content::ToolProvider

      # The following code is used as an example of content being returned.
      # This should be replaced by actual logic.
      embed_type = params[:embed_type]
      if embed_type =~ /Video/
        @content_type = "iframe"
        @title = "Getting Started in Canvas Network"
        @url = "https://player.vimeo.com/video/79702646"
        @width = "500"
        @height = "284"
      elsif embed_type =~ /Picture/
        @content_type = "image_url"
        @title = "Laughing Dog"
        @url = "https://dl.dropboxusercontent.com/u/2176587/laughing_dog.jpeg"
        @width = "284"
        @height = "177"
      elsif embed_type =~ /Link/
        @content_type = "url"
        @title  = "Edu App Center"
        @url    = "https://www.eduappcenter.com"
      end

      redirect_url = build_url(tp, @title, @url, @width, @height, @content_type)

      if redirect_url.present?
        redirect_to redirect_url
      end
    end

    def xml_config
      host = "\#{request.protocol}\#{request.host_with_port}"
      url = "\#{host}\#{root_path}"
      title = "#{name.humanize.titleize}"
      tool_id = "#{name}"
      tc = IMS::LTI::ToolConfig.new(:title => title, :launch_url => url)
      tc.extend IMS::LTI::Extensions::Canvas::ToolConfig
      tc.description = "[description goes here]"
      tc.canvas_privacy_anonymous!
      tc.canvas_domain!(request.host)
      tc.canvas_icon_url!("\#{host}/assets/#{name}/icon.png")
      tc.canvas_text!(title)
      tc.set_ext_param('canvas.instructure.com', :tool_id, tool_id)
<%= @additional_configs.join("\n") %>
      render xml: tc.to_xml
    end

    def health_check
      head 200
    end

    private

    def build_url(tp, title, url, width, height, content_type)
      if tp.accepts_content?
        redirect_url = nil
        if content_type == "image_url" && tp.accepts_url?
          redirect_url = tp.image_content_return_url(url, width, height, title)
        elsif content_type == "iframe" && tp.accepts_iframe?
          redirect_url = tp.iframe_content_return_url(url, width, height, title)
        elsif tp.accepts_url?
          redirect_url = tp.url_content_return_url(url, title, title)
        elsif tp.accepts_lti_launch_url?
          launch_url = launch_url(url: url)
          redirect_url = tp.lti_launch_content_return_url(launch_url, title, title)
        end
        return redirect_url
      end
RUBY
end

route 'root "lti#index"'
route 'match "/" => "lti#index", via: [:get, :post]'
route 'get "health_check" => "lti#health_check"'
route 'get "config(.xml)" => "lti#xml_config", as: :lti_xml_config'
route 'match  "launch" => "lti#launch", as: :launch, via: [:get, :post]'
route 'get "test/backdoor"'

remove_file "app/views/#{name}/lti/index.html.erb"
create_file "app/views/#{name}/lti/index.html.erb" do <<-'RUBY'
<div class="container">
  <h4 class="page-header">
    <%%= link_to "config.xml", lti_xml_config_path, class: "btn btn-xs btn-primary pull-right" %>
    <%%= image_tag "NAME/icon.png" %> My LTI App
  </h4>

  <p>
    This is an example of how you can select a resource and have it be embedded via LTI.
  </p>

  <%%= form_tag lti_embed_path do %>
    <input type="hidden" name="launch_params" value="<%%= @launch_params.to_json %>" />
    <div class="row">
      <div class="col-xs-4">
        <input type="submit" name="embed_type" class="btn btn-large btn-info btn-block"
               value="Embed a Video" />
      </div>
      <div class="col-xs-4">
        <input type="submit" name="embed_type" class="btn btn-large btn-success btn-block"
               value="Embed a Picture" />
      </div>
      <div class="col-xs-4">
        <input type="submit" name="embed_type" class="btn btn-large btn-warning btn-block"
               value="Embed a Link" />
      </div>
    </div>
  <%% end %>
</div>
RUBY
end

gsub_file "app/views/#{name}/lti/index.html.erb", "NAME", name

create_file "app/views/#{name}/lti/embed.html.erb" do <<-'RUBY'
<div class="container">
  <h4 class="page-header">Embed Code Generated</h4>
  <p>
    You're not in a system that supports auto-inserting content,
    so you'll need to copy and past the following code by hand
    in order to insert it into your content.
  </p>

  <textarea class="form-control" rows="4"><iframe title="<%%= @title %>" width="<%%= @width %>" height="<%%= @height %>" src="<%%= @url %>" /></textarea>
</div>
RUBY
end

inject_into_file "app/controllers/#{name}/lti_controller.rb", after: "require_dependency \"#{name}/application_controller\"\n" do <<-"RUBY"

require "ims/lti"
RUBY
end

gsub_file "spec/controllers/#{name}/lti_controller_spec.rb", "get 'index'\n", "get 'index', use_route: :#{name}\n"

route 'post "embed" => "lti#embed", as: :lti_embed'

inject_into_file "spec/controllers/#{name}/lti_controller_spec.rb", after: "response.should be_success\n      end\n" do <<-"RUBY"
      describe "GET config" do
        it "should generate a valid xml cartridge" do
          request.stub(:env).and_return({
            "SCRIPT_NAME"     => "/#{name}",
            "rack.url_scheme" => "http",
            "HTTP_HOST"       => "test.host",
            "PATH_INFO"       => "/#{name}"
          })
          get 'xml_config', use_route: :#{name}
          expect(response.body).to include('<blti:title>#{name.humanize.titleize}</blti:title>')
          expect(response.body).to include('<blti:description>[description goes here]</blti:description>')
          expect(response.body).to include('<lticm:property name="text">#{name.humanize.titleize}</lticm:property>')
          expect(response.body).to include('<lticm:property name="tool_id">#{name}</lticm:property>')
          expect(response.body).to include('<lticm:property name=\"icon_url\">http://test.host/assets/#{name}/icon.png</lticm:property>')
        end
      end
RUBY
end

inject_into_file "spec/controllers/#{name}/lti_controller_spec.rb", after: "icon.png</lticm:property>')" do <<-"RUBY"

<%= @extra_expects.join("\n") %>
RUBY
end

inside("app/assets/images/#{name}") do
  run "curl -O https://dl.dropboxusercontent.com/u/2176587/icon.png"
end