How to override erb with liquid? - ruby-on-rails

I've added a theming directory to my app as described here, using prepend_view_path. It works as expected. I can now add a view structure in my app under app/themes/my_theme/views
Now, I want to be able to override erb templates by dropping in a
.liquid file, which will render right off the controller action.
For example, I want to override app/views/pages/home.html.erb:
<h1><%= t 'it_works' %></h1>
...with app/themes/my_theme/views/pages/home.liquid
<h1>It works with {{ "liquid" }}</h1>
I don't want to have to specify an array of view paths (upkeep would be awful), but just add .liquid as a layer to the templating engine. Maybe, however, have a blacklist of protected views that cannot be overridden (such as app/views/admin/*)

Do you have a liquid template handler? Otherwise Rails won't know what you want to do with .liquid files. See this blog post: http://royvandermeij.com/blog/2011/09/21/create-a-liquid-handler-for-rails-3-dot-1/
For your second question: not using a theme for app/views/admin/* you should make sure you have an AdminController that does not prepend_view_path.

According to the documentation you can use prepend_view_path
Add the following to your ApplicationController:
before_filter :set_theme_path
def set_theme_path
prepend_view_path "app/themes/#{current_theme}"
end
So Rails should then look for any views in your theme specific directory in preference to the default views in app/views/**/*

Related

Active Admin Customization in Ruby On Rails

I'm using active admin gem. In one table i want admins page to have some extra fields apart from the default functionalities.
Is it possible to have a default active admin page + a provision to render some html.
I want something like this in picture
The extra feature that i was talking was about push notification and message and that text area part
If you want a page with your own content, you could register a page: http://www.activeadmin.info/docs/10-custom-pages.html
But if you want to customise the default html strucure of the index page, you have to re-open the ActiveAdmin::Views::Pages module and override the build_page_content method. You can do this inside your app, for example create a new file in app/lib folder and override the method.
https://github.com/gregbell/active_admin/blob/master/lib/active_admin/views/pages/base.rb#L62
or if you want to customise the index table:
https://github.com/gregbell/active_admin/blob/master/lib/active_admin/views/pages/index.rb
Not a nice solution, but it's work. :/
Unfortunately, it seems index doesn't support custom rendering:
https://github.com/gregbell/active_admin/issues/813#issuecomment-3059957
However, you might have luck using panel, except in my experience that renders above the table ActiveAdmin generates.

Embed web page coded in Ruby on Rails in another web site?

