2010-05-07 8 views
4

J'essaye de construire une grille, dans des rails, pour entrer des données. Il a des lignes et des colonnes, et les lignes et les colonnes sont jointes par des cellules. À mon avis, j'ai besoin que la grille puisse gérer de nouvelles lignes et colonnes sur le bord, de sorte que si vous les saisissez et que vous les soumettez, elles sont générées automatiquement et leurs cellules partagées sont correctement connectées . Je veux être en mesure de le faire sans JS.Rails attributs imbriqués avec un modèle de jointure, où l'un des modèles joint est un nouvel enregistrement

Les attributs imbriqués Rails ne parviennent pas à être mappés à la fois sur un nouvel enregistrement et sur une nouvelle colonne, ils ne peuvent effectuer que l'un ou l'autre. La raison en est qu'ils sont imbriqués spécifiquement dans l'un des deux modèles, et quel que soit celui dans lequel ils ne sont pas imbriqués n'aura aucun id (puisqu'il n'existe pas encore), et lorsqu'il est poussé par accepts_nested_attributes_for sur le modèle Grid de niveau supérieur , ils seront seulement liés au nouvel objet créé pour tout ce qu'ils ont été imbriqués.

Comment puis-je gérer cela? Dois-je contourner la gestion des rails des attributs imbriqués?

Mes modèles ressemblent à ceci, BTW:

class Grid < ActiveRecord::Base 
    has_many :rows 
    has_many :columns 
    has_many :cells, :through => :rows 

    accepts_nested_attributes_for :rows, 
    :allow_destroy => true, 
    :reject_if => lambda {|a| a[:description].blank? } 
    accepts_nested_attributes_for :columns, 
    :allow_destroy => true, 
    :reject_if => lambda {|a| a[:description].blank? } 
end 


class Column < ActiveRecord::Base 
    belongs_to :grid 
    has_many :cells, :dependent => :destroy 
    has_many :rows, :through => :grid 
end 

class Row < ActiveRecord::Base 
    belongs_to :grid 
    has_many :cells, :dependent => :destroy 
    has_many :columns, :through => :grid 

    accepts_nested_attributes_for :cells 
end 


class Cell < ActiveRecord::Base 
    belongs_to :row 
    belongs_to :column 
    has_one :grid, :through => :row 
end 

Répondre

0

Je fait face à un problème similaire il y a quelques jours, et de ce que je pouvais voir il n'y a pas moyen de contourner la question de la double imbrication. Je l'ai dépassé en changeant mon modèle «mental» du problème. En repensant à ce que je faisais et de la traduire à votre situation, voici l'approche que je pris:

class Grid < ActiveRecord::Base 
    has_many cells 
    has_many rows :through => :cells 
    has_many columns :through => :cells 

    accepts_nested_attributes_for :cells, :allow_destroy => true 
end 

class Cell 
    has_one column 
    has_one row 
    belongs_to grid 
end 

class Column 
    has_and_belongs_to_many cells 
end 

class Row 
    has_and_belongs_to_many cells 
end 

Vous obtiendrez certaines des fonctionnalités que vous voulez via des déclarations/méthodes telles que:

a_row = Grid.cells.where("row_id = a_cell.row_id") 

def remove # an instance method for Row 
    self.cells.each do |cell| 
     cell.delete 
    end 
end 

def add_column # an instance method for Grid 
    self.column_count += 1 
    self.row_count.times do |i| 
     cell.new(:column_id => :self.column_count, :row_id => :i) 
     cell.save 
    end 
end 

La plupart des opérations orientées sur les colonnes et les lignes que vous souhaitez effectuer sur votre grille doivent être accomplies avec les méthodes et les étendues que vous écrivez pour créer des collections de cellules ayant un row_id ou un column_id en commun.

Vous ne savez pas si cela fonctionnera exactement pour votre cas, mais cela pourrait vous aider avec différentes approches de modèle. Bonne chance.