Render remote view in local layout - ruby-on-rails

My organization is considering re-implementing an existing Rails monolith as a collection of Rails services. For the content layer, our thought was that our API gateway would contain the layout information for the whole app, and would request individual views via HTTP. Individual services would then render their templates and send them back via HTTP as rendered HTML.
My question is this: is there a mechanism in Rails to request remote content via HTTP, to render the received HTML into an ERB/HAML layout template, and then to serve the fully rendered HTML?

Like requesting that information in a controller and then outputting it as a string in an ERB template?
Is there some other requirement that I'm missing?
Controller
def index
#content = body_of_request_to_service
end
View
...
<%= #content %>
...
But, I wouldn't recommend this style of microservices using Ruby (unless you have a dev-team that understands how to handle async Ruby IO). A good rule of thumb is to only have one blocking service request per client request.

When you render a template in Rails, nothing restricts you in terms of where the markup comes from. Regularly it would come from a locally found *.html.erb template.
When a pre-rendered html piece comes from an external source you can do this:
render html: my_html_string.html_safe
If you want a layout, then:
render html: my_html_string.html_safe, layout: 'my_layout'
The my_html_string could be served by the external source either with html format renderer or as a string to be later serialized to e.g., json.
#my_html_string = render_to_string(
template: 'templates/my_template.html.erb',
layout: false
)

Related

What does the term "template" mean?

I am learning Rails 5.0, via a tutorial. Learning how to generate view templates, but the term "template" is never explicitly defined. I've searched in the Rails docs, and they seem to mention the word a lot, but also never really define it explicitly.
I know that views are the HTML, CSS associated with what the user sees. But was wondering what is a template and how is it different than a standard webpage?
I don't have an authoritative answer. But this is really rather simple. RoR lets you generate content dynamically. This means, with one template, you could generate different content (html pages). The final html page generated and served by the server is the webpage endusers see. For example, you could have a template show.html.erb with the following line:
<h> Product <%=#product.name%> </h>
From this template, different webpages for each different #product can be generated with that #product's name, depending on the #product variable, which is provided by the controller.
So templates allow you to dynamically generate content and render them as different html webpages.

Using a single html template for Rail view and Angular Template

I have a Ruby on Rails app that loads a single page Angular JS Web App when the user is logged in, and serves static info pages via RoR views when the user is not logged in.
The angular templates are in 'app/assets/templates/' and the rails files are in 'app/views'.
I have a text heavy html page that I would like re-use with both rails and angular. I've tried accessing the rails view from my angular $routeProvider, setting templateURL to the path of the view. This causes more than one instance of angular to load and it gets stuck in a loop.
app.config ($routeProvider) ->
$routeProvider.when('/features/',
templateUrl: '/views/features.html'
)
I've tried rendering the file in my assets/templates folder through a rails view. That doesn't work either since rails can't find the partial.
= render 'assets/templates/features.html'
Does anyone know how I might be able to use a single template for both?
I'm mot sure what exactly you mean by text heavy page. But what about other solution - extract all text to JSON file with keys (some sort of translation file). For example:
{ "title1": "Title", "paragraph1": "lore up sum. .." }
Then you can load this JSON in your rails controller and pass it to view that render text parts from it.
<h1><%= #text ['title1'] %></h1>
<p><%= #text['paragraph1'] %></p>
And as well load JSON as resource in your angular app and pass it to view.
<h1>{{ text.title1 }}</h1>
<p>{{ text.paragraph1 }}</p>
If your text is somehow structured you can make use if it and automate the view with loops, conditions etc and so save repeated parts even more.

how can i render a template as well as a JS file BOTH in a controller action

