AJAX call not rendering my partial rails 3 - ruby-on-rails

I am trying to get an Ajax call working in rails, not quite sure what im doing wrong
So in my index I have a form that calls an api then returns the result to the results path. so what i want to do is to get the results rendered on the index page
What i have so far is
Controller
def index
end
def results
results = contact_search(params[:search])
#results = results
end
Index
<div class="container">
<div class="row">
<div class="span6 offset3">
<h2>Search for a contact</h2>
<%= form_tag results_path, :method => "get", :remote => true do %>
<%= text_field_tag 'search', nil, :placeholder => "Enter Email Address here...." %>
<%= submit_tag 'Search' , :id => "submitForm" %>
<% end %>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="span6 offset3">
<div class="cResults">
</div>
</div>
</div>
</div>
Partial _contactResults.html.erb
<h1>The Results</h1>
<%= #results["contactInfo"]["familyName"] %><br>
<img src= <%= #results["photos"].first["url"] %> />
Index.js.erb
$('.cResults').html("<%= escape_javascript(render partial: 'contactResults') %>");
Am i missing anything?

Your javascript file should be named as the action that "computed" the results:
# in results.js.erb, not index.js.erb
$('.cResults').html("<%= escape_javascript(render partial: 'contactResults') %>");
If you need to execute Javascript for a controller's action, you can name the file as the action, with .js.erb instead of common .html.erb. This file will be executed when the controller receive a request for this action, interpreted as JS.

Related

How do I optimize my code so that I don't have to call the entire array every time in views from an API in my controller?

