Como posso substituir um método getter em um modelo ActiveRecord?

98

Estou tentando substituir um método getter para um modelo ActiveRecord. Tenho um atributo chamado nameno modelo Categorye gostaria de poder fazer algo assim:

def name
  name_trans || name
end

Se o name_transatributo não for nulo, retorne-o, caso contrário, retorne o nameatributo. Como eu faria isso?

Em seguida, deve ser chamado normalmente assim:

@category.name
Oyvindhauge
fonte

Respostas:

123

O Rails Style Guide recomenda o uso de self[:attr]over read_attribute(:attr).

Você pode usá-lo assim:

def name
  name_trans || self[:name]
end
Wonsup Lee
fonte
Por que está melhor? Não se limite a criar links para outros sites, inclua as partes relevantes aqui. Links podem se tornar inválidos
JamesT
2
Para um pouco mais de contexto, consulte aqui: github.com/bbatsov/rails-style-guide/issues/155
mimsugara
98

Update: O método preferido de acordo com o Rails Style Guide é usar ao self[:name]invés de read_attributee write_attribute. Eu o encorajaria a pular minha resposta e preferir esta .


Você pode fazer exatamente assim, exceto que você precisa usar read_attributepara realmente buscar o valor do atributo name e evitar a chamada recursiva para o namemétodo:

def name 
  name_trans || read_attribute(:name)
end
meagar
fonte
2
Alguma idéia de por Rubocop prefere self[:name]mais read_attribute[:name]?
Zack Xu
18

Eu gostaria de adicionar outra opção para sobrescrever o método getter, que é simplesmente: super.

def name
  name_trans || super
end

isso funciona não apenas no método getter de atributos, mas também nos métodos getter de associações。

lei liu
fonte
1
Isso é o que os guias do Rails recomendam atualmente, para getters E setters: api.rubyonrails.org/classes/ActiveRecord/…
sandre89
5

Substituir o getter e usar read_attributenão funciona para associações, mas você pode usar alias_method_chain.

def name_with_override
  name_trans || name_without_override
end

alias_method_chain :name, :override
Patrick Oscity
fonte
Você pode dar um exemplo adequado ...?
Arup Rakshit
Bem. Acabei de ver o doco . Agora, se eu chamar nameo objeto de modelo, qual será chamado - name_with_overrideou name_without_override?
Arup Rakshit
1
nameagora vai ligar name_with_override. Se você deseja chamar o método original por algum motivo, você pode chamar name_without_override.
Patrick Oscity
O que vejo .. Obrigado por suas respostas //
Arup Rakshit
2

Se você usar atributos de loja como este

store :settings, accessors: [:volume_adjustment] 

ou usando gemas como hstore_accessor link de gema

Então você acabou usando o storemétodo no modelo, então para substituir aqueles métodos que você não pode usar self.read_attribute, você deve usar superassim:

def partner_percentage
  super.to_i || 10
end
onemanstartup
fonte
0

Se alguém quiser atualizar o valor após o name_transmétodo getter, você pode usar self [: name] =.

def name
  self[:name] = name_trans || self[:name]
  # don't do this, it will cause endless loop
  # update(name: name_trans)
end
fangxing
fonte
0

Você pode usar o método read_attribute do Rails. Rails docs

Rajat Bansal
fonte
Embora este link possa responder à pergunta, respostas apenas de link não são permitidas no SO, por favor, adicione algum contexto à sua resposta a partir do que está por trás desse link. Obrigado! :)
AJT82 de