开发者

Rails nested attributes with a join model, where one of the models being joined is a new record

I'm trying to build a grid, in rails, for开发者_运维问答 entering data. It has rows and columns, and rows and columns are joined by cells. In my view, I need for the grid to be able to handle having 'new' rows and columns on the edge, so that if you type in them and then submit, they are automatically generated, and their shared cells are connected to them correctly. I want to be able to do this without JS.

Rails nested attributes fail to handle being mapped to both a new record and a new column, they can only do one or the other. The reason is that they are a nested specifically in one of the two models, and whichever one they aren't nested in will have no id (since it doesn't exist yet), and when pushed through accepts_nested_attributes_for on the top level Grid model, they will only be bound to the new object created for whatever they were nested in.

How can I handle this? Do I have to override rails handling of nested attributes?

My models look like this, 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


I faced a similar issue just a few days ago, and from what I could see there is no way around the dual nesting issue. I got beyond it by changing my "mental" model of the problem. In looking back at what I did and translating it to your situation, here is the approach I took:

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

You will get some of the functionality you want via statements/methods like:

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

Many of the column and row oriented operations that you want to perform on your grid will need to be accomplished with methods and scopes you write to create collections of cells that have a row_id or column_id in common.

Not sure if this will work for your case exactly, but it might help you with some different model approaches. Good luck.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