I'm making a sports app to learn Rails. I've figured out how to call the API and display it how I want, but right now, I'm putting the full array in my view every time I want to call any key.
For instance, I want to make a page that shows the starting line-ups for teams using the JSON from the API, and right now I have it displaying, but the code within the view itself is pretty big and ugly.
My view:
<%= stylesheet_link_tag 'lineups' %>
<div id="lineupcontainter">
<div id= "team1lineup">
<div id= "player1"><%= #schedule["data"][0]["lineup"]["data"][0]["player_name"] %>
<div id= "playerphotos"> <%= image_tag #schedule["data"][0]["lineup"]["data"][0]["player"]["data"]["image_path"] %> </div> </div>
<div id= "player1"><%= #schedule["data"][0]["lineup"]["data"][1]["player_name"] %>
<div id= "playerphotos"> <%= image_tag #schedule["data"][0]["lineup"]["data"][1]["player"]["data"]["image_path"] %> </div> </div>
<div id= "player1"><%= #schedule["data"][0]["lineup"]["data"][2]["player_name"] %>
<div id= "playerphotos"> <%= image_tag #schedule["data"][0]["lineup"]["data"][2]["player"]["data"]["image_path"] %> </div> </div>
<div id= "player1"><%= #schedule["data"][0]["lineup"]["data"][3]["player_name"] %>
<div id= "playerphotos"> <%= image_tag #schedule["data"][0]["lineup"]["data"][3]["player"]["data"]["image_path"] %> </div> </div>
<div id= "player1"><%= #schedule["data"][0]["lineup"]["data"][4]["player_name"] %>
<div id= "playerphotos"> <%= image_tag #schedule["data"][0]["lineup"]["data"][4]["player"]["data"]["image_path"] %> </div> </div>
<div id= "player1"><%= #schedule["data"][0]["lineup"]["data"][5]["player_name"] %>
<div id= "playerphotos"> <%= image_tag #schedule["data"][0]["lineup"]["data"][5]["player"]["data"]["image_path"] %> </div> </div>
<div id= "player1"><%= #schedule["data"][0]["lineup"]["data"][6]["player_name"] %>
<div id= "playerphotos"> <%= image_tag #schedule["data"][0]["lineup"]["data"][6]["player"]["data"]["image_path"] %> </div> </div>
<div id= "player1"><%= #schedule["data"][0]["lineup"]["data"][7]["player_name"] %>
<div id= "playerphotos"> <%= image_tag #schedule["data"][0]["lineup"]["data"][7]["player"]["data"]["image_path"] %> </div> </div>
<div id= "player1"><%= #schedule["data"][0]["lineup"]["data"][8]["player_name"] %>
<div id= "playerphotos"> <%= image_tag #schedule["data"][0]["lineup"]["data"][8]["player"]["data"]["image_path"] %> </div> </div>
</div>
My controller
def game1
#response = RestClient.get "https://soccer.sportmonks.com/api/v2.0/fixtures/between/2022-02-01/2022-02-04/62?api_token=____&include=lineup.player,"
{content_type: :json, accept: :json, "user_key": "____"}
#schedule = JSON.parse(#response)
render JSON: #schedule
end
What can I do to create something where I don't have to call the entire array every time I want to put something in views?
Something like this should work:
<div id="lineupcontainter">
<div id= "team1lineup">
<% #schedule["data"][0]["lineup"]["data"].each do |cur_schedule|%>
<div id= "player1">
<%= cur_schedule["player_name"] %>
<div id= "playerphotos">
<%= image_tag cur_schedule.dig("player", "data", "image_path") %>
</div>
</div>
<% end %>
</div>
Also, your controller has some redundant logic. You are parsing a JSON string and turning it into a ruby hash, then you take that hash and render it as a JSON string. You should be able to render the json directly.
If you want to reduce the lines of code in your template, you can iterate over the instance variable in the .erb file. This bit of code should work if you put it in your erb file:
<div id="lineupcontainter">
<div id="team1lineup">
<!-- iterating on team 1 -->
<%= #schedule["data"][0]["lineup"]["data"].map.with_index do |data, index| %>
<!-- index will increase by 1 each iteration, starts at 0 -->
<div id="player1"><%= data[index]["player_name"] %>
<div id="playerphotos"> <%= image_tag data[index]["player"]["data"]["image_path"] %></div>
</div>
<% end %>
</div>
</div>
I would recommend parsing that data in your controller before sending it to the template, something like this:
def game1
#response = RestClient.get "https://soccer.sportmonks.com/api/v2.0/fixtures/between/2022-02-01/2022-02-04/62?api_token=____&include=lineup.player,"
{content_type: :json, accept: :json, "user_key": "____"}
schedule = JSON.parse(#response)
# in the ERB, replace schedule["data"][0]["lineup"]["data"] with #lineup_data
#lineup_data = schedule["data"][0]["lineup"]["data"]
render JSON: #lineup_data
end
Another note: you do not need to call render json: #schedule in your controller. That will call .to_json on the instance variable and it's unnecessary when rendering data in an ERB template. The Rails MVC design allows the template to access instance variables defined in controllers. See section 2.2.8 Rendering JSON for documentation.
def game1
#response = RestClient.get "https://soccer.sportmonks.com/api/v2.0/fixtures/between/2022-02-01/2022-02-04/62?api_token=____&include=lineup.player,"
{content_type: :json, accept: :json, "user_key": "____"}
schedule = JSON.parse(#response)
#lineup_data = schedule["data"][0]["lineup"]["data"]
end

submit_tag not sending to the right controller and action in Rails

I created a form on my application that is suposed to delete some media on my app.
I have a Album entity that has some media on it. I created a partial called media_uploader so I can reuse it on other places. Im calling my partial from the albums/new view. Like this:
<%= render '/profiles/edit/sidebar', user: current_user %>
<article class="col-9 col-offset-1">
<h3 class="color-gray-medium">Album Info</h3>
<div class="row row-no-padding top-5">
<%= form_for #album do |f| %>
<div class="col-9">
<div class="form-group row" >
<div class="col-6">
<label for="">Name:</label>
<%= f.text_field :name %>
</div>
</div>
</div>
<div class="col-9">
<div class="form-group row" >
<div class="col-6">
<%= render 'shared/media_uploader', media_contents: #media_contents %>
</div>
</div>
</div>
shared/_media_uploader.html.erb
<%= link_to 'Delete', delete_media_path, method: :delete, id: 'delete-all', class: 'btn btn-danger', disabled: media_contents.empty? %>
<br><br>
<div class="row">
<div id="media-contents" class="col-12">
<% if media_contents.empty? %>
<h5 id="no-media">No Media Found</h5>
<% else %>
<% media_contents.each do |media| %>
<div class="col-4">
<div class="thumbnail">
<%= image_tag media.file_name_url(:thumb) %>
<div class="caption">
<p>
<%= check_box_tag 'media_contents[]', media.id %>
</p>
</div>
</div>
</div>
<% end %>
</div>
</div>
<% end %>
<% end %>
My routes are like this:
resources :media_contents, only: [:create]
delete 'delete_media', to: "media_contents#delete_media"
delete 'delete_all', to: 'media_contents#delete_all'
When I click on the delete button here:
<%= form_tag({controller: "media_contents", action: "delete_media"}, method: "delete") do %>
<%= submit_tag 'Delete', id: 'delete', class: 'btn btn-danger', disabled: media_contents.empty? %>
It gives a error:
No route matches [DELETE] "/albums"
I understand that this is caused because of the outside form_for: #album.
The question is: "How can I do this?" How can I, inside this #album form, call a method from another controller and make it works?
Looks like you routes of media_contents is limited to "create"
Adding :delete could solve the issue
resources :media_contents, only: [:create, :delete]
Also why add a custom routes for delete when DELETE action already exists for the controller?
I could be that your form_tag of media_contents is inside the form_tag of albums.
That could be one of the reasons it's calling "albums" controller
You can't use form inside another form, it is invalid html. But you can use 2 submit buttons and decide what to do inside the controller action, depending on commit parameter. You need to remove inner form_tag from the partial and change update action like:
if params[:commit] == "Delete"
# deletion logic or redirect to needed delete action goes here
else
# existing `update` goes here
end

Pagination not working only with a certain query

I am using Kaminari gem to paginate using ajax
i have three paginations on the same page
#all_questions = Question.where.not(id: current_user.question_ids).page(params[:unanswered]).per(1)
#wrong = Tracker.where("user_id = ? AND correct = ?", current_user, false).page(params[:wrong_answers]).per(1)
#answered = Tracker.where("user_id = ? AND answered = ?", current_user, true).page(params[:all_answered]).per(1)
while the last two of the above instance variables correctly work. The first one when i click the next button, while i see the ajax request happening in the rails console, it does not refresh the page.
in my view
<%= paginate #all_questions, :remote => true, :param_name => "unanswered" %>
<%= paginate #wrong, :remote => true, :param_name => "wrong_answers" %>
<%= paginate #answered, :remote => true, :param_name => "all_answered" %>
Anyone knows why?
html
<section role="tabpanel" aria-hidden="true" class="content" id="panel2-2">
<div class="row">
<div class="large-10 large-offset-1 columns">
<div class="panel questions-progress-panel">
<ul>
<div id="unanswered">
<%= render partial: "all_questions" %>
</div>
<div id="paginator4" class="text-center paginator">
<%= paginate #all_questions, :remote => true, :param_name => "unanswered" %>
</div>
</ul>
</div>
</div>
</div>
</section>
#all_questions partial
<% #all_questions.each do |q| %>
<li>
<div class="wrapper">
<div class="row">
<div class="large-8 medium-8 small-8 columns">
<p class="question-title"> <%= q.description %> </p>
</div>
<div class="large-4 medium-4 small-4 columns text-right">
<%= link_to "Go", category_question_path(q.category,q), class:"button round success" %>
</div>
</div>
</div>
</li>
<% end %>
Your corresponding js.erb could look like this:
$('#unanswered').html('<%= escape_javascript render(all_questions) %>');
$("#paginator4").html('<%= escape_javascript(paginate(#all_questions, :remote => true).to_s) %>');

Ruby on Rails - dynamic navigation with link_to in a div

I want to add navigation to a series of div, which are loaded dynamically.
For this I am using link to covering the div and passing it the attribute to the method.
The problem is that when I press on the div the attribute does not correspond.
I put the code.
With this code all it's ok, but i don't have the link in the div.
<%for i in inicio..final %>
<div class="col-md-3">
<div class="tarjeta_comercio">
<%= link_to 'mezcla/mostrar_institucion', {:controller => "mezcla", :action => "mostrar_institucion", :institucion_actual => #institucions[azar[i]].id} %>
<div class="foto">
<%= image_tag #institucions[azar[i]].logo.url(:original) %>
</div>
<div class="titulo">
<%= #institucions[azar[i]].nombre %>
</div>
<% end %>
But the problem is when i do a block with "link_to...do-div-end". If i do this the parameter don't run. I don't explain why this happen. This is the wrong code.
<%for i in inicio..final %>
<div class="col-md-3">
<div class="tarjeta_comercio">
<%= link_to 'mezcla/mostrar_institucion', {:controller => "mezcla", :action => "mostrar_institucion", :institucion_actual => #institucions[azar[i]].id} do %>
<div class="foto">
<%= image_tag #institucions[azar[i]].logo.url(:original) %>
</div>
<div class="titulo">
<%= #institucions[azar[i]].nombre %>
</div>
<% end %>
<% end %>
In :institucion_actual each time put 0 (when i pulsed over).
Thanks.

Writing a helper method for page headers

I am currently integrating twitter bootstrap.
My application layout currently includes my flash messages right above the yield:
<div class="container">
<%= render 'layouts/header' %>
<div class="content" role="main">
<%= render :partial => 'shared/flash', :object => flash %>
<%= yield %>
</div>
<%= render 'layouts/footer' %>
</div> <!--! end of #container -->
However, I am also using the bootstrap Page Headers in my individual views
<div class="page-header">
<h1>Sign In <small>through one of these services:</small></h1>
</div>
I would like my flash messages to be below these page headers when page headers are set. So I'm thinking the best way to do this is to create a helper method and edit my application layout to be something like:
<%= render 'layouts/header' %>
<div class="content" role="main">
<%= pageHeader %>
<%= render :partial => 'shared/flash', :object => flash %>
<%= yield %>
</div>
How would I go about writing the helper for this. Would the best way to just have instance variables for #page_header and #page_header_small in my controller? Or is there a better rails way to handle this situation?
You can user content_for combined with yield.
In your layout you can put this block with headline above flash message
<%= yield :page_header %>
<%= render :partial => 'shared/flash', :object => flash %>
<%= yield %>
and in your template for action
<% content_for :page_header do %>
<div class="page-header">
<h1>Sign In <small>through one of these services:</small></h1>
</div>
<% end %>
Check it out at Ruby Guides

Resources