Jak skrócić tasiemce?

Piszę aplikację, w której m.in. prowadzona będzie lista rankingowa graczy. Zasady obliczania rankingu są straszliwie zamotane. W tej chwili istotne jest jedynie to, że do obliczenia rankingu potrzebna jest historia rozegranych partii. Jednak lista rankingowa ma wyświetlać aktualny stan.

Mam zatem modele Player, PlayerScore oraz Strength (to jest słownik nazw rankingów). Teraz trochę kodu:

[code=ruby]class Player < ActiveRecord::Base

has_many :scores, :class_name=>"PlayerScore", :dependent=>:destroy

(…)
end

class Strength < ActiveRecord::Base

has_many :scores, :class_name=>"PlayerScore"

(…)
end

class PlayerScore < ActiveRecord::Base
belongs_to :player
belongs_to :strength

def self.current(options={})
	last({:order=>:created_at}.merge(options))
end

end

( plik views/plyers/index.html.erb)

<%= t ".Listing players" -%>

(...)

<% @players.each do |player| %>

(...) <% end %>
<%= PlayerScore.human_attribute_name(:strength) -%>
<%=h player.scores.current.strength.name unless player.scores.current.nil? %>
[/code] Jak widać do wyświetlenia aktualnej siły gracza muszę stosować strasznego tasiemca. Gdyby to było tylko w jednym miejscu to drobiazg ale takie zapisy będą się powtarzać w wielu miejscach w aplikacji. Jak to skrócić? Myślałem już o has_many ... through ale to nie do końca jest prawdziwe bo powinno być has_one ... through.

Widziałem kiedyś w necie ciekawy artykuł o skracaniu takich tasiemców ale nie mogę go teraz odszukać … może ktoś ma adres w zakladkach?

A może tak po najmniejszej linii oporu i po prostu opakować tasiemca w metodę?

helpera?

def strength_for(player) h(player.scores.current.strength.name) unless player.scores.current.nil? end
i w widoku

<%= strength_for(player) %>

Też już myślałem o helperach ale to tylko częściowo rozwiązuje problem. Jednym z elementów obliczenia wyniku partii jest różnica siły graczy więc:

diff = player1.scores.current.strength.id - player2.scores.current.strength.id (...)
Najlepiej gdyby udało się przygotować odpowiednią metodę w modelu Player lub jakiś named_scope. Niestety moje próby kończyły się komunikatem o braku metody :frowning:

[quote=Tuptus]Też już myślałem o helperach ale to tylko częściowo rozwiązuje problem. Jednym z elementów obliczenia wyniku partii jest różnica siły graczy więc:

diff = player1.scores.current.strength.id - player2.scores.current.strength.id (...)
Najlepiej gdyby udało się przygotować odpowiednią metodę w modelu Player lub jakiś named_scope. Niestety moje próby kończyły się komunikatem o braku metody :([/quote]

[code]# w modelu
def strength
scores.current.strength
end

diff = player1.strength.id - player2.strength.id[/code]

[quote=drogus][code]# w modelu
def strength
scores.current.strength
end

diff = player1.strength.id - player2.strength.id[/code]
[/quote]
Ot ciekawostka. Dokładnie w ten sposób to robiłem i dostawałem komunikat o braku metody scores. Teraz działa. :slight_smile:
Dzięki.

W Rubym jest jedna rzecz, która jest nieco problematyczne - zmienne i metody mogą wyglądać tak samo. Dlatego jak korzystasz z metod,
które są akcesorami do związków (jak score powyżej) najlepiej zawsze używaj self:

[code=ruby]def method1

zamiast

scores.current.strength

bezpieczniej

self.scores.current.strength
end[/code]