11
votes

Problème avec le postéral Setter sur Activerecord

Ce n'est pas exactement une question, c'est plutôt un rapport sur la manière dont j'ai résolu un problème avec write_attribute code> lorsque l'attribut est un objet, sur les rails ' actif enregistrement code>. J'espère que cela peut être utile aux autres face au même problème.

Permettez-moi d'expliquer avec un exemple. Supposons que vous ayez deux classes, book code> et auteur code>: p> xxx pré>

très simple. Mais, pour une raison quelconque, vous devez remplacer l'auteur code> code> = méthode sur book code>. Comme je suis nouveau dans les rails, j'ai suivi la suggestion de Sam Ruby sur le développement Web Agile avec des rails: utilisez attribute_writer code> méthode privée. Donc, mon premier essai était: p> xxx pré>

Malheureusement, cela ne fonctionne pas. C'est ce que je reçois de la console: p>

>> book = Book.new(:name => "Alice's Adventures in Wonderland", :pub_year => 1865)
=> #<Book id: nil, name: "Alice's Adventures in Wonderland", pub_year: 1865, author_id: nil, created_at: nil, updated_at: nil>
>> book.author = "Lewis Carroll"=> "Lewis Carroll"
>> book
=> #<Book id: nil, name: "Alice's Adventures in Wonderland", pub_year: 1865, author_id: nil, created_at: nil, updated_at: nil>
>> book.author
=> #<Author id: nil, name: "Lewis Carroll", created_at: nil, updated_at: nil>


0 commentaires

3 Réponses :


21
votes

Je recommande de créer un attribut virtuel au lieu de remplacer la méthode authentificateur = . xxx

alors vous pouvez faire des choses cool comme l'appliquer à un champ de formulaire. < / p> xxx

serait-ce que cela fonctionnerait pour votre situation?


6 commentaires

Je pensais faire ça, mais je ne voulais pas d'attributs en double. La méthode que j'ai proposée ci-dessus fonctionne très bien; Je voulais juste le partager. Je peux en effet faire le tour text_field avec ça. Mais merci pour votre réponse! = D


Ne serait-il pas plus correct de remplacer la méthode authentifiant avec délégué: Nom ,: =>: Auteur ,: préfixe => vrai ?


@Adam, c'est certainement une solution alternative de le faire. Je n'utilise généralement que délégué lors de la gestion de plusieurs méthodes. S'il n'y en a qu'un seul, je préfère définir la méthode directement parce que je pense que c'est plus clair.


Y a-t-il des descentes cachées à l'utilisation de délégués ou est-ce juste une préférence personnelle?


Je ne peux penser à aucune descente d'utiliser délégué . Il se sent un peu plus compliqué que de définir la méthode directement dans ce scénario spécifique.


J'ai des besoins très similaires, mais pas tout à fait identique, y a-t-il un moyen de faire quelque chose de similaire à la création d'une méthode def auteure = et à l'intérieur de l'équivalent de super (auteur) ?



6
votes

Lorsque vous remplacez l'accesseur, vous devez définir un attribut db réel pour wreck_attribute code> et auto [: the_atribute] = code> et non le nom de l'association générée Attribut que vous remplacez. Cela fonctionne pour moi.

require 'rubygems'
require 'active_record'
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
ActiveRecord::Schema.define do
  create_table(:books) {|t| t.string :title }
  create_table(:authors) {|t| t.string :name }
end

class Book < ActiveRecord::Base
  belongs_to :author

  def author=(author_name)
    found_author = Author.find_by_name(author_name)
    if found_author
      self[:author_id] = found_author.id
    else
      build_author(:name => author_name)
    end
  end
end

class Author < ActiveRecord::Base
end

Author.create!(:name => "John Doe")
Author.create!(:name => "Tolkien")

b1 = Book.new(:author => "John Doe")
p b1.author
# => #<Author id: 1, name: "John Doe">

b2 = Book.new(:author => "Noone")
p b2.author
# => #<Author id: nil, name: "Noone">
b2.save
p b2.author
# => #<Author id: 3, name: "Noone">


3 commentaires

Comme je l'ai dit ci-dessus, la méthode que vous avez proposée ne fonctionne que si l'auteur est enregistré (c'est-à-dire une pièce d'identité), ce qui n'est pas mon cas. Je peux avoir un nouvel auteur qui doit être sauvé uniquement lorsque le livre est enregistré aussi.


J'ai ré-écrit un peu basé sur votre commentaire. Cela a-t-il plus de sens maintenant?


Oh merci, maintenant cela fonctionne comme je m'attends. Mais (malgré toutes les recommandations) Je tiendrai la solution d'origine. Néanmoins, c'est une bonne alternative si je change d'avis un jour. =]



0
votes

J'ai résolu ce problème en utilisant alias_method xxx


0 commentaires