I'm making an ajax call to this method
def check_solution
puzzle = Puzzle.find(params[:id])
solved = puzzle.grid.solution == params[:solution].to_s
solved_before = params[:solved_before]
puts !solved_before
if(solved && !solved_before)
Puzzle.find(params[:id]).increment!(:times_solved, by =1)
end
respond_to do |format|
response = { :status => "ok", :message => "Success!", :html => solved}
format.json { render json: response }
end
end
The parameters going in from my local server are
Parameters: {"solution"=>"0001000010110011001100000", "solved_before"=>"false", "id"=>"3758"}
Why, when I print out !solved_before with puts, does it say false instead of true?
That's because solved_before comes in as a string and not as a boolean.
Related
I'm having a hard time getting something which should be incredibly simple to work.
I've got an online quiz with multiple choice questions and a pass/fail mark. I've got everything working correctly bar the damned emailer function at the end. No matter whether passed is set to true or false it's always sending out the passed email. Have I done something a bit daft in this code which I just can't see or am I going to have to go back through everything with a fine-tooth comb?
def finalize
quiztype = params[:quiztype]
slug = params[:slug]
#qd = Quizdata.where(quiztype: quiztype, usertoken: slug).take
if #qd
#qd.completed = true
quizdata = JSON.parse(#qd.quizdata)
quizdata["completed"] = true
#qd.quizdata = quizdata.to_json
#qd.passed = params[:passed]
if #qd.save
if params[:passed]
QuizMailer.results_email_user(quizdata, #qd).deliver
else
QuizMailer.results_email_user_failed(quizdata, #qd).deliver
end
QuizMailer.results_email_client(quizdata, #qd).deliver
render json: { errors: [] }
else
render :json => { :errors => #qd.errors.full_messages }, :status => 422 #Unprocessable entity
end
else
render :json => { :errors => [ "Record not found" ] }, :status => 404
end
end
Here you go:
Replace
if params[:passed]
with
if ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(params[:passed])
It was failing because, you are getting result in String format (not nil, which makes it return true always), instead of Boolean.
Hope it helps!
Parameters are passed as strings.
Should have been:
if params[:passed] == "true"
QuizMailer.results_email_user(quizdata, #qd).deliver
else
QuizMailer.results_email_user_failed(quizdata, #qd).deliver
end
In my Case model (case.rb) I have a few after_create callbacks. One of which is not functioning as expected.
By that I mean when I run it in the console, it works, but when creating it in the controller via an HTTP request, it does not.
Model code (the problem is with :create_case_users not working):
after_create -> { redis_check(true) },
:create_case_users,
:create_manager,
:pusher_trigger
And the create_case_users method:
def create_case_users
cus = CaseUser.where(:case_id => self.id, :is_age => 1)
cus.each do |cu|
connections = Connection.where({ :cases => 1, :con_id => cu.user_id })
connections.each do |connection|
if connection.user_id && connection.connection_id
case_user = CaseUser.new
case_user.case_id = self.id
case_user.user_id = connection.user_id
case_user.email = connection.cases_emails
case_user.is_age = 0
case_user.cm = 0
case_user.save!
end
end
end
end
When running the above snippet in the console of my app, specifying the Case to run it for, it works & creates the records I expect.
When I POST to /api/v1/cases, it hits this controller action:
#case = Case.new(case_params)
#case.current_user(#current_user)
if #case.save
render :json => #case,
:root => "case",
:status => :created,
:location => #case,
:serializer => CaseShowSerializer,
:current => #current_user
else
render :json => #case.errors,
:status => :unprocessable_entity
end
What could be the problem? The after create callback after create_case_users runs and functions as expected, meaning create_case_users isn't returning false.
Edit:
When running Case.find(500).create_case_users in the console it works.
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 just want to test that a controller method is passing an int.
Test:
it 'responds successfully with mocked fto hours remaining' do
get :fto_hours_remaining, {}, { "Accept" => "application/json" }
json = JSON.parse(response.body)
expect(json['hours_remaining']).to be_100
end
Controller method (I tried the commented out block too):
def fto_hours_remaining
#fto_hours_remaining = 100
render json: #fto_hours_remaining
# respond_to do |format|
# format.json { render :json => {:hours_remaining => #fto_hours_remaining} }
# end
end
I get the error: JSON::ParserError: 757: unexpected token at '100' with the error pointing to json = JSON.parse(response.body)
Anybody see a mistake? Thanks.
So you have right version in your controller:
def fto_hours_remaining
#fto_hours_remaining = 100
render :json => { :hours_remaining => #fto_hours_remaining }
end
Your action now render just string 100 this is invalid json.
Try in irb:
=> require 'json'
=> true
=> JSON.parse "100"
=> JSON::ParserError: 757: unexpected token at '100'
render( json: { hours_remaining: #fto_hours_remaining } ) means render me in json format this hash { hours_remaining: #fto_hours_remaining } that should be valid json:
{
"hours_remaining": 100
}
And your test:
# return string "100"
number = json['hours_remaining']
# fails beacause "100" != 100
expect(json['hours_remaining']).to be_100
# try this
expect(json['hours_remaining']).to eq("100")
In my ruby on rails code I want to send back json response to client. Since I am new to ruby on rails I do not know how can I do this. I want to send error = 1 and success = 0 as json data if data does not save to database and if it successfully saves that it should send success = 1 and error = 0 Please see my code below
here is my controller
class ContactsController < ApplicationController
respond_to :json, :html
def contacts
error = 0
success = 1
#contacts = Contact.new(params[:contact])
if #contacts.save
respond_to do |format|
format.json { render :json => #result.to_json }
end
else
render "new"
end
end
end
here is my javascript code
$('.signupbutton').click(function(e) {
e.preventDefault();
var data = $('#updatesBig').serialize();
var url = 'contacts';
console.log(data);
$.ajax({
type: 'POST',
url: url,
data: data,
dataType: 'json',
success: function(data) {
console.log(data);
}
});
});
There are tons of other elegant ways, but this is right:
class ContactsController < ApplicationController
def contacts
#contacts = Contact.new(params[:contact])
if #contacts.save
render :json => { :error => 0, :success => 1 }
else
render :json => { :error => 1, :success => 0 }
end
end
end
Add also a route to routes.rb. If you need to use html response you have to include respond_to do |format|.
You have to adjust your routes to accept json data
match 'yoururl' => "contacts#contacts", :format => :json
Then it will work