i have a scenario where in edit action ,i need to render the edit.html.erb as well as trigger the edit.js.erb file as well.right now i have
def edit
#page_id = params[:id]
respond_to do |format|
format.html
format.js
end
end
but only the view is renderring ,but my edit.js.erb is still not triggered.
With both ansers you can get it working, but you do not follow conventions. The edit.js is meant for Ajax-calls.
What you seem to be doing, is using partials to build up your page. Then you really should follow naming conventions (starting the filename with _) to be clear for other programmers.
Second, you always need to make sure your site can work without javascript, so your Edit page never should require any Javascript to work. The javascript is complementary to improve user experience (like using ajax to make edits without a page-refresh).
Summing up:
- move the 'required' javascript code to your edit.html.erb.
- only use the edit.js.coffee to handle the updates to the existing webpage if Ajax is activated, use as much of the js from the edit.html.erb.
- Put the rest of the shared code into partials, like _niceedit.js.coffee and render it using 'render :partial=>'...
Follow conventions, it will help you later on and when using test services etc.
respond with js and write code below:
edit.js.erb
$('body').html('<%=j render "edit" %>');
Your impression of what it does is wrong.
If you want javascript to run, then your edit.html.erb file needs to contain:
<%= javascript_include_tag "jsfilename" %>
and store your javascript in public/javascripts/jsfilename or similar location (public/assets/javascripts/
The respond to format.html, format.js is for requesting the view in that format.
Eg. If I browse to edit.html, it shows the html.erb view, if I browse to edit.js, it shows the js.erb view. The functionality is so that you can request the same content in different file formats, rather than to add javascript functionality to your webpage.

Rails: generating URLs for actions in JSON response

In a view I am generating an HTML canvas of figures based on model data in an app. In the view I am preloading JSON model data in the page like this (to avoid an initial request back):
<script type="text/javascript" charset="utf-8">
<% ActiveRecord::Base.include_root_in_json = false -%>
var objects = <%= #objects.to_json(:include => :other_objects) %>;
...
Based on mouse (or touch) interaction I want to redirect to other parts of my app that are controller specific (such as view, edit, delete, etc.).
Rather than hard code the URLs in my JavaScript I want to generate them from Rails (which means it always adapts the latest routes).
It seems like I have one of three options:
Add an empty attr to the model that the controller fills in with the appropriate URL (we don't want to use routes in the model) before the JSON is generated
Generate custom JSON where I add the different URLs manually
Generate the URL as a template from Rails and replace the IDs in JavaScript as appropriate
I am starting to lean towards #1 for ease of implementation and maintainability.
Are there any other options that I am missing? Is #1 not the best?
Thanks!
Chris
I wrote a bit about this on my blog: Rails Dilemma: HATEOAS in XML/JSON Responses.
I came to similar conclusions. There's no incredibly clean way to do it as far as I know, because by default the model is responsible for creating a JSON representation of itself, but generating URLs is strictly a controller/view responsibility.
Feel free to look over my thoughts/conclusions and add comments here or there.

Rails + facebox + authlogic - how?

on my web site I want to have login/registration form in modal window done using facebox (jQuery plugin). What is better:
Create view with one method and template that has form and refer facebox to this view.
Create static HTML file in public directory and refer facebox to this static page.
What I want to achieve is:
Easy verification (like "user name already taken", "password confirmation doesn't match password" and stuff like that).
Easy submit and redirect
I'm new to Rails, I just know about forms verification in Django, so for Django I would probably choose option 1, but it might be another thing in Ruby.
If you want the verification to come back to the registration page, you should make it a dynamic page.
The other problem with a static page in the public directory is that your links all become hardcoded, so if you application ever lives off the domain root (i.e. example.com/app) the links in that static file could be wrong.
Additionally, if you ever need to move your images to a different host, you lose the advantages of the image_tag.
Only use static resources if you know things won't change and you need speed. If your dynamic pages are too slow, you can cache them, or you might be doing something wrong.
UPDATE: (to address the first comment)
You can't use the rails functions to build your URLs when you are in the public folder. If you need rails generated URLs in your javascript, trigger them from a rails view page.
Generally, I'll do the following:
In application.html.erb in the head tag:
<%= yield :headScripting %>
Then in the view page that is triggering the javascript:
<% content_for :headScripting do %>
jQuery().ready(function() {
jQuery("#placeholder").load("<%= summary_model_path(#model) %>");
});
<% end %>
That would load the summary text from the model controller action summary. This would probably render :text => "summary" or render :layout => false depending on your needs

Resources