Rails 100% новичок - метод send () - PullRequest
32 голосов
/ 26 октября 2011

Может ли кто-нибудь помочь мне понять, для чего используется метод send (), указанный ниже? Приведенный ниже код, когда я его читаю, не имеет смысла, для чего он служит.

Это приложение Rails, использующее Ruby 1.8.7 с Rails 1.2.3. Пожалуйста, не говорите мне об обновлении, это среда клиента, поэтому у меня нет такого досуга.

Само собой разумеется, что утверждение, на которое я ссылаюсь, выглядит так:

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

Модель исполнителя

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

Контроллер, в котором это содержится, является Производительностью. Я обыскивал Google, пытаясь выяснить, для чего на самом деле предназначен этот "@ Performer.send (selected_track)", но мне кажется, что я гребу против водоворота.

Может кто-нибудь помочь мне разобраться в этом?

Спасибо.

Ответы [ 3 ]

65 голосов
/ 26 октября 2011

Реализация Ruby для метода send, который используется для отправки сообщения метода объекту, работает следующим образом:

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

Это основа, дополнительная часть важной информации заключается в том, что send позволит вам отправлять в сообщениях методы PRIVATE, а не только публичные.

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

Что касается того, что будет делать ваш конкретный вызов, более вероятно, что в классе Performer есть def method_missing, который настроен на его перехват и выполнение некоторых действий.

Надеюсь, это поможет, удачи!

12 голосов
/ 26 октября 2011

send используется для передачи метода (и аргументов) объекту. Это очень удобно, когда вы не знаете заранее название метода, потому что он представлен в виде простой строки или символа.

Пример: Performer.find(params[:performer_id]) совпадает с Performer.send(:find, params[:performer_id])

Остерегайтесь здесь, поскольку полагаться на параметры при использовании send может быть опасно: что если пользователи передадут destroy или delete? Это на самом деле удалит ваш объект.

6 голосов
/ 26 октября 2011

Метод send является эквивалентом вызова данного метода для объекта. Поэтому, если переменная selected_track имеет значение 1234, то @performer.send(selected_track) совпадает с @performer.1234. Или, если selected_track это "a_whiter_shade_of_pale", то это похоже на вызов @performer.a_whiter_shade_of_pale.

Предположительно, тогда класс Performer переопределяет method_missing таким образом, что вы можете вызывать его с любой дорожкой (имя или идентификатор, это не ясно из приведенного выше), и он будет интерпретировать это как поиск этой дорожки внутри треки этого исполнителя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...