I have a rails app. I'm trying to integrate the fullcalendar into my app. For testing I created manually an event which shows up in the calendar after sending over with as_json to the browser. When I try to move (update) the event the js works but I can't save it to the db thanks to routing problems. In the code below I have it hard coded, so it works this way.
If I use in the AJAX: url: the_event.recipientId + "/events/" + the_event.id
then the console tells me: Started POST "/users/1/1/events/1" --> no route matches. If I use url: "/events/" + the_event.id
then started POST "/events/1" --> no route matches. So now I'm using event.url that is sent over from event.rb, but it is hard coded.
How could I set the matching urls for the current_user in the AJAX POST(for this I also need to find recipient (user) from db) and PUT call? For the PUT (update) recipient and sender are already defined so with the as_json method the data will be sent over to the browser. Here my problem is to tell in the model (event.rb) if the current_user is the sender or the recipient and set the url without hard coding as it is now. For the POST it's way harder. Browser should figure out who the current_user (sender) is based on url or somehow, and on the top of that it should be able to pick an existing user (recipient) from the db. How can I do this second part?
/users/1/events/json
[{"id":1,
"recipientId":1,
"senderId":2,
"title":"cool",
"body":"hahahhahhhaha",
"start":"2015-12-15T17:03:05.110-08:00",
"end":"2015-12-15T19:03:05.111-08:00",
"allDay":null,
"recurring":false,
"url":"/users/1/events.1"}] //hard coded in rails model since there is no current_user in model level
event.js
var updateEvent;
var ready = function() {
$('#calendar').fullCalendar({
editable: true,
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
defaultView: 'month',
height: 500,
slotMinutes: 30,
eventSources: [{ url: '/users/:user_id/events', }], // IS THIS LINE OKAY?
timeFormat: 'h:mm t{ - h:mm t} ',
dragOpacity: "0.5",
eventDrop: function(event, dayDelta, minuteDelta, allDay, revertFunc) {
return updateEvent(event);
},
eventResize: function(event, dayDelta, minuteDelta, revertFunc) {
return updateEvent(event);
select: function(start, end, allDay) {
var title = prompt('Event Title:');
$('#calendar').fullCalendar('renderEvent',
{
title: title,
start_at: start,
end_at: end,
allDay: allDay
},
true //making event stick
);
$.ajax({
type: "POST",
url: "/users/1/events",
data: { event: {
title: the_event.title,
start_at: "" + new Date(the_event.start).toUTCString(),
end_at: "" + new Date(the_event.end).toUTCString(),
body: the_event.body,
sender_id: the_event.senderId,
recipient_id: the_event.recipientId }
}
});
}
});
};
updateEvent = function(the_event) {
$.ajax({
type: "PUT",
url: the_event.url // used to be: the_event.recipientId + "/events/" + the_event.id, WHAT SHOULD I USE HERE?
data: { event: {
title: the_event.title,
start_at: "" + the_event.start,
end_at: "" + the_event.end,
body: the_event.body,
sender_id: the_event.senderId,
recipient_id: the_event.recipientId }
}
});
};
$(document).ready(ready);
$(document).on("page:load", ready);
events controller
class EventsController < ApplicationController
before_action :set_event, only: [:show, :edit, :update, :destroy]
def index
@events = current_user.events#.between(params['start'], params['end']) if (params['start'] && params['end'])
respond_to do |format|
format.html
format.json { render json: @events }
end
end
def show
respond_to do |format|
format.html
format.json { render json: @event }
end
end
def new
@event = Event.new
respond_to do |format|
format.html
format.js
end
end
def create
@event = Event.new(event_params)
@event.sender_id = current_user.id
respond_to do |format|
format.html
format.js
end
end
def edit
end
def update
respond_to do |format|
if @event.update_attributes(event_params)
format.html { redirect_to @event, notice: 'Event was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @event.errors, status: :unprocessable_entity }
end
end
end
def destroy
@event.destroy
respond_to do |format|
format.html { redirect_to user_events_path(current_user) }
format.json { head :no_content }
end
end
private
def set_event
@event = Event.find(params[:id])
end
def event_params
params.require(:event).permit(:recipient_id, :sender_id, :title, :body, :start_at, :end_at, :all_day)
end
end
event.rb
class Event < ActiveRecord::Base
belongs_to :recipient, class_name: "User", foreign_key: "recipient_id"
belongs_to :sender, class_name: "User", foreign_key: "sender_id"
scope :between_time, -> (start_time, end_time) do
where("? < start_at < ?", Event.format_date(start_time), Event.format_date(end_time))
end
scope :allevents, -> (u) { where('sender_id = ? OR recipient_id = ?', u.id, u.id) }
scope :between, -> (sender, recipient) do
where("(events.sender_id = ? AND events.recipient_id = ?) OR (tasks.sender_id = ? AND tasks.recipient_id = ?)", sender.id, recipient.id, recipient.id, sender.id)
end
def self.format_date(date_time)
Time.at(date_time.to_i).to_formatted_s(:db)
end
def as_json(options = {})
{ id: self.id,
recipientId: self.recipient_id,
senderId: self.sender_id,
title: self.title,
body: self.body || "",
start: start_at,
:end => end_at,
allDay: self.all_day,
recurring: false,
url: Rails.application.routes.url_helpers.user_event_path(self.recipient_id, self.id)
#self.recipient hard coded, it could be self.sender if self.sender == current_user
}
end
# def event_interlocutor(event)
# current_user == event.recipient ? event.recipient_id : event.sender_id
# end
end
regarding "is this line ok" lines:
eventSources: [{ url: '/users/:user_id/events', }], // IS THIS LINE OKAY?
you are mixing up your js and ruby which is why it isn't working.
'/users/:user_id/events'
is not a route. '/users/12234/events
is a route. Your js does not understand what :user_id
is -> you have to actually put a real user id in there.
the one thing I notice is missing from your controller code is anywhere where you instantiate an actual user... do you have current_user
? (ie are you using devise for users to login?) if so then you could plausibly use this:
eventSources: [{ url: '/users/<%= current_user.id %>/events', }], // IS THIS LINE OKAY?
however - I notice that your js file is named "events.js" and is thus not ruby-related at all - in which case the above is also not going to work because there's no ruby in a plain js file.
You will need to set some kind of javascript environment variable in your erb template... that the javascript code can access.
this is getting iffy in my own knowledge but I'd say a horrible, nasty hack would be to do something like:
<script>
var user_id = <%= current_user.id %>
</script>
I DO NOT RECOMMEND that you actually do this... google a better way - there must be some tutorials on integrating devise into your js in rails. It's here just to show you how your js and ruby must interact in order for the information to be available to your js.
来源:https://stackoverflow.com/questions/34323316/fullcalendar-passing-js-vars-to-rails-and-vice-versa