Static HTML, want to use ruby on rails - javascript

I have an app that hosts a static HTML webpage with text and some images. I want to use ruby on rails to learn about it more.
I have a simple ror app. I went to app/views/home.html.erb, and pasted the HTML I have there. This is not the best approach.
Is there a better approach to port this Static HTML to ror?
Where do javascript files go in ror?

You should checkout high_voltage, which is a gem for static pages.

1) You have helpers in RoR ERB to help you with HTML, especially if you connect to a DB, for example from their help:
<table>
<tr>
<th>Title</th>
<th>Summary</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #books.each do |book| %>
<tr>
<td><%= book.title %></td>
<td><%= book.content %></td>
<td><%= link_to "Show", book %></td>
<td><%= link_to "Edit", edit_book_path(book) %></td>
<td><%= link_to "Remove", book, method: :delete, data: { confirm: "Are you sure?" } %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to "New book", new_book_path %>
Everything between <%= .... %> are RoR helpers, so it's really up to your application if RoR will help you with your static HTML or not (maybe since you say it's static, i.e. not dynamic at all, the best approach would just be to leave it as is.
2) Javascript files are placed under app/assets, and you should definitely read about the asset pipeline

Related

Rails 4: dynamically added checkboxes are not submitting

I started to learn Rails and try to apply AJAX with some records that are added dynamically in a listing. Then I want to delete multiple records that are selected via checkboxes directly in the listing.
It works fine but not when I create a new Record and want to delete it without refreshing the page. The header's response is : "ActiveRecord::RecordNotFound in AccountsController#destroym". It acts as if I click the button without checking my checkboxes.
Thanks for your help :)
accounts_controller.rb
def destroym
Account.destroy(params[:delete])
respond_to do |format|
format.html {redirect_to accounts_path}
format.js #render accounts/destroym.js.erb
end
end
_row.html.erb
<% #data = Account.find(id) %>
<tr id='tr<%= #data.id %>'>
<td><%= #data.id %></td>
<td><%= #data.login %></td>
<td><%= check_box_tag 'delete[]', #data.id %></td>
</tr>
index.html.erb
<table class="table table-striped table-hover " id="accountsListing">
<%= form_tag destroym_accounts_path, method: :DELETE, remote: true, id: "deleteForm" do %>
<thead>
<tr>
<th>#</th>
<th>Username</th>
<th>Password</th>
<th>Website</th>
<th>Date</th>
<th>Editer</th>
<th><%= submit_tag "delete" %>
<%= link_to "Delete", '', :onclick => "$('#deleteForm').submit()", id: "removePwd", class: "text-danger", remote: true, method: :DELETE %> </th>
</tr>
</thead>
<tbody>
<% #accounts.each do |account| %>
<%= render 'row', id: account.id %>
<% end %>
</tbody>
<% end %>
</table>
destroym.js.erb
$("#accountsListing input:checked").closest("tr").remove();
create.js.erb
$("#accountsListing tr:first").after("<%= escape_javascript (render 'row', id:#account.id) %>");
The problem in this case is that you're replacing your whole page's HTML... So, all the DOM events bound to your elements are also destroyed.
When you replace your html (the .js.erb file), Rails will provide some special attributes to your elements (Rails calls that "unobstrusive JavaScript", because there's no JS code directly in your elements).
The issue here, of course, is that the JS code that Rails uses (see my link) are only applied when the page launches.
You have several choices:
1) your destroy.js.erb can only remove the exact row you just deleted (instead of replacing all the rows).
2) you can call rails-ujs' code by yourself. This is a hack and should not seriously be considered.
3) you can reload the page "automatically" (you lose the benefit of AJaX).
4) you can write your own JS code to send the AJaX request.
My solution to handle checkboxes created dynamically. The on function is mandatory if you want to handle events on elements added dynamically.
JS code
$("#deleteBtn").on("click", function() {
var ids = [];
$('#accountsListing :checkbox:checked').each(function(){
ids.push($(this).val());
});
$.ajax({
url: '/accounts/destroym',
type: 'POST',
data: {
"_method":"DELETE",
"authenticity_token": window._token,
"delete[]": ids
},
});
});

