I am trying to make a very simple ajax call with Rails 4, but the json response is not being retrieved properly.
Here's the script:
$(document).on "submit", "form[name=upvote-form]", ->
form = $(this)
$.post "/vote", $(this).serialize(), (data) ->
if data["status"] is true
form.find("input").addClass "disabled"
$("#vote-count-".concat(form.find("#question_id").attr("value"))).html data["votes"]
else
return
return
alert(data['votes']) is undefined, which made me try to find what was going wrong.
Then in the console I could see this:
ArgumentError (Nil location provided. Can't build URI.):
app/controllers/vote_controller.rb:8:in `vote'
And here's the method with the problem:
class VoteController < ApplicationController
def vote
question_id = params[:question][:id]
user_id = current_user.id
vote = Vote.where(["question_id = :q", { q: question_id }]).where(["user_id = :u", { u: user_id }]).take
respond_to do |format|
if vote.nil?
#vote = Vote.new
#vote.question = Question.find question_id
#vote.user = User.find user_id
#vote.save
votes = Vote.where(["question_id = :q", { q: question_id }]).count
format.json { render :json => { status: true, votes: votes } }
else
format.json { render :json => { status: false } }
end
end
end
end
Any clue of what's going wrong? And what can I do?
respond_with is meant to be used with a resource. Example
def show
#vote = Vote.find params[:id]
respond_with(#vote)
end
In your case, you need to use the respond_to method
def vote
# stuff
respond_to do |format|
if vote.nil?
# stuff
format.json { render json: { status: true, votes: votes } }
else
# other stuff
end
end
end
Related
I have a problem with HTML sortable update in rails 6
I want to drag and drop the images through web page and that is worked fine but, When I want to update the order I got 404 not found error in console log and also an error in find ID.
by the way, I use this script for HTML sortable
https://github.com/jordanhudgens/devcamp-portfolio/blob/master/app/assets/javascripts/html.sortable.js
Controller :
class PortfoliosController < ApplicationController
before_action :set_portfolio_item, only:[:edit , :show, :update , :destroy]
layout "portfolio"
access all: [:show, :index , :angular], user: {except: [:destroy, :new , :create , :update , :edit , :sort]}, site_admin: :all
def index
# You can filter what you want to show in protfolio
# Portfolio.where(subtitle: "Angular")
# You can define it in models and call the method here
# It must create on Portfolio.rb in models
# You can create scope too on models and call
#portfolio_items = Portfolio.by_position
end
def angular
#angular_portfolio_items = Portfolio.angular
end
def sort
params[:order].each do |key, value|
Portfolio.find(value[:id]).update(position: value[:position])
end
head :ok
end
def new
#portfolio_item = Portfolio.new
3.times { #portfolio_item.technologies.build }
end
def create
#portfolio_item = Portfolio.new(portfolio_params)
respond_to do |format|
if #portfolio_item.save
format.html { redirect_to portfolios_path, notice: 'Portfolio was successfully created.' }
else
format.html { render :new }
end
end
end
def edit
end
def update
respond_to do |format|
if #portfolio_item.update(portfolio_params)
format.html { redirect_to portfolios_path, notice: 'The record was successfully updated.' }
else
format.html { render :edit }
end
end
end
def show
end
def destroy
# Perform the lookup
# Destroy/delete the record
#portfolio_item.destroy
#Redirect
respond_to do |format|
format.html { redirect_to portfolios_url, notice: 'Portfolio was successfully deleted!.' }
end
end
private
def portfolio_params
params.require(:portfolio)
end
def set_portfolio_item
#portfolio_item = Portfolio.find(params[:id])
end
end
This is my routes.rb
Rails.application.routes.draw do
devise_for :users, path: '', path_names: { sign_in: 'login', sign_out: 'logout', sign_up: 'register' }
resources :portfolios, except: [:show] do
put :sort, on: :collection
end
get 'portfolio/:id' , to: 'portfolios#show', as: 'portfolio_show'
get 'angular-items' , to: 'portfolios#angular'
# we can pass anything here after get
get 'about', to: 'pages#about'
get 'contact', to: 'pages#contact'
resources :blogs do
member do
get :toggle_status
end
end
resources :posts
root to: 'pages#home'
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
This is my CoffeeScript for HTML sortable
ready = undefined
set_positions = undefined
set_positions = ->
$('.card').each (i) ->
$(this).attr 'data-pos', i + 1
return
return
ready = ->
set_positions()
$('.sortable').sortable()
$('.sortable').sortable().bind 'sortupdate', (e, ui) ->
updated_order = []
set_positions()
$('.card').each (i) ->
updated_order.push
id: $(this).data('id')
position: i + 1
return
$.ajax
type: 'PUT'
url: '/portfolios/sort'
data: order: updated_order
return
return
$(document).ready ready
Thanks for your helps!
i'm trying to fetch data from database in rails, this is my controller file
class PathsController < ApplicationController
before_filter :authenticate_user!
skip_before_filter :verify_authenticity_token
def getall
#result = Path.select('x', 'y')
end
respond_to do |format|
format.json { render json: #result }
end
end
Here is my js function
function makelines()
{
$.ajax({
type: "GET",// => method type
url: "/path", // => Target function that will be return result
contentType:"application/json",
success: function(result){
result = JSON.parse(result);
console.log(result);
}
});
}
Here is the route
match '/path => 'Paths#getall', via: [:get, :post], :default => { :format => 'json' }
The first thing you should do in this circumstance is consult your console or logs; that will be the most helpful in pinpointing the exception.
That said, I'll take a guess and warrant that the issue is that you are invoking a respond_to outside of a controller action
def getall
#result = Path.select('x', 'y')
end
respond_to do |format|
format.json { render json: #result }
end
Should be:
def getall
#result = Path.select('x', 'y')
respond_to do |format|
format.json { render json: #result }
end
end
Let's improve your code a little bit:
def getall
#results = Path.select('x', 'y')
respond_to do |format|
if #results.count > 0
format.json { render json: #results, , status: :ok }
else
format.json { render json: #results.errors, , status: :not_found }
end
end
end
Per Rails conventions it would be better to return results instead of result as you are returning more than 1 item.
I also think that as you are returning a JSON object to your AJAX method it would be good to return either a 200 (:ok) or a 404 (:not_found, in the event no record is in the database)
I am trying to post data (jQuery ajax) to a custom method in my controller so that I can build dynamic database queries, I am taking values from a dropdown menu and using them as my search queries.
My method
class PublicController < ApplicationController
def rehomed(query={})
Animal.where(query).to_json
respond_to do |format|
format.js {render :json => {} }
end
end
end
Ajax call
$('select.btn').on('change', function() {
var animal_type = $('#animalType option:selected').text();
var animal_town = $('#animalTown option:selected').text();
$.ajax({
type: 'POST',
url: '/public/rehomed',
data: {
animal_type: animal_type
},
success: function(data) {
console.log(data);
}
});
});
So as an example if a user selects 'Cat' from the dropdown menu the query from my method should be
Animal.where(animal_type: 'Cat')
at the moment the query it is performing is
SELECT "animals".* FROM "animals"
which is just selecting every animal
How do I make this happen? what do I pass within {render :json => {} }
I'm trying to figure out how to put all this together.
You need to capture and pass the result of the query. Use params to get the param information from the request.
def rehomed
#animals = Animal.where(animal_type: params[:animal_type])
respond_to do |format|
format.js {render :json => #animals }
end
end
Or in one line
def rehomed
respond_to do |format|
format.js {render :json => Animal.where(animal_type: params[:animal_type])}
end
end
Note I'm not calling #to_json given that render :json will convert the query result to json.
Change jQuery to this:
$('select.btn').on('change', function() {
var animal_type = $('#animalType option:selected').text();
var animal_town = $('#animalTown option:selected').text();
$.ajax({
type: 'POST',
url: '/public/rehomed',
data: { 'query': { 'animal_type': animal_type } }, // or 'name': animal_name etc
success: function(data) {
console.log(data);
}
});
});
then in controller:
class PublicController < ApplicationController
def rehomed
respond_to do |format|
format.js { render :json => Animal.where(params[:query]) }
end
end
end
Note: queries as shown above may open a serious security issue, so do NOT do it unless you have a very strong reason or you know what you're doing.
If you don't change the jQuery shown above, then you will have to fetch the submitted value presented in params inside your controller like this :
def rehomed
respond_to do |format|
format.js { render :json => Animal.where(:animal_type => params[:animal_type]) }
end
end
For some reason after a click my button that requests data from my controller, my table disappears. Here is my table:
<div id="SelectedTm" style= float:right>
<table id = "PlyrsTm2" style = float:right>
<tr><th id="PTTitle" colspan=2>List of players on selected team</th></tr>
<tr><th id="PTHRows">Player</th><th id="PTHRows">Team</th></tr>
<% #pl.each do |f| %>
<tr><td class="player"><%= f.Plyr %></td><td class="team"><%= f.Team%></td></tr>
<% end %>
</table>
</div>
Here is the button that triggers my jquery with ajax
<button id="showbtn">Select Team</button>
Here is the jquery and ajax:
$(document).ready(function(){
$('#showbtn').on('click', function() {
ids = $('#teams').val()
IM = false
$.ajax({
url: "http://localhost:3000/teamplayers.json?resolution="+ids+"&import="+IM,
type:"get",
dataType: "json",
cache: true,
success:function(data){
$('#PlyrsTm2').html(data);
alert("Loading Players....");
},
error: function(error) {
alert("Failed " + console.log(error) + " " + error)
}
});
$('#PlyrsTm2').trigger('create');
return false;
});
});
Now as you can see, my table is populated by rails. Every time i select a new team the table disappears. And only re-appears if I reload the page, but that is the originally selected team, which by default is the first one.
UPDATE
Here is my controller:
class TeamplayersController < ApplicationController
before_filter :set_id
before_action :set_id, :set_teamplayer, only: [:show, :edit, :update, :destroy]
# GET /teamplayers
# GET /teamplayers.json
def index
#teamplayers = Teamplayer.all
#fteams = Fteam.all
tid = params[:resolution]
toimport = params[:import]
puts tid
if tid.nil? == true
tid = 1
#ids = tid
#pl = Teamplayer.joins(:live_player).where(:teamid => #ids).all
else
tid = tid.to_i;
#ids = tid
#pl = Teamplayer.joins(:live_player).where(:teamid => #ids).pluck(:Plyr, :Team)
end
if toimport == "true"
#turl = Fteam.where(:id => #ids).pluck(:TeamUrl)
#turl = #turl[0]
system "rake updateTm:updateA[#{#turl},#{#ids}]"
end
end
# GET /teamplayers/1
# GET /teamplayers/1.json
def show
end
# GET /teamplayers/new
def new
#teamplayer = Teamplayer.new
end
# GET /teamplayers/1/edit
def edit
end
# POST /teamplayers
# POST /teamplayers.json
def create
#teamplayer = Teamplayer.new(teamplayer_params)
respond_to do |format|
if #teamplayer.save
format.html { redirect_to #teamplayer, notice: 'Teamplayer was successfully created.' }
format.json { render action: 'show', status: :created, location: #teamplayer }
else
format.html { render action: 'new' }
format.json { render json: #teamplayer.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /teamplayers/1
# PATCH/PUT /teamplayers/1.json
def update
respond_to do |format|
if #teamplayer.update(teamplayer_params)
format.html { redirect_to #teamplayer, notice: 'Teamplayer was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #teamplayer.errors, status: :unprocessable_entity }
end
end
end
# DELETE /teamplayers/1
# DELETE /teamplayers/1.json
def destroy
#teamplayer.destroy
respond_to do |format|
format.html { redirect_to teamplayers_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_teamplayer
#teamplayer = Teamplayer.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def teamplayer_params
params.require(:teamplayer).permit(:playerid, :teamid)
end
end
So what is going wrong here, because i notice that it is calling every records individual page but why is it now giving my back the the information from my query as the data instead?
Looks like the statement ids = $("#teams").val(); will return undefined, since there is no element with id="teams".
If ids is undefined, it's likely that data is null or undefined in this function call:
function(data){
$('#PlyrsTm2').html(data);
alert("Loading Players....");
}
If data is null, calling html(null) will cause all your table data to disappear.
So, the solution is to populate ids correctly. I'm not sure what ids is supposed to do, but that's most likely the solution.
$('#PlyrsTm2').html(data);
That's why your table disappears
The problem is you're replacing the content of this element (not the element itself). To fix this, I'd do this:
$('#SelectedTm').html(data);
I want to the following thing to happen:
When I select a selectbox I want it to send a JSON object through AJAX to my controller like so :
var encoded = $.param(data);
jQuery.ajax ({
url: '/trips',
type: 'GET',
data: {'toSearch' : encoded},
success: function (response) {
//succes
console.log(encoded);
}
});
and use these as params for my query like so
respond_to :json, :html
def index
#trips = Trip.scoped
#trips.where("category_id = ?", params[:category_ids]) if params[:category_ids] # category_ids = array; select * from trips where category_id IN [1,3,4]
respond_with #trips
end
How do I do this? and what is the best way to serialize my JSON object?
You can do the following:
def index
#trips = Trip.scoped
#trips.where("category_id = ?", params[:category_ids]) if params[:category_ids] # category_ids = array; select * from trips where category_id IN [1,3,4]
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #trips }
format.json { render :json => #trips }
end
end
Then you should do whatever you want to in the javascript callback.
Edit
If you want just the json format you can do the following:
render :json => #trips
You can also check the Layouts and Rendering in Rails guide.