0

When a :user_id is selected how can we show in the following collection_select that user's challenges? In other words, how can we make

@challenges = @user.challenges.order(:created_at)

For example,

enter image description here

As you can see all the challenges are listed and even if I change the user all the challenges are still listed. The javascript never kicks in to just list the challenges for that respective user.

schema

  create_table "duelers", force: true do |t|
    t.integer  "user_id"
    t.integer  "challenge_id"
    t.datetime "created_at",     null: false
    t.datetime "updated_at",     null: false
    t.integer  "duel_id",        null: false
    t.boolean  "accept"
    t.string   "user_name"
    t.string   "user_last_name"
    t.string   "challenge_name"
  end

  add_index "duelers", ["duel_id"], name: "index_duelers_on_duel_id", using: :btree

  create_table "duels", force: true do |t|
    t.text     "consequence"
    t.text     "reward"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
  end

models

class Duel < ActiveRecord::Base
  belongs_to :user
  belongs_to :challenge
  has_many :duelers
  accepts_nested_attributes_for :duelers, :reject_if => :all_blank, :allow_destroy => true #correct
end

class Dueler < ActiveRecord::Base
  belongs_to :user
  belongs_to :challenge
  belongs_to :duel
end

routes

get 'duels/user_challenges', :to => 'duels#user_challenges', as: 'user_challenges'

duels_controller

def user_challenges
  @user = User.find(params[:id])
  @challenges = @user.challenges.order(:created_at)
end

def new
  @duel = Duel.new
  @duel.duelers << Dueler.new(user_id: current_user.id, user_name: current_user.name, user_last_name: current_user.last_name)
respond_with(@duel)
end

duels/_form

<%= simple_form_for(@duel) do |f| %>
  <%= f.fields_for :duelers do |dueler| %>
    <%= render 'dueler_fields', :f => dueler %>
  <% end %>
  <%= link_to_add_association f, :duelers do %>
    + Dueler
  <% end %>
  The loser(s) will <%= f.text_field :consequence, placeholder: "Enter Consequence" %>
<% end %>

duels/_dueler_fields.html.erb

<%= f.select :user_id, User.order(:name).map { |user| [user.full_name, user.id] }, include_blank: true, id: "change-challenge-options" %>

  will

<%= render partial: 'user_challenges', locals: { challenges: Challenge.order(:created_at) } %>

<script> # Upon changing :user_id this javascript never triggers, how to fix it? Not sure if just javascript problem or also controller or ruby
    $( "#change-challenge-options" ).change(function() {
         $.ajax({
            type: "GET",
            url: '<%= user_challenges_path %>',
            data: {name: $('#change-challenge-options').prop('value')}
         });
    });
</script>

duels/_user_challenges.html.erb

<div id="dropdown-no-2">
  <%= collection_select(:dueler, :challenge_id, challenges, :id, :full_challenge, include_blank: true) %>
</div>

user_challenges.js.erb

$("#dropdown-no-2").html('<%=j render :partial => "user_challenges", locals: {challenges: @challenges} %>'); 
Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
AnthonyGalli.com
  • 2,796
  • 5
  • 31
  • 80
  • 1
    the information you've provided is helpful to debug your problem but it's not apparent how you've tried to solve this issue. what in specific are you trying to do - javascript (is the data already loaded and filterable through the client?), ajax or synchronous route? Your solution depends on which approach you're going for. – max pleaner Oct 01 '16 at 07:54
  • @maxpleaner whatever gets the job done, probably AJAX though, sorry I'm not very good at javascript. Whatever it takes to get it where when a user is chosen only his respective challenges will show in `collection_select`. Sorry been at this for weeks and I'm just slamming my face against the keyboard at this point. – AnthonyGalli.com Oct 01 '16 at 09:01
  • ok, I think I see where your problem is and I've posted an answer. In this case, though, only the code in `duels/_dueler_fields.html.erb` was relevant and including all those other code snippets in the question made it little difficult to find what problem was. People on StackOverflow often tell posters to include more code with their question, which is valid. But on the flipside there are also "code dumps", which are discouraged as well. You're question sort of appeared like a code dump, which is why some people flagged it to be closed. – max pleaner Oct 01 '16 at 18:31
  • Yea you are definitely right. I'll reduce the code once the question is hopefully solved. I put a lot there because I really wasn't sure what the root of the problem was, which at least you help me narrow down @maxpleaner :) – AnthonyGalli.com Oct 02 '16 at 07:34

1 Answers1

0

This line is what you'd need to change:

$( "#change-challenge-options" ).change(function() {

The problem is that the DOM selector is being run before the page is in a ready state. If you run some test like this

var nodes = $("#change-challenge-options")
console.log(nodes.length)

You'd probably see that the nodes list is empty.

In a static website you'd wrap it in $(function(){}) or document.ready(function(){}), but Rails makes it slightly more complicated by adding turbolinks.

In a Rails app, you have a couple options.

You can follow the advice here and wrap your DOM related code in a special listener:

$(document).on('turbolinks:load', function() {
    $( "#change-challenge-options" ).change(function() {
        ...
    }
});

OR you can follow the advice from the jquery.turbolinks gem. You'd first install the gem and add the dependency to application.js, then you'd refactor your code in the following ways:

  1. Bind your events outside of the document.ready block. This might seem counter-intuitive; this whole time I've been advising putting everything in that block.
  2. Refactor the change listener to use the following syntax:

    $(document).on('change', '#change-challenge-options', function() {
       ... 
    })
    

If all this is proving difficult, you can remove turbolinks references from the Gemfile, application.js, and application.html.erb. Then the typical document.ready code would suffice:

$(function(){
  <all your custom code>
})
Community
  • 1
  • 1
max pleaner
  • 26,189
  • 9
  • 66
  • 118
  • Yea I don't use `turbolinks` because it conflicts with other gems I use, but your last code chunk fired, which I tested with `$(function(){ console.log("Fired!"); });`, but then once I put in my custom code it didn't fire. I tried various versions like, `$(function(){ $.ajax({ console.log("Fired!"); type: "GET", url: '<%= user_challenges_path %>', data: {name: $('#change-challenge-options').prop('value')} }); });` – AnthonyGalli.com Oct 02 '16 at 07:48