chris
chris

Reputation: 371

Rails button_to or link_to image

Noob with some help needed. I am creating a chore chart for my children which should look like a online version of:

http://learningandeducationtoys.guidestobuy.com/i-can-do-it-reward-chart

Chores listed down the Y-axis and Days (Sun, Mon... ) on top X-axis. Boxes for kids to click and receive stars for completed chores.

The chores/index.html.erb table is ugly code (sorry):

Listing chores

  <table>
    <th><%= "" %></th>
    <th><%= "SUN" %></th>
    <th><%= "MON" %></th>
    <th><%= "TUES" %></th>
    <th><%= "WED" %></th>
    <th><%= "THURS" %></th>
    <th><%= "FRI" %></th>
    <th><%= "SAT" %></th>
    <% @chores.each do |chore| %>
    <tr class="<%= cycle('list-line-odd', 'list-line-even') %>">

    <%     ##TODO.. Fix to be sure to link "post" action to "show" child. %>
    <td>
      <%= image_tag(chore.image_url, :class => 'list-image') %>
      <dt><%=h chore.title %></dt>
    </td>

    <td class="button"><%= button_to "Add to Wallet", wallets_path(:chore_id => chore, :child_id => session[:child_id]),
    :remote => true %></td>
    <td class="button"><%= button_to "Add to Wallet", wallets_path(:chore_id => chore, :child_id => session[:child_id]),
    :remote => true %></td>
    <td class="button"><%= button_to "Add to Wallet", wallets_path(:chore_id => chore, :child_id => session[:child_id]),
    :remote => true %></td>
    <td class="button"><%= button_to "Add to Wallet", wallets_path(:chore_id => chore, :child_id => session[:child_id]),
    :remote => true %></td>
    <td class="button"><%= button_to "Add to Wallet", wallets_path(:chore_id => chore, :child_id => session[:child_id]),
    :remote => true %></td>
    <td class="button"><%= button_to "Add to Wallet", wallets_path(:chore_id => chore, :child_id => session[:child_id]),
    :remote => true %></td>
    <td class="button"><%= button_to "Add to Wallet", wallets_path(:chore_id => chore, :child_id => session[:child_id]),
    :remote => true %></td>


  </tr>
  <% end %>
</table>
</div>

The above creates "Add to Wallet" buttons for each chore for each day. Wallets is a join table between Children and Chores Tables. Two questions:

  1. How do i switch the buttons to boxes in the table which, when clicked, turn to the stars images (as per the example)?
  2. How do i refactor the code in the table so i don't violate the DRY rule?

Upvotes: 0

Views: 1008

Answers (1)

tadman
tadman

Reputation: 211590

There's sort of two questions in one here which makes it awkward to answer. For the DRY part you should recognize that you're copy-pasting the same statement many times over and this is bad form. Generally that sort of thing is better expressed as some kind of loop with a single instance of the statement.

An example would be rolling up your days into a constant stored somewhere, then using that:

<% DAYS.each do |day| %>
<th><%= day_name %></th>
<% end %>

DAYS could be defined somewhere convenient, like in a model associated with this, or something of the sort. It may require a prefix like MyModel::DAYS if this is the case, but will work the same.

It's really not clear why you're using the pattern <%= "X" %> which has the effect of returning the same string every time when X would do just as well.

You can also iterate over the seven other td elements with the same principle:

<% DAYS.each do |day| %>
<td class="button"><%= button_to "Add to Wallet", wallets_path(:chore_id => chore, :child_id => session[:child_id]),
:remote => true %></td>
<% end %>

Even though the day variable isn't used, the driving factor here is, apparently, the number of days, so it makes sense. If you had a five day week, those columns would shrink accordingly.

As for the second part of your question, what you're looking for would be best expressed as a jQuery onclick handler for those table cells. Using unobtrusive JavaScript techniques, you can define an action on an entire class of DOM elements quite easily:

$('td.button').live('click', function () { ... });

You'd fill in the ... part with the AJAX call that fetches and updates the cell. There's no need for an actual button inside the cell at this point, just some CSS to make the cell the right size and color. For style reasons this could just as easily be applied to an element inside the cells by adjusting the selector accordingly.

Upvotes: 2

Related Questions