Rails 3 DRY Conditional Layout for iframes

2019-06-11 04:31发布

I was recently tasked with loading a portion of my Rails application within an iframe on another website. The relevant pages should be using a different layout file, but only if they're being rendered inside of the iframe. There was a solution proposed here Detect iframe request in a rails app that involved passing a query string parameter.

For example the requesting website could call my application through an iframe with the src of http://foo.com/bar?iframe=true. Then in our controller we could simply check:

def bar
  render :template => "iframe" if params[:iframe]
end

This seems like a good solution, but sadly that only works for the initial request as the original query string is completely static. Assuming we have accessible links to other routes within the iframe is there any way of easily relaying the iframe=true request parameter to maintain the correct iframe layout without having to repeat code? Basically I would like to take the DRYest approach possible without breaking any existing functionality. I considered creating another link_to helper which included the logic to relay this parameter if it exists and replacing all of my link_to calls throughout my application; I was wondering if anybody had a better approach though.

1条回答
Melony?
2楼-- · 2019-06-11 05:17

I decided to tackle this problem using JavaScript and added the following to my haml layout file:

:javascript
    for(i = 0; i< $('a').length; i++)
    {
      if($('a')[i].href.match(document.domain))
      {
        $('a')[i].href = $('a')[i].href + "?iframe=true";
      }
    }

This coupled with my server-side checks for the iframe param will ensure that the appropriate layout is loaded. I decided to only cater this functionality to users who enable JavaScript so it might not be the best solution. The only other problem with this approach lies in controller redirects and forms where I have to manually check for the iframe param and then forward it accordingly - not DRY at all, but I was at least able to put the logic into a controller method. If somebody knowns of a better solution please feel free to leave an answer.

查看更多
登录 后发表回答