How to asynchronously send JS variable to Rails

Simple HTML form in a view. I need the user selected value of the form to pass into the active record query when the user switches it. (Probably not params because then it won't be asynchronous?)
In the example below I need the business_id to be the value of the form. New to rails, so if you could provide some in page javascript, I'll deal with refactoring it to the resources later...
<select name="clients">
<option value="1">Tesla</option>
<option value="4">Chevy</option>
</select>
<table>
<% #clients.where(month_year:'2015-02',business_id:'NEED VALUE OF HTML FORM HERE').find_each do |client| %>
<tr>
<td><%= client.month_year %></td>
<td><%= client.business_id %></td>
<td><%= client.bill_charge %></td>
</tr>
<% end %>
</table>
To expound on other answers, here's a (perhaps) overly simplified mock up.
Client view
Here you need to call render that points to a partial. This partial will contain the table data (so it's resuable later). You also need to give your select statement a class that jquery can easily grab to do the async fetch of your client data.
# app/views/clients/index.html.erb
<%= select_tag "business", options_from_collection_for_select(Business.all, "id", "name"), class: "car-select" %>
<div class="clients-table">
<%= render "table_list" %>
</div>
Table Partial
With the table you just cut out of the index view, you'll need to paste into a partial
# app/views/clients/_table_list.html.erb
<table>
<thead>
<tr>
<th>Month year</th>
<th>Business</th>
<th>Bill charge</th>
</tr>
</thead>
<tbody>
<% #clients.each do |client| %>
<tr>
<td><%= client.month_year %></td>
<td><%= client.business.try(:name) %></td>
<td><%= client.bill_charge %></td>
</tr>
<% end %>
</tbody>
</table>
AJAX script
This need to watch for changes to the select and submit a request for client data
# app/assets/javascripts/clients.coffee
ready = ->
$('.car-select').on 'change', ->
bid = $(this).val()
$.ajax
url: '/businesses/' + bid
dataType: 'script'
return
return
$(document).ready(ready)
$(document).on('page:load', ready)
# this is turbolinks-friendly
Businesses Controller processes request
In your ajax request you are calling to a URL like, "http://yourapp.com/businesses/23", which really hits the show action of your businesses controller. You want to do it this way because it's completely RESTful and you don't have to change any routes. But you will need to edit the action to provide an instance variable for clients.
# app/controllers/businesses_controller.rb
def show
#business = Business.find(params[:id])
#clients = #business.clients (this assumes that you already have a proper has_many / belongs_to relationship between business and client)
respond_to do |format|
format.html
format.js
end
end
UJS View
The last piece of the puzzle is the UJS view. This is javascript that is only called when the js request type is sent to a particular controller action. In this case, the show action of the businesses controller. This is going to take the newly created #clients and replace the existing table with the partial and new data.
#app/views/businesses/show.js.erb
$(".clients-table").html("<%= escape_javascript(render( '/clients/table_list', client: #clients)) %>");
If you still have questions, or want to do more complicated things, you should go research a little on UJS templates and callbacks.
put your result table into a partial.
fire a ajax request on the on change event of the select
render the table based on the value of the select which you pass as request variable (`#clients')

Split Index Results Over Several Pages

I'd like to generate a list of all the characters in my Character table, but split them so that the page isn't extremely long. I'd like for the default to be 15 characters, then you'll be presented with a "Next" button, to view the next 15 results. Is this possible to do in rails?
Here is a copy of my index.html.erb (I've taken out all the .CSS information):
<table class="table">
<tr>
<th><strong>Name</strong></th>
<th><strong>Race</strong></th>
<th><strong>Class</strong></th>
<th><strong>Alignment</strong></th>
</tr>
<% #characters.each do |character| %>
<% if character.user_id == current_user.id %>
<tr onclick="location.href= '<%= character_path(id: "#{character.id}") %>'">
<td><%= character.name%></td>
<td><%= character.race %></td>
<td><%= character.class_ %></td>
<td><%= character.alignment %></td>
</tr>
<% else %>
<tr>
<td><%= character.name%></td>
<td><%= character.race %></td>
<td><%= character.class_ %></td>
<td><%= character.alignment %></td>
</tr>
<% end %>
<% end %>
</table>
If need be, I am open to using JavaScript or Jquery to get this done.
What you're describing is called pagination. There are many ways to do it, but the kaminari gem is the most popular. Here's a guide to using it in your Rails app: http://railscasts.com/episodes/254-pagination-with-kaminari
In short, your controller should be responsible for setting #characters to only the particular page you want to return (with Kaminari, that's #characters = Character.page(params[:page].to_i)). Then, provide links on your view to go to the previous and next pages (making sure to handle the first and last page properly).

Call javascript function inside erb tag

I'm trying to add rows to a table as shown in the below code snippet from my view.html.erb file:
<% #res.each do |r| %>
<tr>
<td class="alt" id="resName"><%= r.name %></td>
<td class="norm" id="startDate"><%= r.startDate %></td>
<td class="norm" id="endDate" ><%= r.endDate %></td>
</tr>
<% end %>
The problem that I am encountering is that the startDate and endDate values are being displayed with the format: Thu May 01 2014 08:00:00 GMT-0400 (EDT) where I want to display them with the format 05/01/2014.
I have a javascript function, formatDate, which will make the formatting change, but I can't figure out a way to call it from within the erb tags.
I've tried a few things, but can't seem to get it to work. Is it not possible, or am I just doing something wrong? Can anyone offer any help/advice? Thank you in advance!
<td><%= r.startDate.strftime("%-m/%-d/%Y)" %></td>
I prefer very light views; I'd use a decorator:
<td><%= r.start_date_formatter %></td>
Or at least a helper:
<td><%= view_date(r.start_date) %></td>
(Unrelated markup elided for clarity; consider doing the same in future questions. If it's not directly related to the question, it's just noise :)

Ruby on Rails: error when using unobtrusive JavaScript to update partial

I am using Rails 3.2.13, and I'm trying to update a 'summary' partial after creating a 'child' item.
I have a template and template tasks, and what I am trying to do is update the partial on the 'show' view, which is a summary that indicates how many tasks are allocated to the template. I am doing this in the create.js.erb of the template task.
Here are the contents of _template-summary.html.erb:
<div id="template-summary-details">
<table class="table table-striped">
<tbody>
<tr>
<td><span class="fa fa-th-list"></span> No. of tasks</td>
<td><%= #template.templatetasks.count %></td>
</tr>
<tr>
<td><span class="fa fa-clock-o"></span> Total task days</td>
<td>
<%= #template.templatetasks.sum(:days) %>
</td>
</tr>
<tr>
<td><span class="fa fa-check-square-o"></span> No. of checklists</td>
<td>
<%= #template.templatetasks.count(:checklist_id) %>
</td>
</tr>
</tbody>
</table>
</div>
And here are the contents of create.js.erb:
<% #template = Template.where("id = ?", #templatetask.template_id?) %>
$("#template-summary-details").replaceWith("<%= escape_javascript(render partial: "templates/template-summary", locals: {template: #template}) %>");
<% if #templatetask.parent_id? %>
$('#templatetasks'+<%= #templatetask.parent_id %>).prepend('<%= j render(#templatetask) %>');
<% else %>
$('#templatetasks').prepend('<%= j render(#templatetask) %>');
<% end %>
The problem is that I am getting the following error:
undefined method `where' for ActionView::Template:Class
I have also tried using find but haven't gotten that to work either.
How else would I pass the #template to the partial during the creation of a template task?
You first problem is that you have a name clash between the Rails class ActionView::Template and your Template model class. You can work around that by referring to your model class as ::Template (a top-level Ruby class). e.g.
<% #template = ::Template.where("id = ?", #templatetask.template_id).first %>
But that is just a round about way of doing a primary key lookup which is simpler with find:
<% #template = ::Template.find(#templatetask.template_id) %>
Even easier, if you have already set up a belongs_to association from TemplateTask to Template you could just refer to the related object directly:
<% #template = #templatetask.template %>
That would probably get you a bit further but if you want to make your partials more reusable its might be better to avoid having them refer to instance variables (e.g. #template). Instead the partial should refer to a local template variable that you pass into the render method via the locals hash (which you are already doing).

Categories