I would like to make my web page that I coded with Ruby on Rails as backend embeddable so that users are able to easily share it by copy and pasting some embed code. (much like YouTube embed code, but for a webpage)
Could someone point me to a tutorial or general direction how to go about doing so?
I'm planning to embed my web page in Joomla CMS.
Many thanks.
Pier.
Let's suppose you want to create a Widget for a mobile app store. The widget would allow to embed information of a certain app in any web page.
If we use the script tag, the embeddable code could look like this:
<script src="http://my_appstore.com/apps/1234.js" type="text/javascript"></script>
Where 1234 would be the id of the specific app we would like to embed.
If we use the iframe tag the code to put in other web pages could look like:
<iframe src="http://my_appstore.com/apps/1234" width="500" height="200" frameborder="0"></iframe>
First thing we have to decide is what kind of tag to use. Using and iframe tag is more straight forward but we are limited to use an iframe. Using an iframe is not a bad option but if you distribute this to third party web pages you won't be able to change that afterwards. Instead, it is preferable to use a script tag that will insert an iframe. This tag will also allow you to switch to embedding your content directly into pages if you choose to do so afterwards.
Inserting an iframe means that the proportions of your content have to be fixed and can't change to adapt to different window sizes in the parent window. Embedding your content directly doesn't have this problem but you have to be very careful with CSS and add style to all your elements because otherwise they will inherit the host page styles. Also embedding your content directly and then making AJAX calls will likely produce cross-browser request problems unless you use JSONP.
Let's first create a simple web page with Sinatra that we will use to embed our Rails Widget:
mkdir host_page
cd host_page
With your text editor create host.rb file inside host_page folder:
# host.rb
require 'sinatra'
get '/' do
erb :index
end
Create index.erb and launch host_page:
mkdir views
cat '<script src="http://localhost:3000/apps/1234.js" type="text/javascript"></script>' > views/index.erb
ruby host.rb
Now if we visit http://localhost:4567/ we see nothing but there will be a widget there soon.
Let's now create the rails app that will be embedded. Start with a new folder for your project and do:
rails new widget
cd widget/
rails g controller apps
rm app/assets/javascripts/apps.js.coffee
Add the needed routes:
# config/routes.rb
MyApp::Application.routes.draw do
resources :apps
end
Edit your apps controller:
# app/controllers/apps_controller.rb
class AppsController < ApplicationController
def show
#mobile_app = {
:title => "Piano Tutorial",
:descr => "Learn to play piano with this interactive app",
:rating => "*****"
}
end
end
In that controller we are always returning the same app. In a real situation we would have a model and the controller that would retrieve the appropriate app data from the model id found in params.
Create your javascript view and start the server:
echo 'document.write("<h3><%=#mobile_app[:title]%></h3><p><%=#mobile_app[:descr]%></p><p><em><%=#mobile_app[:rating]%></em><p>");' > app/views/apps/show.js.erb
rails server
And that's it. Go to http://localhost:4567/ and see your widget.
In case you want to use an iframe, replace the contents of your show.js.erb file with this:
document.write("<%=escape_javascript(content_tag(:iframe, '', :src => app_url(params['id'])).html_safe)%>");
Here we are using a content_tag but it could also be done in a way similar the previous one by just using the <iframe> tag as previously.
Obviously if we use an iframe, we are doing two calls, one to render the iframe and the other one to load the contents of that iframe. For this second call we are still missing an html view. Just create the view like that:
# app/views/apps/show.html.erb
<h3><%=#mobile_app[:title]%></h3>
<p><%=#mobile_app[:descr]%></p>
<p><em><%=#mobile_app[:rating]%></em><p>
Now you can point again to http://localhost:4567/ and see your widget inside an iframe.
A bit late, but I stumbled over this Question while searching for a solution by myself. I found a Gem that does exactly what's described. It will make your rails app embeddable like YouTube Videos or Content from other Webpages like Google Maps, Instagram, Twitter… It's called EmbedMe
To use you simply need to change your Routes to define, which Paths need to be embeddable
get 'private', to: 'application#private'
embeddable do
get 'embeddable', to: 'application#embeddable'
end
Gem on Github or Documentation
In case anyone is coming across this now, almost 9 years later...
If you use the JavaScript method, you'll have to allow Cross-Origin requests, like #abessive mentioned in their comment above. I was able to do this by adding this to the top of my controller class:
protect_from_forgery except: :method
where :method is the method that will be called for the embed request.
Here's my controller:
class PagesController < ApplicationController
protect_from_forgery except: :home
def home
render 'index.js'
end
end
And the relevant route in routes.rb:
get "index.js", to: "pages#home"
And I have views/pages/index.js.erb with some JS code that renders the widget.
(I'm using Rails 6.1.4)

how do i dynamically change my format rendering engine in rails?

My default templating engine is haml, but I would to sometimes change it to erb if i specify a specific parameter?
For example, I am pasting in some html code and would just like to test the code without HAML complaining about its format.
Any idea how to do this?
do something like:
if params[:render_erb]
render 'file.html.erb'
else
render 'file.html.haml'
end
and call the action with ?render_erb=true
or
render "file.html.#{params[:render]}" ir params[:render]
and call it ?render=haml or ?render=erb (or nothing and it will use the default
at the end of the controller's action that you are using
Am I wrong that you simply need to save file as your_file.html.erb instead of your_file.html.haml?
You can use different templates in the same application, and you can use different template engines for views, partials, and layouts, but as far as I know you can't duck in and out of multiple template engines within the same template file.
If you just want to drop some code in using a different template language, then I'd put it in a separate partial. That certainly seems easiest in this particular case.

What is this inside an erb template [Rails]

I'm seeing code like this inside of an erb template:
<% hook :admin_footer_scripts do -%>
What exactly is hook? is it a standard method within ActionView?
It's probably a helper method defined in your application. Look in app/helpers/application.rb or in the app/helpers/ directory for a ruby file named like the controller which renders that view
Just from what it looks like I'd say it's a way to allow the controller to add code the the page. But bgj is right. Look in your helper files.

Fallback format in rails

for my CMs i want to be able to easily add new themes, my idea was to simply add a mime type for the new theme (so application.theme1.erb would work).
but for 99% of the themes im not going to want to change the views, well not all of them.
is there someway to have rails fall back on html if the themed view isnt present?
I'm pretty new to Rails, so this might not be a perfect answer:
you might want to try using querystring parameters as part of the route like described here:
http://guides.rubyonrails.org/routing.html#querystring-parameters
so eventually something like this would work
map.connect ':theme/:controller/:action/:id'
As I understand it, the theme would be available as params[:theme] in the controller. If no theme is specified you probably have to add another route like
map.connect '/:controller/:action/:id'
to handle that case.
In the i18n guide something similar is described for locales: http://guides.rubyonrails.org/i18n.html#setting-the-locale-from-the-url-params
Hope that helps.
It depends on how much of the layout you want to change with the themes.
If you build your HTML right, most of the things can be done through css. (changing fonts, colours, where the stuff show up)
Then it is quite easy to add just a theme parameter to style it.
If you don't want to do that, you can always create a separate layout for it, and assign that depending on the parameters passed in (or even set it as a session variable so you won't have it in the url).
Basically, for the default theme, you stick to the layouts/application.erb, then you have say layouts/theme1.erb which you then assign with a method
class ApplicationController
layout :decide_layout
def decide_layout
#session[:layout] || 'application'
end
end
Customizing the views would be possible just by doing something like this in your actions:
def my_action
render "my_action_#{#session[:layout]}" if #session[:layout]
end
if #session[:layout] is not set, it will render the default, otherwise it will render your themed view.
Of course, if you set the layout depending on user input, make sure to sanitize and check the layout parameter before.
I've just had this same problem with mobile_fu, which sets the format to :mobile for mobile requests.
It turns out that if an :action.:format.erb template isn't available, Rails will serve :action.rhtml as a replacement in any format.
I can't say whether this will work for layouts, but it certainly works for actions

Resources