Question

I'm trying to show all toys that a client uses.

The problem is that is showing all toys without the state selected.

When I select a state the result should be depending of the status selected.

Tables:

|toys|
   |id| |name|     |client_id| |status|
     1   facebook       1         0
     2   whatsup        1         1
     3   android        2         0
     4   google         2         1
     3   iphone         3         0

|clients|
   |id| |name|
     1    ZUCK
     2    GATES
     3    JOBS

Here is controller:

def index
  if params[:status]=="3"
    @data= Toy.find(:all,:conditions=>['status IN (0,1,2)' ])
    @client_groups = Toy.find(:all, :include => :client, :conditions=>['status IN (0,1,2)' ],:group=>['client_id'] )
  else
    @data= Toy.find(:all,:conditions=>['status= ?',params[:status] ])
    @client_groups = Toy.find(:all, :include => :client,:conditions=>['status = ?',params[:status] ],:group =>['client_id'] )
  end
end

Here the models:

class Client < ActiveRecord::Base
   has_many :toys
end

class Toy < ActiveRecord::Base
   belongs_to :client     
end

Here is the view:

<% form_tag :controller=>"toy",:action=>"index" do %>
  Status:
  <%= select_tag "status", "<option value=\"3\">All</option>"+ options_for_select([ ["Active",0],["Inactive",1]],params[:status].to_i) %>
  <%= submit_tag "SEARCH", :name => nil %>
<% end %>
<%= render :partial=>"table" %>

Here is the partial view:

<table border="1">
<% @client_groups = @data.group_by{|toy| toy.client.name} %>
<% @client_groups.each do |client_name, toys| %>
  <tr><td>Client Name</td></tr>
  <tr><td><%= client_name %></td></tr>
  <tr>
     <td></td>
     <td>Name Toy</td>
     <td>State Toy</td>
  <tr>
  <% toys.each do |toy| %>
  <tr>  
     <td></td>
     <td><%= toy.name  %></td>
     <td><%= toy.status %></td>
  </tr> 
  <% end %>
<% end %>
</table>

The partial view is showing this:

enter image description here

I'm trying to show the information group by client like this:

enter image description here

I tried

<% @client_groups = @data.group_by{|toy| toy.client.name} %>
<% @client_groups.each do |client_name, toys| %>
  <tr><td>Client ID</td><td>Client Name</td></tr>
  <tr><td><%= client_name.id %></td></tr>
  <tr><td><%= client_name.name %></td></tr>
  <tr>
     <td></td>
     <td>Name Toy</td>
     <td>State Toy</td>
  <tr>

enter image description here

Please somebody can help me with this?

All kind of help will be accepted.

Was it helpful?

Solution

You can do this 2 ways. This simpler approach is to group your rows before you present them using group_by (this assumes Ruby 1.8.7 or later):

<% @client_groups = @data.group_by{|toy| toy.client } %>
<% @client_groups.each do |client, toys| %>
  <tr><td>Client Id</td><td>Client Name</td></tr>
  <tr><td><%= client.id %></td><td><%= client.name %></td></tr>
  <tr>
    <td></td>
    <td>Name Toy</td>
    <td>State Toy</td>
  <tr>
  <% toys.each do |toy| %>
    <tr>  
      <td></td>
      <td><%= toy.name  %></td>
      <td><%= toy.status %></td>
    </tr> 
  <% end %>
<% end %>

The other approach would be to group using SQL/ActiveRecord, which will actually be more efficient. I don't recall the exact format used in Rails 2.x, but it should be something like this:

@client_groups = Toy.find(:all, :include => :client, 
                                   :conditions=>['status IN (0,1,2)' ], 
                                   :group => 'client_id' )

And then use the already grouped @client_groups collection as above.

Note that I used :include to eager load the client association (to avoid an N+1 situation where each toy triggers an additional query to the server to find the client) - this should be done regardless of the grouping strategy. You can also refactor your controller code to keep it DRY:

status_condition = params[:status]=="3" ? 
  ['status IN (0,1,2)'] : 
  ['status= ?',params[:status] ]
@data= Toy.find(:all, :conditions=> status_condition, 
                         :include => :client)            # add :group if grouping in the query
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top