How to use json in d3.js Rails application - javascript

I am using the gem gon to create json from my Rails database.
I am able to do this successfully and show the results in an alert although I would like to show it in d3.js
I have a database called users (name:string,value:integer)
I would like to pass just the values to json so these can be graphed.
Is it better to try to do this in the controller or to pass the whole table into json and then configure d3 to graph the parts I want?
Trying the former as follows
class GraphController < ApplicationController
def index
end
def data
gon.users = #users.value.as_json
#users = User.value
end
end
gives me the error:
NoMethodError in GraphController#data
undefined method `value' for nil:NilClass
and this highlights the line
gon.users = #users.value.as_json
Im not quite sure how to graph the values I want
UPDATE
So on recommendation I have now ditched gon and reverted back to creating json the old fashioned way and then trying to call it from an ajax call.
The controller therefore looks like this:
def data
render :json => User.select('value')
end
end
and I make exactly the same call to data using the ajax as set out in the tutorial I am trying to follow here
However this doesnt show me the bar graph I want and return a hash of id and value in json format.

You're not actually loading any users from the database:
class GraphController < ApplicationController
def index
end
def data
#users = User.all
gon.users = #users.value.as_json
#users = User.value
end
end
Is it better to try to do this in the controller or to pass the whole
table into json and then configure d3 to graph the parts I want?
This is a matter of opinion but I would say that it's better to create a well thought out API which exposes your resources as JSON in a way that fits many uses.
I would also ditch gon and use plain old JSON and Ajax. Injecting data into javascript from the server via script tags is kind of an anti-pattern. It relies on globals, creates timing issues and makes your controllers coupled to the behavior of javascripts components on the page.
Applications which take the "eat your own dogfood" approach and consume their own API's tend to be better executed and far more modular.

Related

What is the best approach to manage multi page JavaScript in Rails application?

I am building a Rails application which contains hundreds of html pages and it requires unique javascript on each page including js libraries. Rails because I am more familiar with it and also for other backend purposes.
To get an idea you can take an example of simple code conversion (eg. XML to JSON) online tools. Here the code for converting xml data to json is written in javascript on the HTML page. In my case, I want to make 100's of such tools (ie. csv to json, html to pdf etc), where each one is independent of other. I m not storing any data from these in the database but only the user info who is going to use tools. So basically all pages will be rendered from a single controller.
Please suggest me better approach for that or should I continue writing javascript on every single HTML page. Thanks.
For your case above I would like to suggest using coffeescript OOP method, below is the detail and some code for your requirement
I suggest you to use coffee with class method and then check each page with event turbolinks:load
you can check which page with name of
controller and the the method for example $(".purchase_requests.new")[0] meaning the controller is purchase_requests and the method new
also I suggest you to read brandon hilkert blog for some additional reference below is the link
sample coffeescript with check each page load
class App.PurchaseRequest
renderYourJavascript: ->
console.log "purchase request js"
$(document).on "turbolinks:load", ->
if $(".purchase_requests.new")[0] || $(".purchase_requests.edit")[0]
purchase_request = new App.PurchaseRequest
purchase_request.renderYourJavascript()
I not surely I understand your ideal. But, I think you can try to save your javascript code into database.
And you use a controller for read javascript code from database and render it as javascript file.
Example:
# routes.rb
get '/js/:file_name.js', to: 'javascripts#show'
# model
Javascript( id: :interget, name: :string, content: :text )
# controller
class JavascriptsController < ApplicationController
def show
js = Javascript.find_by_name(params[:file_name])
respond_to do |format|
format.js { js.content if js.present? }
end
end
end
I try to simply describe my ideal. Please checking again and surely it works as you want.
Hope its help.

Is it approperiate to mix a JSON object with HTML?

With ASP.NET MVC you have the possibility to return a JSONResult.
return JSON(new { View = RenderViewAsString("MyView", model), wasSuccessful = true})
As you can see my JSON object will have HTML and some data. The idea behind this is to use strongly typed HtmlHelpers in the MVC view and making only one request to the server instead of multiple ones.
Is it approperiate to mix a JSON object with HTML?
It is certainly effective and will get the job done quickly.
However, if you find yourself getting back ready-made HTML renders from the server together with other data a lot, or if you end up digging into the HTML received to perform "adjustments" before inserting it into the page then you should start looking into client-side templating instead. This way the server can return just the data as JSON and the client will take up the task of rendering the data into HTML independently.

Trying to port over ruby script to a rails application, getting uninitialized constant error

I am not very experienced with rails, but I have used it for several apps before. This app is different because I want to port over a ruby script to a rails app and I am running into several problems, I'm fairly certain I'm going about it the wrong way so wanted to ask S.O. some advice.
The script generates some equations, and I want the controller to just call a helper (or something) to generate the equations list with my script, then pass them on as JSON or something that I can play around with using JS in the view. I tried simply copying the script files over to the helpers folder, but when I try to initialize them via a new route I made in the controller, it gives this error: NameError (uninitialized constant UsersController::EquationSettings). I think it may be expecting my model to include all of these objects.
Code snippet:
The new controller action is in the users_controller (it has its own route now - wanted it to just pass the equation_list and the user to the view where I will handle all the display):
def list_equations
#user = User.find(params[:id])
equation_settings = EquationSettings.new 10
equation_list_generator = EquationList.new equation_settings
#equation_list = equation_list_generator.generate
respond_to do |format|
format.html # show.html.erb
format.json { render json: #user, json: #equation_list }
end
end
Folder structure:
app/controllers/users_controller.rb (the controller noted above)
app/helpers/equation_helpers/(EquationSettings, and EquationList rb files are here)
Once this #equation_list gets passed to the view, I just want to be able to access it like any other JSON hash. Wide open to any suggestions, if it seems I'm going about this completely the wrong way please try to point me in the right direction. Appreciate the time of all the readers,
--Anthony
Guessing from your code snippet, you may need to change your approach. A few suggestions/pointers:
It looks like you're trying to use a helper class, but in Rails, helpers should be modules, not to instantiate but to simply use their methods in the view. For example, in app/helpers/stark_helper.rb you would want to have:
module StarkHelper
def use_honor
# winter is coming
end
end
That would make use_honor available in your view.
Helper methods automatically become available in the view, but not the controller. To use helper methods in a controller (not recommended; doing so would violate the MVC pattern) you need to explicitly include the helper in the controller class, e.g.:
class BaratheonController < ApplicationController
include BaratheonHelper
# stuff
end
When auto-loading project files, such as helpers, Rails expects folder structure and file names to reflect the names of modules and classes defined therein. For example, Rails would not load your file if in app/helpers/lannister.rb, you had defined module LannisterHelper; you would need to change that file name to lannister_helper.rb. (lannister_helper.rb -> LannisterHelper)
Another important facet of the auto-loading I mentioned is that sub-folders are expected to reflect sub-classes and sub-modules. So if you had app/helpers/greyjoy_helper/greyjoy_boat_names.rb, that file would need to have this definition:
module GreyjoyHelper
module GreyjoyBoatNames
# stuff
end
end

Ajax and Json with Rails

I followed Hartl's Rails tutorial where he does Ajax using RJS and sending javascript in the response to be executed on the client side to edit the DOM.
But what do you do if you want just JSON sent in the response and not send javascript. This also means the javascript to manipulate the DOM should already be in the html file on the client. Is there a tutorial as good as Hartl's book on how to do this in Rails. Presumably it would use Jquery and some other stuff maybe that I've not heard of to make the code not be a million lines?
My best attempt at an answer is that it really depends on the scope and complexity of what you're trying to achieve. Generally, JSON shows up in views. If your application does not require you to dynamically retrieve JSON, that is, you can load it all when the view is initially rendered, then you can set an instance variable in your view's controller like so
#my_json = some_object.to_json()
Then, your instance variable is available in your view
<script type = 'text/javascript'>
var theJSON = <%= #my_json %>
</script>
Now, your data is available in the DOM, parsed nicely into JSON.
If your application requires you to dynamically retrieve JSON after the controller/view are loaded, then you should probably look into using AJAX to hit a particular controller's method that returns the JSON that you desire.
Here's a good RailsCast that can hopefully help you along your way Passing Data to Javascript
You should take a look at Ajax in Rails 3.1 - A Roadmap.

Sending data from Ruby(rails) code to javascript/jquery

I recently started working on a project which involves ruby on rails/javascript/jquery. I am very new to all this. The part I am involved is like this. User clicks on a button. A dialog will open, where user will enter a term to search. With that term, I am will be constructing an URI by looking at an xml. Then I will do a REST call. The response will be a XML file. I will be parsing it and displaying data in the same dialog where user entered term to search.
I am using JQuery to create a dialog. And I am doing parsing and REST call part in ruby code (Helper class). I am not using models and controller for my part. Now I need to send data from helper method to erb file where I will be displaying data as a table. Output will be like this
string11 string12 string13
string21 string22 string23
string31 string32 string33
. . .
. . .
For now, in ruby code I have create 3 arrays for every column. I am not sure on how to send data from ruby to html/javascript. If there is better way to do this then let me know. For ex: instead of sending as 3 separate array, is it better to send as xml/json? Or any other suggestions will be really helpful. Mainly I am not understanding on how to send this data to the erb file. Thank you in advance.
Edit: Adding a sample code
Javascript/Jquery -
On button click, I want to call a ruby method in erb file
Ex: <%= getUserList%>
erb file is also having other javascript/html code to display other stuffs.
And in helper method I have getUserList method
def getUserList(search)
uri = create_url(search)
#doc = Nokogiri::HTML(open(uri))
//Doing parsing and other stuffs here
//creating 3 array as mentioned above which needs to be displayed
end
I want above arrays to be displayed. I am not sure on how to send these arrays to the erb file which invoked this method
In your controller:
def users
respond_to do |format|
format.js do
render(:js => "callback(#{#users.to_json});")
end
end
end
Use something like this in your HTML to call that:
<%= link_to_remote "get users", :url => { :action => "users" } %>
More information on rendering vanilla JavaScript from a Rails action: http://guides.rubyonrails.org/layouts_and_rendering.html#rendering-vanilla-javascript
This example constructs JavaScript that calls a "callback()" function in your JavaScript code, with JSON data. Your callback function will receive a JSON string that will be easy to parse. You could also use to_xml to send XML if you really want, but parsing JSON is much simpler and faster.
You don't need a helper in this example because the JavaScript call that includes the data will come directly from your controller. There is no view template, so you don't need a helper. The best place for the code that gets the #users would be in a User model class. Not an Active Record model, just a plain model. The code that fetches the users from the remote REST API could possibly be a class method. (If you're feeling lazy then you could set #users with the REST API response right there in the "users" controller action. But that's not ideal use of Rails because the whole point of Rails is MVC.)
If you're using jQuery, then you could also use jQuery's getJSON() function so that your controller would send only the JSON data without using the callback: http://api.jquery.com/jQuery.getJSON/
Note that this is the simple kind of answer that you seem to be looking for, but this isn't really the best way to do this kind of thing for more complex applications. The best way to do this kind of thing at the moment is with something like Backbone.js. http://documentcloud.github.com/backbone/ With Backbone.js, you can define a "users" collection in JavaScript, set the REST URL of that collection (it can be a URL in your Rails app, which relays data from some other API) and then you simply call users.fetch() in your JavaScript to load the data. It's very similar to Active Record, but for the client site. It's better because it abstracts the process and allows you to update and delete records as well as simply listing them.

Categories