Can you tell me how to display a delayed_job handler in my view? my controller returns a JSON object of delayed_job. upon the below code execution I am displaying JSON in my view but not the handler.
****delayed_job_controller.rb****
def show
#job = Delayed::Job.find(params[:id])
respond_to do |format|
format.json { render(json: {payload: #delayed_job.handler}.to_json) }
format.html
end
end
****_list_row.html.haml****
%td=link_to item.id, admin_delayed_job_path(item)
%td=link_to "[+]", '#', class: 'handler'
- %w(priority attempts created_at run_at failed_at).each do |k|
%td= item.send k
-if can? :destroy, item
%td=link_to "Delete",admin_delayed_job_path(item), method: :delete
****delayed_jobs.js.coffee****
class DelayedJobAdmin
constructor: (tableSelector) ->
#table = $(tableSelector)
console.log #table
#initBehaviours()
initBehaviours: =>
#table.find('a.handler').click (e)=>
e.preventDefault()
p = $.ajax {
url: '/admin/delayed_jobs/280.json'
success: (res) ->
$.each res, (index, element) ->
$('.handler').html(element)
error: (res) ->
console.log 'error',res
}
$(document).on 'ready', ->
new DelayedJobAdmin(".delayed-job-admin")
You assigned the job to the #job variable, but when you render the JSON you use the #delayed_job variable.
Try this:
def show
#job = Delayed::Job.find(params[:id])
respond_to do |format|
format.json { render(json: {payload: #job.handler}) }
format.html
end
end
Also, you don't need to call .to_json on the hash, it will be done for you.
Related
I have new and create actions like this:
def new
#foo = Foo.new
end
def create
#foo = Foo.new(foo_params)
respond_to do |format|
if #foo.save
format.html { redirect_to root_path }
else
format.html { render :new } //**this line I want to send params**
end
end
end
I have a jbuilder file to new action like this:
new.json.jbuilder
json.foo do
json.a "Some important info"
json.b "Some important info"
end
And rails can't read this file after create's validation fails. How to render a view template (like render :new) and send some json data in this view?
I have a js calling like this:
var json_url = window.location.href + ".json";
var foo;
$.ajax({
url: json_url,
dataType: 'json',
async: false,
success: function(data) {
foo = data.foo;
}
});
If you want Rails to render a file, you'll need to remove the call to redirect_to as it will effectively prevent any rendering.
Furthermore, if you don't want the controller to respond to different formats, it's better to skip the call to respond_to, too.
If you just call render action: :new, the view template will have access to all controller instance variables (like #foo):
json.foo do
json.a #foo.a
json.b #foo.b
end
I am using a bootstrap typeahead plugin. Basically, it expects a json response when you click on one of the items in the dropdown menu. However, when the item is clicked, I want to redirect to a different page; I do not want to respond with json. I don't know how to handle this situation. This is what I have:
def populate_global_search
respond_to do |format|
if params[:name] && params[:name][:value]
model = Model.where(name: params[:name][:value]
else
model = nil
end
if model.present?
format.json { redirect_to model }
else
format.json { head :ok}
end
end
end
The action is triggered from an ajax call:
$(element).bind('typeahead:selected', function(obj, datum, name) {
$.ajax({
url: that.format_url(),
data: {
name : datum
}
}).done(function(data){
...
Since the redirect_to is not a json response, nothing happens when I click on the item. What can I do?
The main problem here, you call the populate_global_search action asynchronously, respond_to block unable to redirect an asynchronously call. To resolve your problem I suggest you render the path to redirect and change the location by window.location:
The javascript code(that's just an assumption):
$(element).bind('typeahead:selected', function(obj, datum, name) {
$.ajax({
url: that.format_url(),
data: {
name : datum
}
}).done(function(data){
// redirect to the desired path
window.location = data.location;
});
The Rails code(also assumption):
def populate_global_search
respond_to do |format|
if params[:name] && params[:name][:value]
# I use find_by, because where return a collection
model = Model.find_by(name: params[:name][:value])
else
model = nil
end
if model.present?
# render a json objects { location: '/some_path/12' }
# with path which you need
format.json { render json: { location: here_is_the_desired_path } }
else
format.json { head :ok }
end
end
end
Bonus, your can reduce your Rails code to, this also should works:
def populate_global_search
model = Model.find_by(name: params[:name].try(:[], :value))
if model.present?
render json: { location: here_is_the_desired_path }
else
head :ok
end
end
Building on the helpful and working solution presented here, I'm trying to fix my update callback as well.
Problem is, the specific unit that I'm trying to extract data from is always the old cached version, even though this callback is triggered by a successful update action.
// callback triggered by the update action
$('.best_in_place').bind("ajax:success", function () {
...
console.log(unit.duration);
// which is exactly the same as
console.log(<%= Unit.find(unit.id).unit_users.pluck(:duration).sum %>);
// and both print the OLD duration val instead of the updated val which is in the database
});
and the unit_users_controller code...
def update
#unit = #unituser.unit
respond_to do |format|
if #unituser.update(unit_user_params)
#unit.reload
logger.info('-----------------------------------------------------------------')
logger.info('#unit.duration in the controller is ' + #unit.duration.to_s) # which is the correct value
logger.info('-----------------------------------------------------------------')
gon.unit_duration = #unit.duration # an experiment which didn't work for me
format.json {respond_with_bip(#unituser) }
else
# format.html { render :action => 'edit' }
format.json { respond_with_bip(#unituser) }
end
end
end
I've tried several versions of unit.reload, and nothing helps. Maybe I was putting it in the wrong place?
I did this one sometime ago here is my code, maybe it will help you:
Javascript:
$(document).ready(function() {
$('.price_bind').bind("ajax:success", function (event, data, status, xhr) {
var parsed_data = jQuery.parseJSON(data);
$(this).text(parsed_data.newprice);
$(this).parentsUntil('body').find(".totalpricep span").text(parsed_data.totalprice);
});
}
View:
<%= best_in_place detail, :price, :classes => 'price_bind', :path => purchase_detail_path(#purchase, detail)%>
Controller:
def update
respond_to do |format|
if #detail.update_attributes(params[:detail])
#n=#detail.mk_bal
#r=false
if #detail.purchase != nil
#p=#detail.purchase.totalprice
if params[:detail]['status'] && #purchase.step==1
#remdet = #purchase.details.where(:step => 1, :status => false)
if #remdet.empty?
#purchase.update_attribute(:step, 2)
#r=true
end
end
else
#p=nil
end
format.html { redirect_to #detail, notice: 'Detail was successfully updated.' }
format.json { render :json => {:newprice => #n, :totalprice => #p, :newstatus => #detail.status, :refresh => #r}}
else
format.html { render action: "edit" }
format.json { render json: #detail.errors, status: :unprocessable_entity }
end
end
end
This isn't about caching. Your Ruby code is evaluated server-side, before the JavaScript is ever send to the client, and it's only evaluated once, long before the AJAX request can happen.
The client never sees this line:
console.log(<%= Unit.find(unit.id).unit_users.pluck(:duration).sum %>);
All the client will see is something like:
console.log(32); // or whatever the sum is
You cannot use <%= %> here. That will always give you the original value. Instead, you need to send the new value to the client in response to the AJAX request.
I'm new to rails, and unable to set a variable in my modal using ajax! My approach is; I first pass it from external javascript (jquery dialog) to my controller, then to my model method as a parameter. Please critique!
My javascript (ajax within jquery-dialog button):
click: function() {
var qtySelected = $("#quantity[data-id='" + prodvarid + "'] input").val();//inputValue check
qtySelected = parseInt(qtySelected); //ensure value is int
$.ajax({
type: "POST",
url: '/line_items',
beforeSend: function(xhr){
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
data: {product_id: prodvarid, qty_selected: qtySelected, remote: true},
dataType: "script"
});
alert("input value is: " + qtySelected); //inputValue check
$("#quantity[data-id='" + prodvarid + "'] input").val(1); //reset default value on submit
$(this).dialog("close");
}
My controller - it receives the :qty_selected value through an ajax POST, to which it is passed into my model using ctlQty:
# POST /line_items
# POST /line_items.json
def create
#cart = current_cart
product = Product.find(params[:product_id])
ctlQty = :qty_selected
#line_item = #cart.add_product(product.id, ctlQty)
respond_to do |format|
if #line_item.save
format.html { redirect_to(store_index_url) }
format.js { #current_item = #line_item }
format.json { render json: #line_item, status: :created, :location => #line_item }
else
format.html { render :action => "new" }
format.json { render json: #line_item.errors, status: :unprocessable_entity }
end
end
end
My model receives the value and sets the local variable current_qty:
def add_product(product_id, qty_selected)
current_qty = qty_selected
if current_qty
current_qty = qty_selected
else
current_qty = 1
end
current_item = line_items.find_by_product_id(product_id)
if current_item
current_item.quantity += current_qty
else
current_item = line_items.build(:product_id => product_id)
end
current_item
end
Upon testing, I receive:
"TypeError (:qty_selected can't be coerced into Fixnum)"
app/models/cart.rb:17in '+'
app/models/cart.rb:17in 'add_product'
app/controllers/line_items_controller.rb:48in 'create'
The error message states that you're trying to use a symbol and a number. Indeed, in the controller, it should be:
ctlQty = params[:qty_selected].to_i # instead of ctlQty = :qty_selected
Also, in add_product, the first 6 lines looks complex, and could simply be written
current_qty = qty_selected || 1
So, I just discovered select2. Awesome. Now I'm trying to figure out how to use it, server side with ajax / json. All of the examples I see, everywhere, show using select2 with JSONP to retrieve data from an external source. I feel like this should be even easier if calling from a local model, no? I'll get right to the nitty gritty. json returns a value, but the searchbox doesn't autocomplete, it stays blank.
view html:
<%= form_tag request_pal_path, remote: true do %>
<%= hidden_field_tag :email, nil, class: 'ui-corner-all' %>
<%= submit_tag "Send request", class: 'button' %>
<% end %>
and calling some js on it:
$(document).ready(function() {
$("#find_user #email").select2({
width: '400px',
placeholder: "Find user...",
minimumInputLength: 1,
multiple: false,
id: function(obj) {
return obj.id; // use slug field for id
},
ajax: { // instead of writing the function to execute the request we use Select2's convenient helper
url: "/users",
dataType: 'json',
data: function (term, page) {
return {
q: term, // search term
page_limit: 10
};
},
results: function (data, page) { // parse the results into the format expected by Select2.
// since we are using custom formatting functions we do not need to alter remote JSON data
return {results: data};
}
},
formatResult: FormatResult,
formatSelection: FormatSelection,
escapeMarkup: function (m) { return m; }
});
})
function FormatResult(user) {
return '<div>' + user.name + '</div>';
}
function FormatSelection(user) {
return user.name;
}
which goes to the controller, user index action:
def index
#find = User.where('name LIKE ?', "%#{params[:q]}%")
#users = #find.where('id NOT IN (?)', current_user.id).order('random()').page(params[:page]).per(100)
#title = "Potential pals"
respond_to do |format|
format.html
format.js {
#find = #find
#users = #users
}
format.json { #find }
end
end
and I made a .json file for it to respond to (not sure if this is even necessary):
<% #find.each do |user| %>
<%= user.name %>
<% end %>
So, the json is working, to an extent. If I look in the developer console, it shows a response coming from http://localhost:3000/users.json?q=tay, or whereever, and it returns a single value, for Taylor (in that instance). But when I search inside of the select2 search box, it just spins and spins, with no results. No console errors, so that's nice, ha. Thoughts? Thanks!
The select2 plugin expects JSON data in the following format:
[ { "text": "Taylor", "id": 1 }, { "text" : "Tailor", "id": 2 }, ...]
So you need to replace name with text in your user model when converting to JSON:
def as_json(*args)
super.tap { |hash| hash["text"] = hash.delete "name" }
end
and then in the index method:
def index
#find = User.where('name LIKE ?', "%#{params[:q]}%")
#users = #find.where('id NOT IN (?)', current_user.id).order('random()').page(params[:page]).per(100)
#title = "Potential pals"
respond_to do |format|
format.html
format.js {
#find = #find
#users = #users
}
format.json { render json: #find, :only => [:text, :id] } # might be :name here ?
end
end
and you don't need the view for JSON.
I guess the problem is in your .json file, since select2 needs json array or json object. Try to remove it and respond with format.json { render json: #find.to_json }. Other code seems ok to me.