2012-08-14 55 views
5

我有一个has_many的游戏模型:texts。问题是,我必须根据它们属于哪个游戏对文本进行不同的排序(是的,很丑,但它是传统数据)。我创建了一个Text.in_game_order_query(game)方法,它返回适当的顺序。参考has_many中的实例(Rails)

我最喜欢的解决方案应该是在Text模型中放置一个默认范围,但这需要知道他们是哪个游戏的一部分。我也不想为每个游戏的文本创建单独的类 - 有很多游戏,更多的游戏,所有新的游戏都将使用相同的顺序。所以,我有另外的想法:在订货的has_many文本,当我知道他们的一部分,该游戏:

has_many :texts, :order => Text.in_game_order_query(self) 

然而,自我是这里的班级,这样是行不通的。

除了每次打电话@game.texts.in_game_order(@game)以外真的没有其他解决方案吗?

回答

-1

我认为,如果你想运行时信息处理,你应该得到这跟做:

has_many :texts, :order => proc{ {Text.in_game_order_query(self)} } 
+0

双曲花括号给了我一个语法错误,并且只有一组{}围绕它表示“无法访问proc”。 – Sprachprofi 2012-08-14 10:27:22

+0

抱歉错字。只有一套大括号。但我不确定,如果这适用于:订单。我用它:条件。如果proc不起作用,请尝试使用lambda或Proc.new – 2012-08-14 11:37:11

0

这里有一个方法,你可以做到这一点,

has_many :texts, :order => lambda { Text.in_game_order_query(self) } 

这是另一种方式,我通常不会推荐(但会工作),

has_many :texts do 
    def game_order(game) 
    find(:all, :order => Text.in_game_order_query(game)) 
    end 
end 

你可以打电话给他们,

game.texts.game_order(game) 
+0

“Can not visit proc”:-( – Sprachprofi 2012-08-14 10:27:45

+0

尝试使用'has_many:texts,lambda {{:order => Text.in_game_order_query(self)}}' – PradeepKumar 2012-08-14 10:45:36

+0

“错误参数的数量(1代表0)“ - 我开始认为这是不可能的:-(我也尝试将这个函数移动到游戏模型,以便我可以做self.in_game_order_query而不必传递参数,但没有运气。 – Sprachprofi 2012-08-14 12:14:33

1

会的Association extension是一种可能性?

看来,你可以做这项工作:

module Legacy 
    def legacy_game_order 
    order(proxy_association.owner.custom_texts_order) 
    end 
end 

class Game << ActiveRecord::Base 
    includes Legacy 
    has_many :texts, :extend => Legacy 

    def custom_texts_order 
    # your custom query logic goes here 
    end 
end 

这种方式,给定一个游戏实例,你应该能够无需自通过访问实例的自定义查询:

g = Game.find(123) 
g.texts.legacy_game_order 
3

继续使用PradeepKumar的想法,我发现下面的解决方案工作

假设一个类Block其中有一个属性block_type,和co ntainer类(比如页),你可以有这样的事情:

class Page 
    ... 

    has_many :blocks do 
    def ordered_by_type 
     # self is the array of blocks 
     self.sort_by(&:block_type) 
    end 
    end 

    ... 
end 

然后当你调用

page.blocks.ordered_by_type 

你得到你想要的东西 - 由proc定义。 很显然,Proc可能更复杂,并且在SQL调用中不工作,但是在编译结果集之后。

UPDATE:
我重新阅读这篇文章和一堆时间后,我的答案,我不知道你是否可以做作为你基本上表明自己在后的另一种方法是简单的事情。

如果添加什么Game的方法称为ordered_texts

def ordered_texts 
    texts.in_game_order(self) 
    end 

这是否解决了问题?或者这种方法是否需要与其他Game关系方法链接?

3

最近我有一个非常类似的问题,我确信在Rails中这是不可能的,但是我学到了一些非常有趣的东西。

您可以声明一个作用域的参数,然后不传入它,它会默认传递父对象!

所以,你可以这样做:

class Game < ActiveRecord 
    has_many :texts, -> (game) { Text.in_game_order_query(game) } 

相信不相信,你没有在游戏中通过。 Rails会为你神奇地做它。你可以简单地做:

game.texts 

虽然有一个警告。如果您启用了预加载,这在Rails中目前无法使用。如果这样做,您可能会收到以下警告:

DEPRECATION警告:关联作用域的“文本”是实例相关的(作用域块带有参数)。预加载在个体实例创建之前发生。这意味着没有实例被传递给关联作用域。这很可能会导致错误或不正确的行为。加入,预加载和急切加载这些关联将被弃用,并且将来会被删除。