Using a single html template for Rail view and Angular Template - ruby-on-rails

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.

Related

How to store html for use in rails form_for?

I've got a page with
<p class = 'new-question'> Placeholder </p>
I have a form on the same page
<%= form_for(:question, url: question_path(Question.find_by(content:))) %>
I want the value of :content to be whatever the text of the <p> class is, ie in this case it should be Placeholder, I can't just put content: "Placeholder" because the text will be changed by a js script. How should I do this?
You can't use Ruby dynamically in the web page like that. question_path(Question.find_by(content: "whatever")) only resolves once, when the page loads, and just gives you a url that plops into the form.
The right way to do this is to dynamically change the url for the form directly with JS. If you only want to figure out the url based on the content/respective content, then you have two options:
Load all the Questions at once so that they're available to your JS on page load. Once the JS has the content, it can look through those Questions to find the appropriate url (where you'll also need to figure out how the routes are arranged--it's usually something simple like /questions/1/create.
If you're willing to make additional requests, then you can more sensibly use AJAX calls to ping your DB every time the content changes and let Rails tell you (through the AJAX) exactly what url to replace with.

Rails erb vs gsub dynamic template performance

In my project, I am using the ERB as template engine. We have one page which used ERB template and it's loaded within 5-7 seconds.
The same page we changed it into dynamic template, the template values are stored in the database.
sample template
<p> {{name}} </p>
<p> {{address}} </p>
<p> {{mobile number}} </p>
For applying the actual values over dynamic template, i have used the gsub. This case the same page takes load time as 16-20 seconds. I used 17 gsub over dynamic template.
How erb rendering is fast? (Because i am using the same content
before and after dynamic template)
Is there any way to increase the performance?
Note:
Compared to 'gsub' method, 'sub' method is fast. But in my case i need to use global sub (gsub).
In my case, the whole page is like a dynamic template with 20 tags. In that case gsub is not a correct solution to replace the 20 tags.
Client Side:
I have used the client side template engine called Handlebar.js. Using this my page loads with normal speed.
Server Side:
https://github.com/Shopify/liquid
If you store templates in database then you could use appropriate tools to render them. If it's erb then just use ERB, don't gsub variables manually. The reason why erb is so much faster than manual gsub is because erb template gets compiled to ruby code (like "Foo <%= bar %>" becomes "Foo " + bar) and executed.
As I understand you want to store your templates in database and render them both on server and client. You can use mustache for that, it's framework-agnostic and safe to run on server.

How to call a Header (an ERB) in my application body index ? (RoR)

im trying to make a web page in Ruby on Rails but im having some problem trying to split my page into various ERB files to split my page in: head,foot and body, now my question is how can i call each one of my views, in my body page to build the entire web page. thanks!
Let's say you have a _header.html.erb, you call it inside you application.html.erb by typing 'render 'header' (without the underscore) in your body tag

How to disable Backbone code to call an underscore template in non-essential pages?

I have an app that uses Backbone on the client side and Rails on the back end.
My Backbone code calls an underscore template in this manner:
var todo = Backbone.View.extend({
.
template : _.template( $('#todo_rows').html() ),
.
}
However, there's only one page on the site which would need to call this template, and the Backbone js loads on every page. That means that there will be a JS error on the other pages which don't have the "#todo_rows" underscore template defined.
One solution would be to create a blank "#todo_rows" template section for all the other pages, but this strikes me as a major hack and not the best way to deal with this problem.
What is the best way to disable the code to call a template in Backbone? It needs to be disabled if you are not on the home page OR if you are not logged in.
Underscore's template is happy with receiving an empty string as argument. As $('#todo_rows').html() returns null if the #todo_rows element does not exist, you can easily avoid the JS error by using the or-operator idiom:
template : _.template( $('#todo_rows').html() || '' ),
which means "use an empty string as dummy template if the real one is not available".
Another, Rails-specific workaround for this problem (and a neat approach in general) is to add the ejs gem to your project's Gemfile, which allows you to put each template in a separate .jst.ejs file in app/assets and have the Asset Pipleline compile it to a JST object that can be accessed by your view to get the template content:
templates/todo_rows.jst.ejs
<% // Your template (content of former "#todo_rows") here %>
todo_rows_view.js
//= require templates/todo_rows
var todo = Backbone.View.extend({
template : _.template(JST['templates/todo_rows']),
// ...
}
This avoids the roundtrip to the DOM and makes it possible to nicely organize the templates into multiple files, but has the drawback that the template string will be sent as part of the JavaScript code for every page including it.

How do you handle widgets in rails?

StackOverflow, for example, has a user's reputation displayed up top. Clearly, this is grabbed from the database, and it's displayed on every page. Of course, this isn't in every controller action on every page, because that would be incredibly redundant.
How do you handle this kind of situation in rails? The only way I can think of it is to use before_filters to pass the models into the page, but that just seems like abuse of that feature. There seems to be the cells gem that does what I want, but I'd imagine this is a common problem and there must be a simple solution for it in rails without having to resort to plugins or gems.
What you are looking for is the layout. In rails this is where you define headers, footers, and sidebars that frame your site. Look for app/views/layouts/application.html.erb in your generated rails code. Towards the bottom you will see:
<body>
<%= yield %>
</body>
The yield is where rest of the app gets invoked. Everything before and after the yield will appear on every page. So, using your example, you might query the database and set the instance variable #reputation in the application controller:
#reputation = User.find( current_user ).reputation
then display it in the layout like this:
<body>
<%= #reputation %>
<%= yield %>
</body>
This is covered thoroughly in the book "Agile Web Development With Rails". If you are going to develop in Rails I recommend getting the latest edition.
I would just make a partial with the widget in it and render it in the layout(s) where you want it to appear. Let it do whatever it needs to do, eg connect to the db, run some js to connect to an external site, etc.
If you're concerned about optimisation then deal with it when it becomes a problem.
I guess, you can put the code you need into a view helper. And then render some partial, like it was said before, in the layouts where you want it to appear, calling helper's function.
Look here:
Rails view helpers in helper file

Resources