2010-02-28 31 views
13

Tôi có một vài phương pháp tôi muốn chia sẻ giữa các mô hình thay vì sao chép và dán chúng. Trong một bộ điều khiển, tôi có thể làm điều này bằng cách đặt các phương thức trong application_controller.rb mà tự động được đưa vào trong mọi bộ điều khiển. Có điều tương tự cho mô hình không?Cách chia sẻ mã trên các mô hình? (Rails 2.3)

Cảm ơn!

Trả lời

16

Bạn có thể tạo một tập tin gọi functionality.rb hoặc một cái gì đó tương tự trong lib thư mục của ứng dụng Rails của bạn. Đặt tên tệp sau mô-đun để tự động tải tệp khi Rails khởi động. Ví dụ, nếu tôi muốn thêm giảm sút nhiều mô hình, tôi muốn tạo ra một tập tin gọi là lib/flagging.rb, và nó sẽ trông như thế này:

module Flagging 
    # Flags an object for further review 
    def flag! 
    self.update_attribute(:flagged, true) 
    end 

    # Clears all flags on an object 
    def deflag! 
    self.update_attribute(:flagged, false) 
    end 
end 

Trong mỗi mô hình tôi muốn thêm chức năng này vào, tôi muốn làm như sau:

class Foo < ActiveRecord::Base 
    include Flagging 
end 

sau đó tôi có thể làm điều gì đó như:

foo = Foo.create 
foo.flag! 
+0

cảm ơn bạn! đó là những gì tôi đã kết thúc bằng cách sử dụng –

+1

dude. Đó là tất cả về thư mục lib. Tôi đã bắt đầu đặt thêm mã ở đó và nó chỉ là nơi thuận tiện để tổ chức mọi thứ. –

3

Bạn có thể a) làm điều gì đó tương tự với application_controller và tạo một lớp mô hình mà từ đó người khác có thể phân lớp hoặc b) sử dụng một mô-đun.

2

Có một số cách bạn có thể chia sẻ phương pháp giữa 2 lớp mô hình.

  • Sử dụng inheritance nếu các mô hình có liên quan với nhau, ví dụ: một lớp cha được chia sẻ có chứa các phương thức, hoặc một lớp con khác chứa các phương thức.
  • Sử dụng modules/mixins có thể được chia sẻ giữa nhiều mô hình
+0

'Biến những phương thức đó thành phương thức trợ giúp mà cả hai mô hình đều có quyền truy cập vào '- Tôi nghĩ rằng các mô hình không có quyền truy cập vào các phương thức trợ giúp. Làm thế nào là có thể (có vẻ như phương pháp sạch nhất cho những gì tôi đang cố gắng làm) –

+0

Bạn nói đúng. Tôi đã suy nghĩ phương pháp tiện ích, không phải là "phương pháp trợ giúp" trong ý nghĩa đường ray. Vì vậy, cách tiếp cận mixin sẽ hữu ích hơn các phương pháp tiện ích. – marklai

4

giải pháp hàng đầu phía trên làm việc cho tôi. Trong Rails 3 Tôi thấy rằng tôi cũng phải cập nhật tệp application.rb với: config.autoload_paths += Dir["#{config.root}/lib/**/"] như được trả lời ở đây: Best way to load module/class from lib folder in Rails 3?

0

Để thêm vào câu trả lời của Josh, đôi khi bạn có thể muốn chia sẻ một số mã xác định một liên kết đa hình. Bạn không thể chỉ cần đặt cuộc gọi has_many phương pháp trong mô-đun của bạn, bởi vì bạn sẽ gặp phải lỗi, ví dụ như trong một module gọi là Votable:

undefined method `has_many' for Voteable:Module (NoMethodError) 

Vì vậy, thay vào đó, bạn cần phải sử dụng các phương pháp self.included(base)base.instance_eval. Dưới đây là một ví dụ với mô-đun Voteable tôi:

module Voteable 

    def self.included(base) 
    base.instance_eval do 
     has_many :votes, as: :voteable 
     has_many :voters, through: :votes 
    end 
    end 

    def voted_up_by?(user) 
    user and votes.exists?(value: 1, voter_id: user) 
    end 

    def voted_down_by?(user) 
    user and votes.exists?(value: -1, voter_id: user) 
    end 

end 

Bây giờ bạn có thể include Voteable trong các mô hình mà sẽ có hành vi đó. Điều này sẽ thực thi phương thức self.included(base) và nó sẽ định nghĩa liên kết trên lớp bao gồm.

+0

Trong Rails 3, việc này thậm chí còn dễ dàng hơn - bạn có thể thay thế cơ sở 'def self.included (base).instance_eval' với 'extend ActiveSupport :: Concern include'. –

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