1

I have an AJAX call in my application.js which sends 3 pieces of data to my events_controller#check action:

//application.js
    $(document).on('click', "#check-button", function(){

        ...

        $.ajax({
                url: '/events/check',
                data: {checkList: checkList , selected_date: selectedDate , length: length },

            }
        );

    });

my check action:

#events_controller.rb
def check
    checkList = params[:checkList]
    selected_date = params[:selected_date]
    length = params[:length]

    busy_array = Array.new #this needs to be rendered in the view

    ...
    busy_array.push(user.id) #busy_array is a list of user ids from database


  end


#routes.rb
resources :events do
    get :check, on: :collection
  end

The view:

<button id="check-button" type="button">Check</button>

          <div class = "col-md-6" id="unavailable">
            <h2>Unavailable on this day:</h2>
            <ol id="unavailable-list">
              <li>THIS LIST SHOULD BE POPULATED BY BUSY_ARRAY</li>
            </ol>
      </div>

Now I need to send back data from events_controller#check to the view, but I don't know how to send busy_array to be rendered in events\new.html.erb

Thanks for you help, I am a ruby/JS beginner

2 Answers 2

2
busy_array = Array.new #this needs to be rendered in the view

If that has to be available in the view, you need to define an @instance variable:

def check
    checkList = params[:checkList]
    selected_date = params[:selected_date]
    length = params[:length]

    @busy_array = Array.new
    ...
    @busy_array.push(user.id) #busy_array is a list of user ids from database
end

Each time you call a controller#action, the data/variables within the action are bound by local scope.

Outputting data in the view requires the variable to be made available across the entire instance of the class (not just the action/function). Thus @busy_array.


Fix

#app/views/events/....
<%= button_to "Check", events_check_path %>

<div class = "col-md-6" id="unavailable">
  <h2>Unavailable on this day:</h2>
  <ol id="unavailable-list">&nbsp;</ol>
</div>

#app/assets/javascripts/application.js
$(document).on('click', "#check-button", function(e){
  ...
  $.get('/events/check', {checkList: checkList , selected_date: selectedDate , length: length});
});

#app/controllers/events_controller.rb
class EventsController < ApplicationController
  def check
    @busy_array = User.joins(:event).where(event: { ... }).pluck(:id) #-> return user ids where event.x = y
    respond_to do |format|
      format.js     #-> invokes app/views/events/check.js.erb
      format.html   #-> invoked when HTML request sent
    end
  end
end

#app/views/events/check.js.erb
<% @busy_array.each do |id| %>
   $("ol#unavailable-list").append("<%=j id %>")
<% end %>

I don't know how to send busy_array to be rendered in events\new.html.erb

The variable will be available in new if it's an @instance var:

#app/views/events/new.html.erb
<%= @busy_array %>

The view is part of the instance of your EventsController class, but outside the scope of the check method. When you send a request to Rails, it uses an instance of the Controller to compile a set of HTML to return to your browser.

For example, you could sum up the EventsController flow as such:

Request > Routing > EventsController.new(request).action > Returned HTML

If you set EventsController.new(request) manually, you'd have the following:

@event = EventsController.new request

@event.check    #-> "busy_array" locally scoped to this function
@event.response #-> outputs view code.... @busy_array needs to be instance var

You'll understand better if you read up about MVC:

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

thank you, does it matter if it's not a post request and is just a get request?
Not at all, but you have to define it as such. Ajax defaults to POST
0

For a real AJAX request in Ruby on Rails, you need to send response from check action in JS format.

events_controller.rb

def check
    checkList = params[:checkList]
    selected_date = params[:selected_date]
    length = params[:length]

    @events = Event.where("checklist = ? and date = ?, checkList, selected_date).limit(length.to_i)
    ...

    respond_to do |format|
        format.js
    end
end

Now, in your view, instead a check.html.erb, you will have check.js.erb. In this Javascript file, you can access to your @ variables and render partials or wherever.

check.js.erb

$("#unavailable-list").append('<%= escape_javascript( render :partial => "events/event", :collection => @events ) %>');

_event.html.erb

<li><%= event.name %></li>

I change busy_array for events array because I don't know what's exactly busy_array but you can change it.

This is the flow for an AJAX request.

4 Comments

ok, so if I did $("#unavailable-list").append('<%= escape_javascript( render @busy_array ) %>'); , it would make each entry an <li> element?
If @busy_array isn't an ActiveRecordRelation you have to specify the partial you want to render like render :partial => "events/event", :collection => @busy_array. Then, in your _event.html.erb you can add your <li> element.
Do you mind showing me within your answer? Sorry, I do not fully understand what you mean. How do I know if it's an Active Record Relation? I created it within my controller
ok thanks, my busy_array holds the users in the database, so if I had (instead of _event.html.erb) a _busy.html.erb, I could render :partial => "events/busy", :collection => @busy_array , and in _busy.html.erb I could write <% (&)busy_array.each do |id| %> <li><%= user.id %><li> <%end%> ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.