2009-06-12 6 views
1

Je suis sûr que c'est une question débutant tout à fait évidente, mais essayer de trouver des réponses aux questions Ruby débutant sur google se révèle être un exercice dans la futilité.Ruby Custom Class au modèle

Quoi qu'il en soit, supposons que j'ai une table de base de données qui ressemble à ceci:

MyMessage 
================== 
int :id 
string :from 
string :to 
string :messagetext 

Maintenant, si je dois exposer une URL qui prend en queryString params sous forme de:

http://mysite.com/?sender=alice&receiver=bob&message=Hello

Quelle est la meilleure façon de mapper les paramètres querystring à mon modèle?

En ce moment, je fais juste par la force brute à l'intérieur du contrôleur:

@sender = params[:sender] 
@receiver = params[:receiver] 
@message = params[:message] 

@mymessage = MyMessage.new 
@mymessage.from = @sender 
@mymessage.to = @receiver 
@mymessage.messagetext = @message 

@mymessage.save 

Je suppose que je devrais être en mesure de créer une classe représentant ce type de demande querystring, à savoir

class Request 
    attr_accessor :from 
    attr_accessor :to 
    attr_accessor :message 
end 

ensuite, utilisez un peu de magie RoR pour créer l'objet Request de la params puis plus magique pour créer une méthode qui associe l'objet Request à l'objet MyMessage.

Des suggestions? Est-ce que cela a du sens?

+0

Ceci est couvert dans à peu près chacun des tutoriels 'application my-first-Rails-'. En avez-vous fait un? – fig

+0

Oui, j'en ai fait environ quatre. Êtes-vous sûr de comprendre la question? Si vous pouvez poster un lien montrant un tutoriel où je l'ai manqué, je vais heureusement supprimer la question. Je pense que je peux le faire via update_attributes, mais la question est marquée 'newbie' pour une raison. – jerhinesmith

+0

Oui, j'ai créé les exemples d'applications. Aucun d'entre eux ne semble toutefois se pencher sur la création de classes personnalisées et leur mise en correspondance avec un modèle générique. Ne pas essayer d'être un crétin non plus, mais comprenez-vous que Model/DB avait des noms/propriétés de champs différents de ce qui est passé par la chaîne de requête? – jerhinesmith

Répondre

3

Vous pouvez faire quelque chose comme ceci:

class MyMessage < ActiveRecord::Base 
    def self.new_from_web(params) 
    returning(self.new) do |message| 
     message.from  = params[:sender] 
     message.to   = params[:receiver] 
     message.messagetext = params[:message] 
     message.save 
    end 
    end 
end 

class MessageController < ApplicationController 
    def save_message 
    MyMessage.new_from_web(params) 
    end 
end 

Bien sûr, tout cela pourrait vraisemblablement être rendu plus simple et plus classique en utilisant de manière plus explicite la sémantique RESTful.

0

Si vous utilisez l'enregistrement actif, la méthode que vous recherchez est update_attributes.

Ça va ressembler à quelque chose comme ceci:

def update 
    @model = Model.find(params[:id]) 
    @model.update_attributes(params[:model]) 
end 

Vous devez être conscient que cela va mettre à jour tout ce que l'utilisateur passe, y compris les champs que vous ne voulez pas changer, par exemple un drapeau comme is_admin sur votre modèle d'utilisateur.

Je suggère l'application attr_accessible à toutes les propriétés que vous souhaitez un utilisateur pour pouvoir modifier, par exemple:

class Model < AR:Base 
    attr_accessible :my_safe_field_name 
end 
+0

Cela a du sens pour moi si les champs transmis sont un mappage un-à-un du modèle, mais dans ce cas ils ne le sont pas (et ne le peuvent pas, puisque nous voulons que le modèle soit générique et ensuite exposer diverses URL RESTful pour les tiers à consommer). Ainsi, le modèle pourrait avoir «à», mais un fournisseur pourrait le transmettre comme «récepteur» et un autre pourrait utiliser «envoyé à», par exemple. Je pense que je dois créer des classes personnalisées pour chaque implémentation, puis les 'mapper' à la classe générique, mais je ne suis pas sûr de savoir comment procéder. Cela a-t-il du sens? – jerhinesmith

+0

Bien params [: model] est juste un hachage, donc vous pouvez toujours écrire une fonction pour changer les clés pour correspondre à votre modèle. Cependant, pourquoi ne pouvez-vous pas avoir une représentation pour les deux? – jonnii

1

Vous pouvez faire quelque chose comme:

class MessageRequest 
    def initialize(params = {}) 
    @sender = params[:sender] 
    @receiver = params[:receiver] 
    @message = params[:message] 
    end 

    def apply_to_my_message(my_message = MyMessage.new) 
    my_message.from = @sender 
    my_message.to = @receiver 
    my_message.message_text = @message 
    return my_message 
    end 
end 

Ensuite, votre code du contrôleur devient:

@mymessage = MessageRequest.new(params).apply_to_my_message 

Si vous voulez juste le personnaliser pour différents paramètres nommés de différents place que vous pourriez avoir des méthodes protégées retournant le nom du paramètre pour chacun des attributs. Par exemple.

class MessageRequest 
    def initialize(params = {}) 
    @sender = params[sender_param] 
    @receiver = params[receiver_param] 
    @message = params[message_param] 
    end 

    ... 

    protected 

    def sender_param; :sender; end 
    def receiver_param; :receiver; end 
    def message_param; :message; end 
end 

Vous pouvez ensuite créer des sous-classes pour les différents paramètres nommés comme:

class OtherMessageRequest < MessageRequest 

    protected 
    def receiver_param; :sentTo; end 

end 

probablement surpuissant pour ce que vous avez décrit, mais, espérons-ce que vous voulez en venir.

+0

A voté vers le haut. Une fois que je digère un peu plus, si ça a l'air de marcher, je vais l'accepter. Merci! – jerhinesmith

0

simple va habituellement un long chemin:

@message = MyMessage.new(params.slice(:sender, :receiver, :message))