Referring to an instance in has_many (Rails)

I have a game model that has_many: texts. The problem is that I have to order the texts in different ways depending on which game they belong to (yes, ugly, but this is outdated data). I created a method Text.in_game_order_query(game)that returns the appropriate order.

My favorite solution would be to place the default area in the Text model, but for that you need to know which game they are entering. I also do not want to create separate text classes for each game - there are many games with a large number of arrivals, and all new ones will use the same order. Therefore, I had another idea: to order texts in has_many when I know which game they are entering:

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

However, the class itself is a class, so it does not work.

Is there no other solution than calling @game.texts.in_game_order(@game)every time?

+5
source share
6 answers

After using the PradeepKumar idea, I found the following solution to work

Assuming a class Blockthat has an attribute block_typeand a container class (like a page), you can have something like this:

class Page
  ...

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

  ...
end

Then when you call

page.blocks.ordered_by_type

you get what you want - defined by Proc. Obviously, Proc can be much more complicated and does not work in an SQL call, but after the result set has been compiled.

UPDATE:
I am re-reading this post and my answer after a lot of time, and I wonder if you can do something as easy as the other method that you basically suggested to yourself in this post.

, 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, . , :

: "" ( ). . , . , , . , .

+3

?

, :

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
+1

,

   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

I'm not sure what your query / query looks like in the in_game_order_query class method, but I believe you can do it

has_many :texts, :finder_sql => proc{Text.in_game_order_query(self)}

Just let me know that I have never used this before, but I would appreciate if you let me know if this works for you or not.

Check out http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many for more documentation on: finder_sql

0
source

I think that if you want to process runtime information, you should do this:

has_many :texts, :order => proc{ {Text.in_game_order_query(self)} }
-1
source

All Articles