Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
325 views
in Technique[技术] by (71.8m points)

jquery - fullcalendar passing js vars to rails and vice versa

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
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...