I'm working on an application that makes some calls to the Twitter and Spotify APIs. After the user is authenticated with twitter, they are redirected to playlist.erb which is the callback url.
My problem is that the playlist.erb page takes a while to render because first we must make a call to fetch all tweets found on the users Twitter page, then try to find information about songs/artists, then use the Spotify API to search for a song that is closest to what information the user specified. Doing this for each tweet takes quite a while. For 10 tweets it sometimes takes between 5-10 seconds. The limit is 50 tweets in total.
The current playlist.erb page after it is fully loaded looks like this.
My question is, is there a way that I can render the page first, then get the partials for each individial tweet to render one at a time,
adding a new row for each tweet as it loads?
I've read that I should use something called AJAX, but I'm not sure how exactly to implement that here.
Also I'm aware that my view could use fixing in terms of CSS refactoring and not using the deprecated <center></center> HTML tags. And I should probably do a whole refactor of the system using proper MVC.
In the playlist.erb, a call to the Twitter API is made through the TweetsController to find all tweets from a page. the _tweet.erb partial is then rendered to this view for each tweet when new_tweet(tweet.text) is called. This method makes a call to the Spotify API to find details about the song mentioned in the tweet.
new_tweet is a method in a helper called playlist_helper.rb.
load_tweets is a method in a controller called tweets_controller.rb.
I realise that this is quite a bit of logic to put in a view, which is why the page takes quite long to load I guess.
playlist.erb
<% loaded_tweets = TweetsController.load_tweets(current_user) %>
<% if loaded_tweets.any? %>
<table class='tweet_view'>
<thead>
<tr class='tweet_row'>
<th class="fixed_cover"><div class='tableheader'><h6 style='color:white'>Cover</h6></div></th>
<th class="fixed_spotify"><div class='tableheader'><h6 style='color:white'>Spotify</h6></div></th>
<th class="fixed_title"><div class='tableheader'><h6 style='color:white'>Track title</h6></div></th>
<th class="fixed_artist"><div class='tableheader'><h6 style='color:white'>Artist</h6></div></th>
<th class="fluid"><div class='tableheader'><h6 style='color:white'>Album</h6></div></th>
</tr>
</thead>
<tbody>
<% loaded_tweets.reverse_each.each do |tweet| %>
<%=new_tweet(tweet.text)%>
<% end %>
</tbody>
</table>
<% else %>
<center>
<p><h8><b>No tweets found!</b></h8></p>
</center>
<% end %>
The _tweet.erb partial just adds a new row for each song.
_tweet.erb
<tr class='tweet_row'>
<td class='tweet_column'>
<div class='tablerow#cover'>
<%= image_tag(#cover,:class => 'album_cover')%>
</div>
</td>
<td class='tweet_column'>
<div class='tablerow#spotify'>
<h5><%= link_to image_tag('spotify', :class => 'spotify_image'), 'https://open.spotify.com/track/'+#spotify %></h5>
</div>
</td>
<td class='tweet_column'>
<div class='tablerow'>
<h5><%=#track_name%></h5>
</div>
</td>
<td class='tweet_column'>
<div class='tablerow'>
<h5><%=#artist%></h5>
</div>
</td>
<td class='tweet_column'>
<div class='tablerow'>
<h5><%=#album%></h5>
</div>
</td>
</tr>
Change playlist.erb to playlist.html.erb
<div id="tweets">
<%= render 'tweet') %>
</div>
....
....
<script>
$( document ).ready(function() {
// call the controller function here
});
</script>
In controller methode add
....
....
respond_to do |format|
format.js
end
create one more file in views folder like action_name.js.erb and add
$('#tweets').html('<%= j(render "tweet") %>')
Related
I have a wired problem when developing rails. The order of elements in container is
<div class="container">
<%= yield %>
<%= render 'layouts/footer' %>
<%= debug(params) if Rails.env.development? %>
</div>
For most of the pages, it works well. But it goes wrong when it renders following page
<% provide(:title, 'All Apps') %>
<h1>All Apps</h1>
<table class="apps table">
<thead>
<tr>
<th>App Name</th>
<th>Status</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<%= render #apps %>
</tbody>
</talbe>
The order of elements in container becomes
<div class="container">
<h1>All Apps</h1>
<footer class="footer">...</footer>
<pre class="debug_dump">...</pre>
<table class="app table">...</table>
</div>
What confuses me is that only this page goes wrong. I am using Rails 4.0.5.
What is most probably happening is your browser HTML parser is trying to fix things, by putting elements "floating" in a table (without being in a tr>td) before the table. You probably have an unclosed tag.
(which is why it's vering important in cases like these to check the generated html and compare it to the browser's DOM panel - it can be very different !)
I'm using a Bootstrap modal. Right now the table listed in the modal gets loaded when the whole html page loads. I would like the data for the table loaded when the modal launches.
How can I load the data in the modal when the modal is launched?
This is the first part of my modal - it contains several Bootstrap tabs.
<div class="modal-body">
<div class="tabbable">
<ul class="nav-tabs">
<li class="active">Details</li>
<li>Materials</li>
<li>Labor</li>
<li>Tasks</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab1_<%= workorder.id %>">
<table border="1" cellpadding="5">
<tr>
<th>Description</th>
<td><%= workorder.description %></td>
</tr>
<tr>
<th>Client</th>
<td><%= workorder.client.client_name %></td>
</tr>
<tr>
<th>Type</th>
<td><%= workorder.type.typecode %></td>
</tr>
<tr>
<th>Priority</th>
<td><%= workorder.wopriority.prioritycode %></td>
</tr>
<tr>
<th>Scheduled Finish</th>
<% if workorder.scheduled_finish != nil %>
<td>Scheduled Finish = <%= workorder.scheduled_finish %></td>
<% else %>
<td></td>
<% end %>
</tr>
</table>
</div>
...
Thanks for the help!
Use Ajax (set your links to link_to with remote => true) and render a partial. Then set the innerHTML of tab-pane to the partial content returned via Ajax. Of course you'll need to add logic in your controller to parse out only the data for each tab.
Might help to read up on:
http://guides.rubyonrails.org/ajax_on_rails.html
You have two choices:
Using AJAX to populate the table, when your mondal is launched
Mondal with an iframe
If you're just simply displaying information, then an iframe is a quick and dirty solution.
I Have a View Folder
FrontEnd
JobDetails.ascx (View)
Another View Folder
Job
Apply.ascx (view)
I have a Apply (a href) in jobdetails which have a show and hide div mechanism for apply (Rendering Apply.ascx in JobDetails
<div id="div1" style="visibility:hidden">
<% Html.RenderPartial("../../Views/Jobs/Create"); %>
</div>
my create View in job
<% using (Html.BeginForm("Create", "Jobs", FormMethod.Post, new { enctype = "multipart/form-data" }))
{%>
<%: Html.ValidationSummary(true) %>
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td></td>
</tr>
<tr>
<td>
<% } %>
the question is that how would i go back in the JobDetails View if some Error occurs in my create form to display the errors there . I am at lost here , hope that the question is clear enough.
Probably the simplest way to handle this is to do the post of the apply via AJAX and simply render the apply form with the errors in place by replacing the existing HTML with that returned when the apply fails. If javascript is turned off, then it will render just the failed application but that seems like a reasonable trade-off to me.
I've a simple page with link_to_remote Rails Ajax function and HTML table.
I'd like to change row of the table when click that link.
This is my html.
<table border="1">
<tr>
<td><div id="ajax_result_1">1</div></td>
<div id="ajax_result_2"><td>2</td></div>
</tr>
<div id="ajax_result_3">
<tr>
<td>3</td>
<td>4</td>
</tr>
</div>
</table>
And this is my code.
<%= link_to_remote 'Change', :update => "ajax_result_1", :url => "change_path" %>
change action just render simple text.
When I use ajax_result_1 for :update, it worked okay.
But, not for ajax_result_2 and ajax_result_3.
Is there a way to solve this? I want to replace row of the table.
<div id="ajax_result_2"><td>2</td></div>
this should be
<td><div id="ajax_result_2">2</div></td>
and
<div id="ajax_result_3">
<tr>
<td>3</td>
<td>4</td>
</tr>
</div>
should be
<tr id="ajax_result_3">
<td>3</td>
<td>4</td>
</tr>
you cann't use <div> tag in table directly if you want to use <div> you have to use it in the <td> only.
I have a user control: VendorDDL.ascx, with the following code:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<List<MeetingCalendar.Models.Vendor>>" %>
<table>
<tr>
<th></th>
<th>
VendorId
</th>
<th>
VendorName
</th>
</tr>
<% foreach (var item in Model) { %>
<tr>
<td></td>
<td>
<%= Html.Encode(item.VendorId) %>
</td>
<td>
<%= Html.Encode(item.VendorName) %>
</td>
</tr>
<% } %>
</table>
My view: Create.aspx, has the following code snippet:
<p>
<label for="VendorNameSearch">Vendor Name:</label>
<input type="text" name="VendorNameSearch" id="VendorNameSearch" style="width:100px" />
<input type="submit" value="search" />
</p>
<% Html.RenderPartial("VendorDDL", MeetingCalendar.Controllers.HomeController.VendorsToSelect); %>
And everything works fine when I load up the Create view. The VendorDDL control is populated with the default values that are found in the VendorsToSelect. My controller has a List<Vendor> VendorsToSelect, which is getting updated properly.
Here is the problem: when the user clicks the SEARCH button, this fires off code in the Controller: return PartialView("VendorDDL", VendorsToSelect); I can see that VendorsToSelect is getting populated correctly based upon the user search.
I can step through the code, line-by-line, and see that immediately after return PartialView("VendorDDL", VendorsToSelect);, the debugger goes directly to the VendorDDL.ascx, and I can see that the Model is properly populated with the new VendorsToSelect, and the item.VendorId and item.VendorName are showing the correct values. But when debugging is done, and the Create view is shown, the VendorDDL control is not showing the new data.
Any suggestions?
I think that the output of your controller is discarded because the view (Create) has the same Html.RenderPartial("VendorDDL", MeetingCalendar.Controllers.HomeController.VendorsToSelect) as during initial load.
If I understand your problem correctly (and admittedly, without looking at the controller I may not) - you need to pass the model dynamically. The simplest (but not the most efficient) way would be to have jquery call $.load("/Home/VendorDDL") that would populate with the whole model; and then on submit hijax the form and pass form data to the same controller action.