acts_as_tree并通过子标头将值传播到项目

时间:2012-02-15 21:35:57

标签: ruby-on-rails ruby ruby-on-rails-3 acts-as-tree

我有一个复杂的模型,并希望通过我对rails的有限理解来获得全部功能。

我有一个部分,一个标题(使用acts_as_tree)和一个项目。

我使用json来提供数据集。这非常有用。我希望能够为整个数据集带来属性,例如'is_shippable'。我希望能够在树中的任何位置指定is_shippable值并设置为true。此外,我希望能够在标题或项目级别覆盖以将其设置为false。

我已经确定将is_shippable作为section,header和item的属性是有意义的,并尝试使用before_create回调来确定它是否应该是is_shippable。

例如:

section
  header -acts_as_tree
    item - is_shippable

示例json:

{
 "name":"sample section",
 "is_shippable": true,
 "headers_attributes":[
   {
    "name":"sample_section"
    "items_attributes":[{
      "name":"sample item",
      "is_shippable":false,
           }
    ]       
   }
 ]

}

在header.rb中

before_save :default_values
private 
def default_values
  self.is_shippable ||=self.section.is_shippable
  # need to be able to set header to is_shippable=false if specified explicitly at that level    
end
item.rb中的

before_save :default_values


private 
def default_values
  # if not set, default to 0
  self.is_shippable ||= 0
  self.is_shippable=1 if self.header.is_shippable==true
  # need to be able to set item to is_shippable=false if specified explicitly at that level
end

有没有比我做的更好的方法呢?如果is_shippable被设置为false,如果在层次结构中将其设置为更高,我将如何在if语句中执行?

编辑 - 还有更多的功能,如is_fragile,is_custom_size等is_shippable ......

2 个答案:

答案 0 :(得分:1)

我更倾向于在控制器中使用before_filter来修改嵌套项目参数。

类似的东西:

before_filter :set_is_shippable, :only => [:update, :create]

def set_is_shippable
  is_shippable = params[:section][:is_shippable]
  params[:section][:items_attributes].each_with_index do |item, index|
    unless item[:is_shippable]
      params[:section][:items_attributes][index][:is_shippable] = is_shippable
    end
  end
end

答案 1 :(得分:0)

我强烈推荐ancestry宝石。它有更多的树遍历方法,并且还优化了对数据库的查询次数。

如果我理解你的困境,ancestry会允许你做以下事情:

@section.descendants.all?(&:is_shippable)

无论如何,祖先更具表现力,肯定会给你更大的灵活性。下面链接的github wiki是宝石,是我见过的最好的。非常有条理,也许仔细阅读它会给你一些更多的想法。

https://github.com/stefankroes/ancestry

http://railscasts.com/episodes/262-trees-with-ancestry