I am using angularjs-rails-resource and I have set up a service. I have a table of leagues which belongs_to a user so the columns of the league table are id, name, and user_id. I am trying to pull out all the leagues for a specified user.
Here's the code. Every time I use it I am getting all the leagues returned. I am pretty sure I don't have the service defined correctly. Any help would be greatly appreciated.
league_service.js
'use strict';
/* Services */
var ffpServices = angular.module('ffpServices', ['rails']);
ffpServices.factory('League', ['railsResourceFactory', function (railsResourceFactory) {
return railsResourceFactory({
url: '/api/v1/leagues',
name: 'league'
}); }]);
leagues_controller.js
'use strict';
/* Controllers */
var ffpControllers = angular.module('ffpControllers', []);
ffpControllers.controller('LeagueCtrl',
function ($scope, $routeParams, League) {
$scope.leagues = League.query({ user_id: $routeParams.userId });
$scope.leagues.then(function (results) {
$scope.leagues_data = [];
$scope.leagues_data = results;
$scope.lempty = false;
if ($scope.leagues_data.length < 1) {
$scope.lempty = true;
}
}, function (error) {
console.log(error);
});
});
leagues_controller.rb
class Api::V1::LeaguesController < ApplicationController
respond_to :json
def index
#leagues = League.all
render json: #leagues
end
def show
#league = League.find(params[:id])
render json: #league
end
def create
#league = current_user.leagues.new(league_params)
respond_to do |format|
if #league.save
format.json { head :created, location: league_path(#league) }
else
format.json { head :unprocessable_entity }
end
end
end
private
def league_params
params.require(:league).permit(:name)
end
end
Related
I am trying to redo my react rails app with gresql so that I can deploy it with heroku. So far everything is working fine except the fetch POST request. I am getting a 404 (Not Found) error and binding.pry isn't coming up in my terminal so I can't see from the controller.
I think it might have something to do with how it is sending back json with render :json. Before I was using respond_to do |format| format.json {.
import fetch from 'isomorphic-fetch';
export function saveData(rec) {
debugger
return function(dispatch){
return fetch(`/api/v1/charts`, {
credentials: "include",
method: "POST",
headers: {
'Accept': "application/json",
'Content-Type': "application/json",
},
body: JSON.stringify(rec)
})
.then(res => {
return res.json()
}).then(data => {
debugger
dispatch({type: 'ADD_CHART', payload: data})
})
}
}
module Api::V1
class ChartsController < ApplicationController
def index
#charts = Chart.all
render json: #charts, include: ["people", "weights"]
end
def create
binding.pry
#chart = Chart.create(chart_params)
render json: #chart, include: ["people", "weights"]
end
def destroy
Chart.find(params[:id]).destroy
end
private
def chart_params
params.require(:chart).permit(:id, :date, people_attributes: [:name, weights_attributes: [:pounds, :currentDate] ])
end
end
end
module Api::V1
class PersonsController < ApplicationController
def index
#persons = Person.all
render json: #persons, include: "weights"
end
def create
binding.pry
#person = Person.create(person_params)
render json: #person, include: "weights"
end
private
def person_params
params.require(:person).permit(:id, :name, weights_attributes: [:pounds, :currentDate])
end
end
end
module Api::V1
class WeightsController < ApplicationController
def index
#weights = Weight.all
render json: #weights
end
def create
binding.pry
e = Weight.where(:person_id => params[:person_id], :currentDate => params[:currentDate])
if !e.empty?
e.first.pounds = params[:pounds]
e.first.save!
#weight = e
else
#weight = Weight.create(weight_params)
end
render json: #weight
end
private
def weight_params
params.require(:weight).permit(:id, :pounds, :currentDate, :person_id)
end
end
end
class ApplicationController < ActionController::API
end
If you've declared resource routes for your charts, you need to change this line:
return fetch(`/api/v1/charts`, {
to:
return fetch(/api/v1/chart, {
As is, charts is likely triggering a POST to your index action.
Changing my fetch to the full url and removing credentials: "include" worked
import fetch from 'isomorphic-fetch';
export function saveData(rec) {
debugger
return function(dispatch){
var url = 'http://localhost:3001/api/v1/charts';
return fetch(url, {
method: "POST",
headers: {
'Accept': "application/json",
'Content-Type': "application/json",
},
body: JSON.stringify(rec)
})
.then(res => {
return res.json()
}).then(data => {
debugger
dispatch({type: 'ADD_CHART', payload: data})
})
}
}
I have installed full calendar into my ruby on rails app. I cannot figure out why changes are not persisting. I want to use the drag/drop and resize features. I have followed their documents but I'm stuck.
I think i've made an error on callback url?
I appreciate the help!
Fullcalendar docs:
https://fullcalendar.io/docs/eventResize
appointment_calendar.js:
$(document).ready(function() {
var arr = $('#business_appointment').data('url');
var calendar = $('#calendar').fullCalendar({
header: {
left: 'prev,next today myCustomButton',
center: 'title',
right: 'month,agendaWeek,agendaDay,listWeek',
},
defaultView: 'agendaWeek',
editable: true,
selectable: true,
nowIndicator: true,
timezone: "Australia/Brisbane",
events: arr,
//header and other values
select: function(start, end, allDay) {
starttime = moment(start).format("ddd, MMM Do YYYY, h:mm a");
endtime = moment(end).format("ddd, MMM Do YYYY, h:mm a");
todaytime = moment().format("ddd, MMM Do YYYY, h:mm a");
var mywhen = starttime + ' - ' + endtime;
$('#createEventModal #appointment_from').val(starttime);
$('#createEventModal #appointment_to').val(endtime);
$('#createEventModal #apptAllDay').val(allDay);
$('#createEventModal #when').text(mywhen);
$('#createEventModal').modal('show');
},
eventDrop: function(event, delta, revertFunc) {
event_data = {
event: {
id: event.id,
start: event.start.format(),
end: event.end.format()
}
};
$.ajax({
url: "/app/calendar/" + calEvent.id + "/edit",
data: event_data,
type: 'PATCH'
});
},
eventResize: function(event, delta, revertFunc) {
alert(event.title + " end is now " + event.end.format());
if (!confirm("is this okay?")) {
revertFunc();
}
},
eventClick: function(calEvent, jsEvent, view) {
$.ajax({
type: 'GET',
url: "/app/calendar/" + calEvent.id + "/edit",
dataType: "script"
});
},
eventRender: function(event, element)
{
element.find('.fc-time').append("<br/>" + event.residentname);
element.find('.fc-time').append("<br/>" + event.appointmenttype);
}
});
$('#submitButton').on('click', function(e){
// We don't want this to act as a link so cancel the link action
e.preventDefault();
doSubmit();
});
function doSubmit(){
$("#createEventModal").modal('hide');
console.log($('#apptStartTime').val());
console.log($('#apptEndTime').val());
console.log($('#apptAllDay').val());
$("#calendar").fullCalendar('renderEvent',
{
title: $('#residentName').val(),
start: new Date($('#apptStartTime').val()),
end: new Date($('#apptEndTime').val()),
allDay: ($('#apptAllDay').val() == "true"),
},
true);
}
});
calendar_controller.rb:
require "datetime_format"
class App::CalendarController < App::BaseController
include DateTimeFormat
before_action :set_appointment, only: [:edit,:update]
def index
#arr = []
#business_appointments = current_business.appointments
#business_appointments.each do |business_appointment|
hash = {}
hash["start"] = business_appointment.start
hash["end"] = business_appointment.end
hash["title"] = business_appointment.name
hash["residentname"] = "#{business_appointment.resident.first_name} #{business_appointment.resident.last_name}"
hash["appointmenttype"] = business_appointment.appointment_type.name
hash["id"] = business_appointment.id
#arr << hash
end
#global_arr = #arr
#appointment = current_business.appointments.new
end
# POST/calender_appointment
def create
#appointment = current_business.appointments.new(appointment_params)
#appointment.author_id = current_user.id
respond_to do |format|
if #appointment.save!
format.html { redirect_to app_calendar_index_path, notice: 'Appointment was successfully created.' }
format.json { render :index, status: :created, location: #appointment }
else
format.html { redirect_to app_calendar_index_path, notice: 'Unable to create appointment.' }
format.json { render json: #appointment.errors, status: :unprocessable_entity }
end
end
end
def edit
end
# PATCH/PUT /update_calender_appointment
def update
#appointment.author_id = current_user.id
respond_to do |format|
if #appointment.update(appointment_params)
format.html { redirect_to app_calendar_index_path, notice: 'Appointment was successfully updated.' }
format.json { render :show, status: :ok, location: #appointment }
else
format.html { redirect_to app_calendar_index_path, notice: 'Unable to update appointment.' }
format.json { render json: #appointment.errors, status: :unprocessable_entity }
end
end
end
private
def set_appointment
#appointment = current_business.appointments.find(params[:id])
end
def appointment_params
if params[:action].eql?("create")
params[:appointment][:start] = format_datetime(params[:start]).to_datetime
params[:appointment][:end] = format_datetime(params[:end]).to_datetime
end
params.require(:appointment).permit(:name, :description, :start, :end, :resident_id, :appointment_type_id)
end
end
It was my error, needed to add this code:
updateAppointment = (event) => {
let event_data = {
appointment: {
id: event.id,
start: event.start.format(),
end: event.end.format()
}
};
$.ajax({
url: "/app/calendar/" + event.id,
data: event_data,
type: 'PUT'
});
}
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
so i have this controller and i want to add a dynamic attribute along with the other data in the #events instance variable
i have search and tried things like #events.attributes.merge(appointment: true)
appointment = true is what i want to add to the events object.
def find
params = event_params
current_user = 2
#events = Event.where('date LIKE ?',"%#{params[:month]}%")
def #events.as_json(options = { })
h = super(options)
h[:appointments] = false # Or combine with above h[:appointments] = self.appointments?
h
end
respond_to do |format|
if current_user == 1
if #events
format.json {
render json: #events.to_json
}
else
render 'index'
end
else
format.json {
render json: #events.to_json
}
end
end
end
ajax code here
function retrieve(date_partial) {
var jsondata = {
events: {
month: date_partial,
}
}
$.ajax({
cache: false,
type: "POST",
url: "/events/find",
data: jsondata,
success: function(data) {
console.log(data);
for (var i = 0; i < data.length; i++) {
var day = data[i].date.substring(0, 2);
$("td[data-day='" + day + "']").addClass('added');
}
},
error: function(xhr) {
alert("The error code is: " + xhr.statusText);
}
});
so how can i add that property?
This could work ? But then maybe the JSON output isn't what you expected ?
format.json { render :json => {events: #events, appointments: true} }
Because this property is view oriented, the model should not know about it. A better way to do this, is to use a decorator, which will allow you to add what ever attributes you want in the manner you want, without polluting the model.
you can create a PORO object
like this one
# this is by no means a complete implementation, but just for you
# to get the idea
class EventDecorator
# use ( delegate :event_attribute, to: :event ) to delegate
# all the event attributes and to be able to access them
# as if they were declared on the decorator itself
attr_reader :event
attr_accessor :appointment
def initialize(event)
#event = event
#appointment = false
end
def to_json
event.attributes.merge(appointment: appointment).to_json
end
end
a better way is to use the draper gem. You can find a good explanation in this railscat, #286 Draper
Two ways to do that I can think of: adding an instance variable or a custom method (or something hybrid)
EDIT : Forget what I said about creating an instance variable out of nowhere (see this answer)^^"
Method
#events.define_singleton_method(:appointments?){true/false}
#events.appointments? # => true/false
EDIT 2 : AJAX/JSON override
See this answer
def #events.as_json(options = { })
h = super(options)
h[:appointments] = true/false # Or combine with above h[:appointments] = self.appointments?
h
end
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