1
votes

Le moyen le plus élégant de créer un hachage à partir de deux sources de données

J'ai un building_table et api :: building_table, j'aimerais avoir les données de building_table par défaut mais si les données n'existent pas dans building_table j'aimerais avoir à les obtenir à api :: building_table. Le problème est qu'il existe des attributs qui n'existent peut-être pas dans building_table mais qui existent dans api building_table. Il y a aussi des colonnes qui ont un nom différent dans chaque table.

Voici mon exemple de code

def get_building_info
  building = Building.find_by(id: params[:id])
  api_building = Api::Building.find_by(id: params[:id])
  building_hash = {}
  building_hash[:name] = building.name || api_building.name
  building_hash[:room] = building.room || api_building.room
  building_hash[:rent] = building.rent || api_building.monthly_fee
...
end

y a-t-il une manière plus élégante de faire cela? btw ceci est dans mon contrôleur.


1 commentaires

Je pense qu'il y a des solutions «intelligentes» suggérées, mais votre approche est facile à lire et à comprendre, et vous devriez vous y tenir.


5 Réponses :


1
votes

Il existe de nombreuses solutions pour y parvenir, mais voici une solution plus simple:

def get_building_info
  building = Hash.new
  building[:name], building[:room] = desired_building.name, desired_building.room 
end

private

 def desired_building
    Building.find_by(id: params[:id]) || 
    Api::Building.find_by(id: params[:id])
 end


2 commentaires

Le problème est qu'un certain attribut peut être extrait de la construction de l'API, mais cela ne signifie pas que d'autres attributs seront également extraits de la construction de l'API.


Vous n'avez pas eu de question sur OP



1
votes

Je pense que vous le faites d'une manière correcte mais la variable building sera écrasée, vous devez définir une nouvelle variable comme building2 = {}


2 commentaires

Vous n'avez pas eu de question sur OP


Je suis désolé de l'avoir tapé dans le navigateur et c'était une faute de frappe!



1
votes
before_action :find_records, only: :get_building_info

def get_building_info
  building_hash = {}
  building_hash[:name] = building_name
  building_hash[:room] = building_room
  # OR
  building_hash[:name], building_hash[:room] = building_name, building_room

end

private

def find_records
  @building = Building.find_by(id: params[:id])
  @api_building = Api::Building.find_by(id: params[:id])
end

def building_name
  @building.name || @api_building.name
end

def building_room
  @building.room || @api_building.room
end

4 commentaires

salut, merci pour la réponse. Mon modèle de bâtiment est composé de 12 colonnes de plus, pensez-vous que c'est une bonne pratique d'en avoir 12 en privé?


Non ce n'est pas ,. je pensais que vous n'aviez que 2 paramètres


Pourquoi pas? Vous pouvez facilement les générer tous, donc il faudrait 5 lignes pour les 12 méthodes.


@AlekseiMatiushkin mais 12 méthodes privées, je pense que votre solution est bien meilleure que la mienne.



2
votes

L'approche générique, acceptant la liste des clés comme argument:

def get_building_info(keys = %i[name room rent].zip(%i[name room fee]))
  building = Building.find_by(id: params[:id])
  api_building = Api::Building.find_by(id: params[:id])
  keys.map do |key, api_key|
    [
      key,
      building.attributes[key.to_s] || api_building.attributes[api_key.to_s]
    ]
  end.to_h
end


7 commentaires

ma question semble manquer de plus de détails, je suis désolé!


J'ai aussi pensé à cela mais j'ai des colonnes de table qui ont des noms différents. Je suis désolé de ne pas l'avoir inclus dans ma question!


Mise à jour d'une réponse.


la raison pour laquelle je n'accepte pas les paramètres pour get_building_info est parce que c'est une requête ajax donc je n'ai id comme paramètre pour la construction.


Je ne suis pas sûr de suivre. La méthode ci-dessus fait exactement ce que vous voulez et peut parfaitement être appelée sans aucun paramètre passé. Comme vous pouvez le voir, il a une valeur par défaut pour l'argument.


Je pense que c'est très élégant, mais que se passe-t-il s'il n'y a que des colonnes qui peuvent être extraites de building_table et qu'elles existent ou non, elles seront prises de building_table


Puis passez nil ou ce qui n'existe pas dans la position respective des api_keys . Ce n'est même pas près d'élégant, c'est l'approche très courante utilisée partout dans le code ruby.