2010-09-06 7 views
1

Schéma:RoR: Liste des sous-enregistrements

  • persons (id, name, birthyear, gender)

  • pets (id, person_id, name, leg_count)

  • plants (id, person_id, kind, qty)

Je voudrais faire une lecture seulement un rapport sur ces choses groupé par des personnes. La liste des personnes est faite (sans les enregistrements associés). Je voudrais avoir des "sous-tables" par personne. Quelque chose comme:

Persons 
+----+------+-----------+--------+ 
| id | name | birthyear | gender | 
+----+------+-----------+--------+ 
| 1 | Joe | 1980  | M  | 
+----+------+-----------+--------+ 
| Pets       | 
| +----+------+-----------+  | 
| | id | name | Leg count |  | 
| +----+------+-----------+  | 
| | 1 | Rex |   4 |  | 
| +----+------+-----------+  | 
| | 2 | Ka |   0 |  | 
| +----+------+-----------+  | 
| Plants       | 
| +----+------------+-----+  | 
| | id | kind  | qty |  | 
| +----+------------+-----+  | 
| | 1 | lemon tree | 2 |  | 
| +----+------------+-----+  | 
+----+------+-----------+--------+ 
| 2 | Jane | 1982  | F  | 
+----+------+-----------+--------+ 
| Pets       | 
| +----+------+-----------+  | 
| | id | name | Leg count |  | 
| +----+------+-----------+  | 
| | 3 | Sue |   6 |  | 
| +----+------+-----------+  | 
| Plants       | 
| +----+------------+-----+  | 
| | id | kind  | qty |  | 
| +----+------------+-----+  | 
| | 2 | Oak tree | 1 |  | 
| +----+------------+-----+  | 
+----+------+-----------+--------+ 

Pouvez-vous s'il vous plaît m'aider avec quelques conseils où et comment accrocher à la structure? (JRuby (1.5.0), Ruby on Rails (2.3.4), ActiveRecord (2.3.4))

Ce qui est fait

Persons 
+----+------+-----------+--------+ 
| id | name | birthyear | gender | 
+----+------+-----------+--------+ 
| 1 | Joe | 1980  | M  | 
+----+------+-----------+--------+ 
| 2 | Jane | 1982  | F  | 
+----+------+-----------+--------+ 

Il est fait en utilisant:

class PersonsReportController < PersonsController 
    layout 'simpreport' 
    active_scaffold :person do |config| 
    c.columns = [:name, :birthyear, :gender, :pets, :plants ] 
    c.label = "Report of people and other living creatures" 
    [:pets, :plants].each do |col| 
     columns[col].clear_link 
    end 
    c.list.columns.exclude :pets, :plants 
    c.actions.exclude :show 
    end 
    # ... 
end 

Et j'ai également personnalisé _list_header.rhtml, _list_column_headings.rhtml, et _list_actions.rhtml un peu afin de tuer toute interactivité (comme les commandes et ainsi de suite).

+1

Est-ce que la solution doivent utiliser le code que vous avez déjà écrit? – Mischa

Répondre

5

Je ne comprends pas le code que vous avez écrit dans votre contrôleur, ni pourquoi il hérite de votre PersonsController. Peut-être pouvez-vous expliquer un peu plus ce que vous essayez d'accomplir là-bas?

Cela étant dit, je résoudre votre problème comme celui-ci:

Modèles:

person.rb:

class Person < ActiveRecord::Base 
    has_many :pets 
    has_many :plants 

    def has_pets? 
    self.pets.size > 0 
    end 

    def has_plants? 
    self.plants.size > 0 
    end 

    def has_pets_or_plants? 
    self.has_pets? || self.has_plants? 
    end 
end 

pet.rb:

class Pet < ActiveRecord::Base 
    belongs_to :person 
end 

plant.rb:

class Plant < ActiveRecord::Base 
    belongs_to :person 
end 

Controller:

reports_controller.rb:

class ReportsController < ApplicationController 
    def index 
    @persons = Person.find(:all) 
    end 
end 

Vue:

rapports/index.html.erb:

Persons 
<table border="1"> 
    <tr> 
    <td>id</td> 
    <td>name</td> 
    <td>birthyear</td> 
    <td>gender</td> 
    </tr> 
