2011-10-25 26 views
31

Ai đó có thể vui lòng giúp tôi hiểu phương thức 'send()' được liệt kê dưới đây được sử dụng để làm gì? Đoạn mã dưới đây, khi tôi đọc nó, không có ý nghĩa gì về mục đích phục vụ.Rails 100% newb issue - phương thức send()

Đây là ứng dụng Rails sử dụng Ruby 1.8.7 với Rails 1.2.3. Xin vui lòng không harp về tôi về nâng cấp, đó là một môi trường của khách hàng, vì vậy tôi không có loại giải trí.

Không cần phải nói mặc dù, tuyên bố tôi đang đề cập đến là như thế này;

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 

Performer Mẫu

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 

Bộ điều khiển rằng đây được chứa trong là hiệu suất. Tôi đã cọ rửa Google cố gắng tìm ra mục đích mà '@ perform.send (selected_track)' thực sự đang làm, nhưng cảm thấy như tôi đang chèo thuyền với một xoáy nước.

Ai đó có thể giúp tôi hiểu rõ hơn về điều này không?

Cảm ơn.

Trả lời

63

Việc thực hiện Ruby cho phương pháp send, được sử dụng để gửi tin nhắn phương pháp để một đối tượng, hoạt động như thế này:

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 

Đó là những điều cơ bản, thêm một mảnh thông tin quan trọng là gửi mà sẽ cho phép bạn gửi tin nhắn đến các phương thức TƯ NHÂN, chứ không phải các phương thức công khai.

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

Đối với những gì cụ thể gửi cuộc gọi của bạn sẽ làm, nhiều hơn khả năng có một def method_missing trong lớp Performer đó là thiết lập để bắt đó và thực hiện một số hành động.

Hy vọng điều này sẽ giúp, chúc bạn may mắn!

+0

Cảm ơn ctcherry! Ví dụ tuyệt vời! Đối với tham chiếu method_missing bạn vừa tạo. Không, thực ra chỉ có 4 phương thức trong lớp Performer. 3 (chỉ mục, hiển thị, và tiêu diệt) và tìm kiếm riêng tư_festival. Điều đó có nghĩa là việc gửi đó không có khả năng hoạt động đúng không? – Skittles

+0

Gửi sẽ vẫn hoạt động. Những gì nó được kích hoạt phụ thuộc vào biến 'selected_track' đang được chuyển vào nó. Bạn có thể đăng nhập và hiển thị nó cho chúng tôi và chúng tôi có thể cung cấp cho bạn thêm thông tin. – ctcherry

+0

Ngoài ra, bạn có đang tìm kiếm trong mô hình Trình điều khiển hoặc bộ điều khiển không? Bạn muốn xem mã mô hình cho sự cố gửi cuộc gọi này. – ctcherry

6

Phương pháp send tương đương với việc gọi phương thức đã cho trên đối tượng. Vì vậy, nếu biến số selected_track có giá trị là 1234, thì @performer.send(selected_track) cũng giống như @performer.1234. Hoặc, nếu selected_track là "a_whiter_shade_of_pale" thì nó giống như gọi số @performer.a_whiter_shade_of_pale.

Có lẽ, khi đó, lớp Trình diễn ghi đè method_missing sao cho bạn có thể gọi nó bằng bất kỳ bản nhạc nào (tên hoặc ID, nó không rõ ràng ở trên) và nó sẽ giải thích đó là tìm kiếm cho bản nhạc đó trong đó bài hát của người biểu diễn.

+0

Cảm ơn bạn đã phản hồi nhanh, JacobM! Câu trả lời của bạn thực sự giúp ích rất nhiều.Tôi nghĩ rằng những gì đã cho tôi một chút bối rối là lớp Performer không có một phương pháp được định nghĩa mà sẽ được gọi là như bạn mô tả. Ví dụ của bạn về biểu diễn @.12.1234 của phương pháp chỉ mục của Trình diễn được gọi là kết quả của việc sử dụng gửi hay cái gì? Tôi nhận thấy rằng có một before_filter đang được sử dụng trong lớp Performer. – Skittles

+1

Ah, mã bạn đăng những thứ đã được làm rõ. 'Method_missing' đang được hỏi là trong ActiveRecord :: Base - cách ActiveRecord hoạt động là tôi có thể định nghĩa một cột (trong cơ sở dữ liệu) trên một mô hình, và sau đó thực hiện cuộc gọi đến nó mặc dù nó không phải là một phương thức được định nghĩa trong mô hình. 'Method_missing' bắt được lời gọi phương thức đó và ActiveRecord khớp với" phương thức "mà tôi đã gọi với tên cột/thuộc tính. –

+0

Đây là tất cả bắt đầu có ý nghĩa tốt hơn bây giờ. Tôi đến từ trường học lập trình cũ. PHP & Perl và bây giờ chỉ nhận được đầu của tôi quấn quanh các cấu trúc phát triển ORM nghiêm ngặt hướng đối tượng. Cảm ơn vì sự thấu hiểu. Nó được đánh giá cao. :) – Skittles

11

send được sử dụng để chuyển một phương thức (và đối số) cho một đối tượng. Nó thực sự tiện dụng khi bạn không biết trước tên của phương thức, bởi vì nó được biểu diễn như một chuỗi hoặc ký hiệu đơn thuần.

Ex: Performer.find(params[:performer_id]) cũng giống như Performer.send(:find, params[:performer_id])

Cẩn thận ở đây vì dựa vào thông số khi sử dụng send có thể là nguy hiểm: những gì nếu người dùng vượt qua destroy hoặc delete? Nó thực sự sẽ xóa đối tượng của bạn.

+0

Cảm ơn bạn đã sẵn sàng! Tôi hiểu rồi. Một số điều này đang bắt đầu có ý nghĩa hơn bây giờ. Và có lẽ đó là một phần giải thích một lỗi mà trang đang ném như biến 'selected_track' không bao giờ được chuyển cho phương thức do_schedule từ những gì tôi có thể nói. – Skittles

+0

giải pháp tốt @apneadiving –

Các vấn đề liên quan