【问题标题】:Rails 100% newb issue - send() methodRails 100% 新手问题 - send() 方法
【发布时间】:2011-12-15 06:23:18
【问题描述】:

有人可以帮我理解下面列出的“send()”方法的用途吗?下面的代码,当我阅读它时,不知道它的用途是什么。

这是一个使用 Ruby 1.8.7 和 Rails 1.2.3 的 Rails 应用程序。升级的事请不要跟我唠叨,这是客户的环境,所以我没有那种闲暇。

不用说,我所指的说法是这样的;

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

其中包含的控制器是 Performance。我一直在搜索谷歌,试图弄清楚 '@performer.send(selected_track)' 的实际用途,但感觉就像我在逆着漩涡划船。

有人可以帮我更好地理解这个吗?

谢谢。

【问题讨论】:

    标签: ruby-on-rails ruby send


    【解决方案1】:

    send 方法的 Ruby 实现,用于向对象发送方法消息,其工作原理如下:

    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 来捕获它并执行一些操作。

    希望这会有所帮助,祝你好运!

    【讨论】:

    • 感谢 ctcherry!很好的例子!至于你刚刚做的 method_missing 参考。不,Performer 类中实际上只有 4 个方法。 3(索引、显示和销毁)和一个私人的lookup_festival。这是否意味着该发送无法正常工作?
    • 发送仍然有效。它触发的内容取决于传递给它的 selected_track 变量。您可以将其记录下来并展示给我们,我们或许可以为您提供更多信息。
    • 另外,您是在寻找 Performer 模型还是控制器?您想查看此发送调用问题的模型代码。
    • @Skittles index、show 和 destroy 方法不太可能在 Performer 类中,考虑到您问题中的代码,这几乎肯定是一个模型。 Performer 模型是否有 selected_track 方法或 DB 列?
    • @Dave Newton,我正在查看控制器。我可以为你们粘贴模型,如果这样可以澄清一点。似乎只有 :other_type_of_music 的一个 attr_accessor 和 set_other_type、salt_access_key 和 Preferred_stages 的 3 个 defs。
    【解决方案2】:

    send 用于将方法(和参数)传递给对象。当您事先不知道方法的名称时,它真的很方便,因为它仅表示为字符串或符号。

    例如:Performer.find(params[:performer_id]) 与 Performer.send(:find, params[:performer_id]) 相同

    这里要小心,因为在使用send 时依赖参数可能很危险:如果用户通过destroy 或delete 怎么办?它实际上会删除您的对象。

    【讨论】:

    • 感谢 apneadiving!我知道了。其中一些现在开始变得更有意义了。也许这部分解释了页面抛出的错误,因为据我所知,“selected_track”变量从未传递给 do_schedule 方法。
    【解决方案3】:

    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,这样您就可以使用任何轨道(名称或 ID,从上面不清楚)调用它,并且它将解释为在其中搜索该轨道那个表演者的曲目。

    【讨论】:

    • 感谢您的快速响应,JacobM!你的回答真的很有帮助。我认为让我有点困惑的是,Performer 类没有定义一个可以按照您描述的方式调用的方法。您的@performer.1234 示例是否表明由于发送使用而调用了 Performer 的索引方法还是什么?我注意到在 Performer 类中也使用了 before_filter。
    • 啊,您发布的代码澄清了一些事情。有问题的method_missing 在 ActiveRecord::Base 中——ActiveRecord 的工作方式是我可以在模型上定义一个列(在数据库中),然后调用它,即使它不是模型。 Method_missing 捕获该方法调用,ActiveRecord 将我调用的“方法”与列/属性名称匹配。
    • 这一切现在开始变得更有意义了。我来自旧的编程学校。 PHP 和 Perl,直到现在我才开始关注对象驱动的严格 ORM 开发结构。感谢您的洞察力。非常感谢。 :)
    • 让我澄清一下,当我说“老派”时,我只是用它来描述那些语言松散的编码原则。从 80 年代后期开始编程。 :)
    • "send 方法相当于调用对象的给定方法。"绝对是最好的答案。
    猜你喜欢
    • 2011-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多