<% @persons.each do |person| -%> 
    <tr> 
    <td><%= person.id %></td> 
    <td><%= person.name %></td> 
    <td><%= person.birthyear %></td> 
    <td><%= person.gender %></td> 
    </tr> 
<% if person.has_pets_or_plants? -%> 
    <tr> 
    <td colspan="4"> 
    <% if person.has_pets? -%> 
     Pets 
     <table border="1"> 
     <tr> 
      <td>id</td> 
      <td>name</td> 
      <td>leg count</td> 
     </tr> 
     <% person.pets.each do |pet| -%> 
     <tr> 
      <td><%= pet.id %></td> 
      <td><%= pet.name %></td> 
      <td><%= pet.leg_count %></td> 
     </tr> 
     <% end -%> 
     </table> 
    <% end -%> 
    <% if person.has_plants? -%> 
     Plants 
     <table border="1"> 
     <tr> 
      <td>id</td> 
      <td>kind</td> 
      <td>qty</td> 
     </tr> 
     <% person.plants.each do |plant| -%> 
     <tr> 
      <td><%= plant.id %></td> 
      <td><%= plant.kind %></td> 
      <td><%= plant.qty %></td> 
     </tr> 
     <% end -%> 
     </table> 
    <% end -%> 
    </td> 
    </tr> 
<% end -%> 
<% end -%> 
</table> 
+0

Cela résout le problème, mais il contourne l'échafaudage actif. S'il n'y aura pas une solution élégante basée sur l'échafaudage actif, vous obtiendrez la prime. :-) Merci! – Notinlist

+0

"pourquoi il hérite de votre PersonsController" - Il semblait une bonne idée pour le programmeur précédent. – Notinlist

+0

Remarque mineure: Vous avez manqué d'échapper des chaînes lors de la sortie. HTML arbitraire et javascript peuvent être injectés. :-) – Notinlist

2

Voici une solution qui fonctionne dans ActiveScaffold:

app/controllers/people_controller.rb

class PeopleController < ApplicationController 
    active_scaffold :person do |config| 
    config.label = "Report of people and other living creatures" 
    config.actions.exclude :show, :delete, :edit 
    # this sets up clickable links for pets and plants. 
    # clicking either link will expand BOTH child object collections. 
    config.columns[:pets].set_link('nested', :parameters => {:associations => "pets plants"}) 
    config.columns[:plants].set_link('nested', :parameters => {:associations => "pets plants"}) 

    # uncomment these if you want to allow editing of pets and plants 
    # config.nested.add_link("Person's pets", [:pets]) 
    # config.nested.add_link("Person's plants", [:plants]) 
    end 
end 

Maintenant, le rapport ouvre avec les tables enfant se sont effondrés, alors nous devons les développer en utilisant event.simulate.js de protolicious.

Téléchargez protolicious et copiez event.simulate.js dans votre répertoire public/javascripts.

incluent maintenant event.simulate.js dans votre mise en page:

<%= javascript_include_tag :defaults %> 
<%= javascript_include_tag "event.simulate.js" %> 
<%= active_scaffold_includes %> 

Et ajoutez cette balise de script au bas de votre point de vue:

<script type="text/javascript"> 
    // iterates through each ActiveScaffold nested item link and clicks it 
    $$('a.nested').each(function(link, index) { 
    link.simulate('click'); 
    }); 
</script> 

Compte tenu des modèles suivants

application /models/person.rb

class Person < ActiveRecord::Base 
    has_many :pets 
    has_many :plants 
end 

app/modèles/pet.rb

class Pet < ActiveRecord::Base 
    belongs_to :person 
end 

app/modèles/plant.rb

class Plant < ActiveRecord::Base 
    belongs_to :person 
end 
+0

+1 pour la réponse détaillée correcte. Mais. De cette façon, un rapport d'environ 50 personnes produira 101 demandes au serveur, ce qui n'est pas suffisant. Un rapport annuel qui peut signifier plus de 2500 personnes, ce qui fait plus de 5000 demandes. :-( – Notinlist

+0

Question: Cliquer sur "Animaux" et les "Plantes" remplace la table des "Animaux" avec la table des "Plantes" Elles ne sont jamais montrées ensemble MAIS Je te le dis sans essayer le code exact a écrit: – Notinlist

+0

Notinlist: la source listée ici montre définitivement Pets et Plants simultanément Ceci est déclenché par set_link ('nested',: parameters => {: associations => "plantes d'animaux"}). – marshally