2

Let's say that I have: a 'Survey' with many 'Questions' which has many 'Answers'

If I had a 'Survey' that had 2 instances of a 'Question', let's call them: 'Good Question' and 'Bad Question'

'Good Question' has 5 'Answers' and 'Bad Question' has 3 'Answers'

If 'Good Question' and 'Bad Question' were connected sortable lists with this jQuery-UI interaction. http://jqueryui.com/sortable/#connect-lists

I know how to display them as 2 sortable lists using the jQuery-UI and I can also drop an 'Answer' from a 'Bad Question' to a 'Good Question'. But how would I save their new sorted positions and their newly sorted association to another 'Question' back to a Rails database?

Railscasts has how to save position for a single sortable lists but not for lists that belong to different associated models. http://railscasts.com/episodes/147-sortable-lists-revised

I really appreciate the help here!

EDIT

I realized that I just need to POST to the Rails controller, an element id of the list that I dropped the 'Answer' into (i.e <ol class = "connectableSortable" id = "Good_Question"</ol>)

This is the syntax for how the Railscast does a POST to the Rails Controller to pass an array of object_id's in the sortable order.

jQuery ->
  $('#faqs').sortable(
    axis: 'y'
    update: ->
      $.post($(this).data('update-url'), $(this).sortable('serialize'))
  )

How would I update this POST to pass the list ID to it, so I can just update the 'Question' foreign key for the 'Answer' to the list 'ID' that it fell into?

This SO answer has a way to retrieve the list ID. Get the item/object where the element is dropped

So now, I really just need to know how to pass an extra parameter back to the rails controller. Any help?

3
  • You can get the the position of the list using something like $('li.selected').index()
    – user1171884
    Commented Nov 2, 2012 at 23:58
  • I'm assuming the lists given by the Question instances are arrays of Answer instances? Then to make them into one array you do master_array = arr1 + arr2 and give that to jQuery. For you to save their newly sorted positions is a whole other thing though. You're actually wanting to save the lists order with respect to Survey, not Question. Just draw it on a piece of paper, starting with Survey on the left, then Questions all the way to Answers on the right. Also, can a Question be used in more that one survey?
    – ian
    Commented Nov 3, 2012 at 0:29
  • For now, a 'Question' only belongs to 1 'Survey'. Also, an 'Answer' only belongs to 1 'Question'. In this case, I'm trying to change the association between an 'Answer' and its 'Question'
    – Hung Luu
    Commented Nov 3, 2012 at 0:37

1 Answer 1

3

I was able to figure out what I wanted after a couple of days of struggling through this. The model here is a Day has many Activities (as opposed to the original question of a Question has many Answers).

This is my jQuery code (in Coffeescript): Using jQuery selectors to get the ID of each list item and the column ID of each list item. Pushing it as a Parameter that looks like this Activity:[{"id":"1", "column":"1"}, {"id":"2", "column":"1"}...etc]

jQuery ->
  $('[id*="day"]').sortable(
    connectWith: ".day"
    placeholder: "ui-state-highlight"
    update: (event, ui) ->
      neworder = new Array()
      $(this).children().each ->
        column = $(this).parent().attr("id").match(/\d+/)[0]
        id = $(this).attr("id").match(/\d+/)[0]
        neworder.push(
          id: id
          column: column
        )
      alert neworder
      $.ajax
        url: "sort"
        type: "POST"
        data: { Activity: JSON.stringify(neworder) }
    ).disableSelection()

How I parse the AJAX call back to the Rails Controller: I'm looping through each {"id":"1", "column":"1"}object in the array and also getting it's index position.

def sort
    JSON.parse(params[:Activity]).each_with_index do |x, index|
      idx = x["id"]
      positionx = index+1
      column = x["column"]
      activity = Activity.find(idx)
      activity.update_attributes(:position => positionx, :day_id => column)
    end
    render nothing: true
  end

Back in my Model, I order "Activities" association by it's Position so when I list it in the view, it shows up in the correct position.

class Day < ActiveRecord::Base
  has_many :activities, :order => 'position'
  accepts_nested_attributes_for :activities, allow_destroy: true 
end

More details for how I arrived to this in these 2 answers:

Formatting Parameters for Ajax POST request to Rails Controller - for jQuery-UI sortable list

jQuery AJAX POST to Rails Controller. Error when doing each_with_index (TypeError can't convert Symbol into Integer)

Not the answer you're looking for? Browse other questions tagged or ask your own question.