web-dev-qa-db-fra.com

Rails 100% newb issue - méthode send ()

Quelqu'un pourrait-il m'aider à comprendre à quoi sert la méthode 'send ()' listée ci-dessous? Le code ci-dessous, quand je le lis, n'a aucun sens à quoi il sert.

C'est une application Rails utilisant Ruby 1.8.7 avec Rails 1.2.3. Veuillez ne pas me harceler la mise à niveau, c'est l'environnement d'un client, donc je n'ai pas ce genre de loisir.

Il va sans dire que la déclaration à laquelle je fais référence est la suivante;

def do_schedule
  @performance = Performance.new(params[:performance])
  @performer = Performer.find(params[:performer_id])
  selected_track = params[:selected_track]
  if FileTest.exists?(File.expand_path(@performer.photo))
    @performance.photo = File.open(File.expand_path(@performer.photo))
  end

  @performance.audio = File.open(File.expand_path(@performer.send(selected_track)))

  if @performance.save
    flash[:notice] = 'Performer scheduled.'
    redirect_to :controller => :performer, :action => :index
  else
    render :action => 'schedule'
  end
end

Modèle d'interprète

class Performer < ActiveRecord::Base
  file_column :audio_one
  file_column :audio_two
  file_column :audio_three
  file_column :photo

  belongs_to :festival
  validates_presence_of :name, :first_name, :last_name, :address, :city, :state, :Zip, :daytime_phone, :availability, :stages
  validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
  validates_confirmation_of :email

  validates_presence_of :audio_one, :audio_two, :audio_three, :photo, :if => :submitted

  after_create :salt_access_key
  serialize :availability
  serialize :stages

  attr_accessor :other_type_of_music
  before_save :set_other_type

  def set_other_type
    if type_of_music == 'Other'
      self.type_of_music = "Other - #{other_type_of_music}" unless other_type_of_music.blank?
    end
  end

  def salt_access_key
    update_attribute(:access_key, Digest::SHA1.hexdigest("--#{self.id}--#{self.name}--#{self.festival.year}"))
  end

  def preferred_stages
    stages = []
    festival = Festival.find(self.festival_id.to_i)
    self.stages.collect { | key, value |
      id = key.gsub(/[\D]/, '').to_i
      if id > 0
        stages << festival.performance_stages.find(id).name
      end
    }
    return stages
  end
end

Le contrôleur dans lequel il est contenu est Performance. J'ai parcouru Google en essayant de comprendre à quoi sert réellement '@ performer.send (selected_track)', mais j'ai l'impression de ramer contre un tourbillon.

Quelqu'un peut-il m'aider à mieux comprendre cela?

Merci.

34
Skittles

L'implémentation Ruby pour la méthode send, qui est utilisée pour envoyer un message de méthode à un objet, fonctionne comme ceci:

class Car

  def start
    puts "vroom"
  end

  private

  def engine_temp
    puts "Just Right"
  end

end

@car = Car.new
@car.start # output: vroom
@car.send(:start) # output: vroom

Ce sont les bases, une information supplémentaire importante est que l'envoi vous permettra d'envoyer des messages à des méthodes PRIVÉES, pas seulement publiques.

@car.engine_temp  # This doesn't work, it will raise an exception
@car.send(:engine_temp)  # output: Just Right

Quant à ce que fera votre appel d'envoi spécifique, il y a plus que probablement un def method_missing dans la classe Performer qui est configurée pour intercepter cela et effectuer une action.

En espérant que ça aide, bonne chance!

67
ctcherry

send est utilisé pour passer une méthode (et des arguments) à un objet. C'est vraiment pratique lorsque vous ne connaissez pas à l'avance le nom de la méthode, car il est représenté comme une simple chaîne ou un symbole.

Ex: Performer.find(params[:performer_id]) est identique à Performer.send(:find, params[:performer_id])

Méfiez-vous ici car se fier aux paramètres lors de l'utilisation de send peut être dangereux: que se passe-t-il si les utilisateurs passent destroy ou delete? Cela supprimerait en fait votre objet.

12
apneadiving

La méthode send est l'équivalent d'appeler la méthode donnée sur l'objet. Ainsi, si la variable selected_track A une valeur de 1234, alors @performer.send(selected_track) est identique à @performer.1234. Ou, si selected_track Est "a_whiter_shade_of_pale" alors c'est comme appeler @performer.a_whiter_shade_of_pale.

Vraisemblablement, alors, la classe Performer remplace method_missing De telle sorte que vous pouvez l'appeler avec n'importe quelle piste (nom ou ID, ce n'est pas clair d'après ce qui précède), et elle interprétera cela comme une recherche de cette piste dans les pistes de cet artiste.

6
Jacob Mattison