read rails variable on react code - ruby-on-rails

How can I read a rails variable on a react component.
On my controller
#test = 'test'
On my react component
var test = "<%= #test %>"
console.log(test) // outputs ''
Is what I am trying to do possible ?

Javascript files aren't rendered in the same manner that erb files are. What you see is what you get for the most part.
If you want to serve up variables from the server that can be read by react, there are a couple of options.
In an html.erb view, create a script tag and populate it with the data
<script>var test = <%= #test %>;</script>
Create an endpoint which will respond with a JSON representation of the data. This would require the javascript to perform an ajax call to said endpoint upon the document being ready (or componentDidMount in react).

Related

Render remote view in local layout

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
)

GET request gets triggered instead of template render with AngularJS, Rails and ngModal

I am using Rails, angular-rails-templates gem, Angular 1.4.8 and http://likeastore.github.io/ngDialog/.
My project structure keeps my template files in app/assets/javascripts/templates and my angular project in app/assets/javascripts/angular-app. I have set up ng-modal as:
$scope.callModal = function () {
ngDialog.open({
template: 'tickets/partials/_resolve.html',
controller: 'TicketEditController',
scope: $scope
});
};
I have a template called _resolve.html.erb inside my app/assets/javascripts/templates/partials/_resolve.html.erb. The issue is that whenever I press on the button who ng-click the function, I see a GET request to /tickets/partials/_resolve.html so it doesn't actual render the template but just makes an http request to that uri.
The modal pops up but displays the whole root page (not the template).
How can I make this work?
try moving your html file to a directory app/assets/templates/partials/_resolve.html. Unless you have your templates configured differently than angular rails templates suggests in their documentation

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 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.

Call a Ruby on Rails helper method from a JavaScript js.erb file

Is it possible to call a ruby helper method from within a js.erb file?
I have a helper in application_helper.rb called solve which makes a API call to a third party service, and they only have a ruby client.
The js.erb file isn't being run on the client side, it is being called from within a controller method and run server side as it is PhantomJS.
I call the JS file from the controller
Phantomjs.run('phantom.js.erb', url)
Then within the PhantomJS js.erb file I have tried
var response = '<%= solve(variable) %>'
which just sets the variable as the string <%= solve(variable) %>
I have also tried
var response = <%= solve(variable) %>
but that just seems to make the application hang and become unresponsive.
I have seen other questions similar to this. In those questions they are asking if it is possible to call it from client side JS which I know you need to use an ajax request to do so.
Is this possible?
Try this:
var content = '#{solve()}'
Need a bit more context for this question, but I'll try my best to answer:
Essentially, you wouldn't be able to access your application_helper methods outside of any .erb files. (ie. if you have application.js or any other js file in your pipeline and you are trying to <%= solve %> from there it wouldn't work - mainly because it isn't an .erb file)
There are a lot of ways and architecture to go about solving this, but here are two simple ones:
If you put the JS you want to evaluate inline on the same page as your partial/html.erb page by using <script> //JS ERB CODE GOES HERE </script> It will actually evaluate properly since it is inside of an erb file. However, this is generally looked upon as unclean...
What you probably want to do is pass the value (presumably) you want that comes from the "solve" application_helper in a 'data' attribute on the html element that it affects. By utilizing "unobtrusive javascript" in this way, you simply pass the value through markup and then in your JS you can get the variable by using jQuery code like this. Here's an example:
<%= link_to "test_link", root_path, :data => {:solve => solve } %>
Of course it doesn't have to be a link, any HTML element will do, and then in your jQuery:
$("#test_link").data("solve");
will return to you whatever output comes out of your "solve" method in the application_helper.
it can possible but there are different ways to do it. one way is define the method in helper_method in your controller and call it from your view. and another way is use the gon gem to access some controller value in your javascript. please check what is best for you please check the below links for more help
http://apidock.com/rails/ActionController/Helpers/ClassMethods/helper_method
https://github.com/gazay/gon
http://railscasts.com/episodes/324-passing-data-to-javascript

Resources