How can I in Rails write a Coffeescript function to update a database column? I guess an Ajax call of sorts would be ideal:
id = $('#document').attr('data-document-id')
$.ajax
url: "/documents/#{id}/update_attr"
type: "GET"
success: (data) ->
console.log(data)
Is something like this the only way? Or is there something better?
Well, keep in mind that frontend code (html, css, js) cannot access the database directly. So you need an AJAX request.
REST best practices would require you to use a POST/PUT/PATCH method instead of the GET method which should never change the state of the application.
Also, you are not passing any value to the Rails backend.
$.ajax
url: "/whatever/#{id}"
type 'POST'
data:
key: value
success: (data)->
console.log data
On the Rails side you need to setup the appropriate route in config/routes.rb:
post '/whatever/:id', to: 'some_controller#some_action'
Still ideally, following the best practices, you probably have some sort of
resources :apples
already mapped to an ApplesController. You now have to implement the action, which will be like this:
def update
#object = Whatever.find(params[:id])
if #object.update(key: params[:key]
render json: { success: 1 }
else
render json: { success: 0 }
end
end
That implementation is not complete (it does not handle HTML requests, multi-key updates and other fancy things), but still it should solve your problem.
Related
I try to store the data from a graph with jQuery but I always get a 400 Bad request.
The problem is the data_series variable isnt just an array of integers but much more. This is unchangeable since it is necessary for my chart generation to be like this.
A litle piece of it to show you what I mean:
data_series[0][data][0][]:1389975624000
data_series[0][data][0][]:91
data_series[0][data][1][]:1390003200000
data_series[0][data][1][]:446
data_series[0][data][2][]:1390089600000
data_series[0][data][2][]:429
.....
My Jquery post looks like this,
$.ajax({
url: "{{ url_for('save_graph_to_session') }}",
method: "POST",
data: {
data_series: data_series
},
success: function(data) {
console.log('Saved to session')
}
});
On flask side I read it like this, and put in a session:
#app.route('/save_graph_to_session', methods=[ 'POST'])
def save_graph_to_session():
session['data_series'] = request.form['data_series'];
return "saved"
I've tried to post with 'data_series[]:' data_series, didn't work out either.
EDIT:
Maybe the solution lies within the way to request, so :
Is there a way to request in flask that ignores the fact that this is an array of arrays
this is the way one can do this:
session['data_series'] = request.form.getlist('data_series[]');
I learned to create d3 graph using the d3 book, in which all the dataset is included directly in the <script> tag, which is in turn included in the html body.
I now want to use d3 in my rails app, but I don't know how to:
Pass data from my Rails database to my d3 script
How to "partial out" the javascript? I have seen materials on "unobstrusive javascript", but they are usually about AJAX form submission and I have a hard time converting that to graph drawing (i.e. including a <div> with graph drawn using app data).
There is still not an answer that deals with both of these issues yet, so hopefully this becomes a reference for future Googlers.
In my opinion requesting the data via AJAX would be the "cleanest" way to do that. You could use jQuery's ajax method to do a GET request to say '/get_data.json' ( which you have to add to your routes.rb), which would return you a JSON with the data.
Something like this.
//your JS file
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
url: '/get_data',
dataType: 'json',
data: "{}",
success: function (received_data) {
var div_where_to_draw = "div.mygraph";
your_d3_function(div_where_to_draw, received_data);
},
error: function (result) {
}
});
function draw_histogram(where_to_draw, data_to_draw){
//Your d3js code here
}
(Note that this JS code is a remake of the answer here)
This is how your controller providing the data could look like(note I made a new controller, you might not want to do that and just use a new action in an existing controller):
#app/controllers/data_controller.rb
class DataController < ApplicationController
def get_data
respond_to do |format|
format.json {}
end
end
end
And this is how your data could look like:
#app/views/data/get_data.json
[1,1,2,3,5,8,13,21,34,55]
I want to perform an action do file in controllers/static_pages_controller.rb:
def fileopen
my_file = File.new("public/CHNAME1.txt","w")
my_file.write "\tfasf"
my_file.close
end
(it work well when i define it in helper and call it in view.)
in myview.html.erb, i want some thing like <button id="button" onclick="readfile()" />
How can I do that?
I tried in application.js
function readfile() {
alert('readfile work')
$.ajax({
alert('ajax work')
url: "/fileopen",
type: "POST",
##don't know what to do to make fileopen work
}
});
}
routes.rb
match '/fileopen', to:'static_pages#fileopen', via: 'get'
and it's seem nothing happen. Only the first alert work.
In answer to your question directly, you have to be able to handle the JS request in the controller. This is typically done by using the respond_to block in Rails, like this:
def fileopen
respond_to do |format|
format.js {
my_file = File.new("public/CHNAME1.txt","w")
my_file.write "\tfasf"
my_file.close
}
end
end
This code may give you some sort of a response with your current code, but it might be the case that you need to appreciate better how Ajax & Rails work in order to help you better
How Ajax Works
Ajax is a javascript technology which sends an "asynchronous" request to other pages on your website. By their nature, asynchronous requests are done completely independently of your main HTTP request, and basically act like a "pseudo" browser -- working in the background
Ajax is used to pull data from JS-enabled endpoints (which are handled with the respond_to function in Rails, which you can then use to modify your page in some way. A lot of people get confused with Ajax, but it's actually quite simple -- it's just javascript which pulls data from another page, allowing you to manipulate your page with that data
Using Ajax In Your Views
The reason why this is important for you is because you mentioned you didn't know what to do with the success callback of your app. Hopefully my explanation will show you that the success part of the $.ajax call should be used to append the data you receive from the controller on your page
This can be done in this way:
$("#button").click(function() {
$.ajax({
url: "/static_pages/fileopen",
type: "POST",
data: {name: $(this).val()},
success: function (data) {
// append data to your page
$("page_element").html(data);
}
});
});
In a Ruby on Rails application, I want to be able to place a User's username in a input text box, press an 'Add' button, and have them appear underneath with their details. Then, I can simply remove them from the list if I want using another button.
How does one connect Javascript and Rails database to complete such a task specifically with those buttons? While Javascript isn't a strength of mine, I'm more puzzled by how to extract and modify the Rails database using Javascript. For reference, I'm also using MongoDB.
What would be the best way to approach this?
Here is the jQuery and AJAX code that I'm using to 'POST' to the server endpoint 'admin/popular/users.json', but I'm not sure how to get Rails to create a new user in the database using my Popular::User model.
$(document).ready(function() {
$('.add-to-popular-users-button').click(function(event){
event.preventDefault();
var addToPopularUsersBtn = $(this);
var userToBeAdded = $('input[name=popular_user]').val();
var data = { 'popular_user': {'username': userToBeAdded, 'category': 'popular'} };
var url = "/admin/popular/users.json";
$.ajax({
url: url,
data: data,
dataType: 'json',
type: 'POST',
success: function(e) {
alert('Great success!');
}
});
});
});
Here's my Popular::User model:
class Popular::User
include Mongoid::Document
include Mongoid::Timestamps
POPULAR = 'popular'
field :category, default: POPULAR
index :user_id
belongs_to :user
validates_presence_of :user_id
validates_uniqueness_of :user_id
def self.popular
user_ids = self.where( :category => POPULAR ).map(&:id)
User.where(:_id.in => user_ids)
end
I am not familiar with rails framework, but you can do it using ajax. You can send an ajax post request to controller method which will creae a user, create a table row(or recreate the table), and returnd html place in table.
A simple example is:
$.ajax({
type:'post',
data:{} //user data,
dataType: 'json', //or any other
url: 'page_or_method', //page or method that will return html
success: function (data) {
$('div#userTable').html(data); //in case data contains the table
}
});
Read about $.ajax method (jQuery), or you can use XMLHttpRequest if you don't whant to use jQuery.
So, I was able to figure this out with a bit of testing. But, basically, you can either do this with AJAX/jQuery or with Rails inherent RESTful architecture, i.e., HTTP verbs like calling :delete, and associating it with a particular UI button.
One important idea that you should recognize with AJAX is that whatever data you send to the right server endpoint with a 'POST' or 'DELETE' verb or what have you, it will get picked up by the appropriate controller action. In other words, if I'm sending data via 'POST' to the '/popular/users.json' endpoint to create something, the def create method will be able to manipulate data afterwards. Then, you can assign the data to an ivar in the controller action to be interpreted and manipulated in the UI view corresponding to the controller action.
I'm looking for a way to return a single JSON/JSONP string from a cross-domain "AJAX" request. Rather than request the string and have JQuery return it as a generic object automatically, I want to get a hold of the string BEFORE that conversion happens. The goal here is to parse it myself so I can turn it straight into new objects of a certain type (e.g. a Person object).
So, just to make this clear, I don't want any string-to-generic-object conversion going on behind the scenes and this must work using a different domain.
Here's a non-working example of what I would like to do:
$.ajax({
type: 'GET',
url: 'http://www.someOtherDomain.com/GetPerson',
dataType: 'text',
success: parseToPerson
});
function parseToPerson( textToParse ) {
// I think I can do this part, I just want to get it working up to this point
}
I'm perfectly happy if JQuery isn't involved in the solution, as long as it works. I would prefer to use JQuery, though. From what I've read, the javascript techniques used to get JSONP data (dynamically creating a script element) would probably work, but I can't seem to get that to work for me. I control the domain that I am requesting data from and I can get the data if I change the dataType in the AJAX call to 'JSONP', so I know that is working.
If your data is being retrieved from another domain, you will need to use JSONP (there are other options, but JSONP is by far the easiest if you control the service). The jQuery call will look like this:
$.ajax({
// type: 'GET', --> this is the default, you don't need this line
url: 'http://www.someOtherDomain.com/GetPerson',
dataType: 'jsonp',
success: parseToPerson
});
The actual request that goes to your service will be http://www.someOtherDomain.com/GetPerson?callback=arbitrary_function_name. On the service side, you will need to return data like this:
arbitrary_function_name("the string (or JSON data) that I want to return");
So you'll need to inspect the querystring parameters, get the value of the callback parameter, and echo it out as if you're calling a Javascript function with that name (which you are), passing in the value you want to provide through the service. Your success function will then get called with the data your service provided.
If you're deserializing the returned data into a Javascript object, you might be better off returning JSON data than a string, so the data your service returns might look like this:
arbitrary_function_name({
"name":"Bob Person",
"age":27,
"etc":"More data"
});
That way you don't have to worry about parsing the string - it'll already be in a Javascript object that's easy to use to initialize your object.
Not sure how this will work in conjuction with jsonp, but maybe converters is what you're looking for?
$.ajax(url, {
dataType: "person",
converters: {
"text person": function(textValue) {
return parseToPerson(textValue);
}
}
});