允许用户将我的内容嵌入他们的网站(如博客) - rails 4

时间:2014-09-05 21:43:39

标签: javascript ruby-on-rails iframe embed embedding

我正在构建一个Rails 4应用程序,我想要做的是为我的用户提供通过可嵌入代码将我的内容嵌入他们自己的网站(如他们的博客)的选项。

换句话说,我希望有一个包含一些内容的erb页面,以及一个显示" Embed"的按钮。当用户点击它时,会出现一小部分可嵌入代码,可以将其复制并粘贴到他们的博客上等。这将显示我页面中的内容。

解决这个问题的最佳方式是什么?请尽可能具有描述性,因为我对此有点新鲜。谢谢!

1 个答案:

答案 0 :(得分:11)

<强>的iFrame

使用当前技术实现的方式通常是在客户端网站上使用从JS调用的iframe。您必须确保设置正确的CORS policy(以允许从远程站点进行连接)


以下是您从高层角度开展的工作:

#config/routes.rb
namespace :embed do
   resources :pages, only: :show, path: "" # -> domain.com/embed/1
end

这将为您提供所谓的endpoint - 您可以从客户网站(嵌入代码)中指出这些内容。从本质上讲,它将使您能够使用JS小部件与your_domain.com/embed/:blog_post_number

连接

然后可以使用相应的控制器处理:

#app/controllers/embed/pages_controller.rb
class PagesController < ApplicationController
   layout false
   def show
      @page = Page.find params[:id]
   end
end

#app/views/embed/pages/show.html.erb
<%= @page.title %>

这将呈现show控制器的pages方法,该方法将呈现没有布局的相应视图。这将无法自行执行任何操作,但如果您从javascript小部件中正确调用它,则可以在iFrame中显示它


<强> JS

因此,您需要一个小部件来嵌入&#34;你的代码。这样做的典型方法是创建一个javascript&#34;小部件&#34;它将驻留在您的服务器上(在public目录中)。然后,您会在用户嵌入代码时提示您调用此脚本:

#public/embed.js
window.onload = function() {

   //Params
   var scriptPram = document.getElementById('load_widget');
   var id = scriptPram.getAttribute('data-page');

   /iFrame
   var iframe = document.createElement('iframe');
   iframe.style.display = "none";
   iframe.src = "embed/" + id;
   document.body.appendChild(iframe);
};

然后,您将提示用户嵌入以下JS:

<script id="load_widget" src="http://domain.com/embed.js" data-page="1"></script>

这里是great resource

这里的底线目标是提供在用户网站上嵌入iframe的功能,最终会调用您的domain.com/embed/:id网址

上面的代码可能有点臃肿(Youtube只是让你直接将#34;裸体&#34; iframe放到你的网站上。您如何做到这将取决于您希望拥有的复杂性,以及您计划的任何未来可扩展性


<强> CORS

最后,您需要管理"CORS" (Cross Origin Resource Sharing policy)。这是一个标准协议,它基本上可以防止来自非原始域的任何XHR请求。

CORS的原因是它可以防止您的服务器受到XHR上的匿名请求的攻击。我不确定它的深层体系结构含义 - 但是您肯定需要确保在服务器上设置CORS策略以允许调用/显示嵌入页面。

在Rails中实现这一目标的最有效方法是使用RACK-CORS gem

#config/application.rb
config.middleware.use Rack::Cors do
  allow do
     origins '*'
     resource '/embed.js', :headers => :any, :methods => [:get, :post, :options] #-> I believe resource needs to be a specific URL - will have to check this
  end
end