Mô-đun Rails / lib và


83

Tôi đang viết một trình bao bọc tùy chỉnh cho open_flash_chartplugin. Nó được đặt trong /libvà tải nó như một mô-đun trong ApplicationController.

Tuy nhiên, tôi có một số vấn đề về phân cấp Lớp hoặc thứ.

Từ bất kỳ bộ điều khiển nào, tôi có thể truy cập các open_flash_chartchức năng OpenFlashChart, Linev.v.

Tuy nhiên, trong một lớp trong một /libmô-đun, nó không hoạt động!

Có ý kiến ​​gì không?


hy vọng điều này có thể giúp bạn stackoverflow.com/questions/17304110/…
S.Yadav

Câu trả lời:


147

Có hai cách để tải tệp trong Rails:

  • Nó được đăng ký trong quá trình tự động tải và bạn tham chiếu đến một hằng số tương ứng với tên tệp. Ví dụ: nếu bạn có app/controllers/pages_controller.rbvà tham chiếu PagesController, app/controllers/pages_controller.rbsẽ tự động được tải. Điều này xảy ra đối với một danh sách các thư mục đặt trước trong đường dẫn tải. Đây là một tính năng của Rails, và không phải là một phần của quá trình tải Ruby thông thường.
  • Tệp được rõ ràng required. Nếu một tệp là required, Ruby sẽ xem qua toàn bộ danh sách các đường dẫn trong đường dẫn tải của bạn và tìm trường hợp đầu tiên mà tệp bạn required nằm trong đường dẫn tải. Bạn có thể xem toàn bộ đường dẫn tải bằng cách kiểm tra $ LOAD_PATH (bí danh của $ :).

libtrong đường dẫn tải của bạn, bạn có hai tùy chọn: đặt tên tệp của bạn bằng tên giống với hằng số, vì vậy Rails sẽ tự động chọn chúng khi bạn tham chiếu đến hằng số được đề cập hoặc yêu cầu mô-đun một cách rõ ràng.

Tôi cũng nhận thấy rằng bạn có thể nhầm lẫn về một điều khác. ApplicationController không phải là đối tượng gốc trong hệ thống. Quan sát:

module MyModule
  def im_awesome
    puts "#{self} is so awesome"
  end
end

class ApplicationController < ActionController::Base
  include MyModule
end

class AnotherClass
end

AnotherClass.new.im_awesome
# NoMethodError: undefined method `im_awesome' for #<AnotherClass:0x101208ad0>

Bạn sẽ cần phải đưa mô-đun vào bất kỳ lớp nào bạn muốn sử dụng nó.

class AnotherClass
  include MyModule
end

AnotherClass.new.im_awesome
# AnotherClass is so awesome

Tất nhiên, để có thể bao gồm mô-đun ngay từ đầu, bạn sẽ cần phải có sẵn nó (sử dụng một trong các kỹ thuật ở trên).


2
Chỉ muốn thêm: Nếu một trong các mô-đun của bạn trong / lib (hoặc trong một trong các thư mục tự động tải) đã được xác định; dụ bạn quá tải ActiveRecord hoặc String, bạn sẽ phải yêu cầu nó một cách rõ ràng hoặc nó sẽ không được nạp
Mike

1
kỳ lạ, tôi đang nhận được: hằng số GaClient (NameError) chưa được khởi tạo, trừ khi tôi yêu cầu trước 'ga_client' (lớp được định nghĩa trong lib / ga_client.rb). Có tài liệu cho lược đồ đặt tên tự động tải không?
mkirk

87

Trong Rails 3 / lib, các mô-đun không được tải tự động.

Điều này là do dòng:

# config.autoload_paths += %W(#{config.root}/extras)

bên trong config / application.rb được nhận xét.

Bạn có thể cố gắng bỏ ghi chú dòng này hoặc, (nó thậm chí còn hoạt động tốt hơn đối với tôi), để lại nhận xét này (để tham khảo trong tương lai) và thêm hai dòng này:

config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]

Điều này sẽ sao chép ../libđường dẫn trong ApplicationName::Application.config.autoload_pathsmảng.
jibiel

1
@jibiel vậy giải pháp ở đây là gì?
ylluminate

4
tại sao tùy chọn sau lại hoạt động tốt hơn cho bạn? Ngoài ra, tại sao mặc định lại bị thay đổi ... chắc chắn phải có lý do mặc dù rất nhiều người đã tìm cách giải quyết.
ckarbass

@ylluminate Vì vậy, config.autoload_paths += Dir["#{config.root}/lib/**/"]chỉ có thể là đủ. @ckarbass Dòng thứ hai cho phép bạn tự do sắp xếp các tiện ích của mình thành các thư mục con và do đó làm hoàn thiện các mô-đun của bạn bằng không gian tên . Nó khá là nhiều. Và đây là lý do tại sao mặc định đã được thay đổi. Muộn còn hơn không bao giờ :)
jibiel

Điều này có vẻ hơi lộn xộn với tôi. Điều này sẽ không tự động tải các tác vụ cào không cần thiết phải không?
Dennis

22

Điều phù hợp với tôi, ngoài việc bỏ ghi chú config.autoload_paths (tôi đang sử dụng Rails 3.1.3), là tạo một trình khởi tạo như sau:

#config/initializers/myapp_init.rb
require 'my_module'    
include MyModule

Bằng cách này, tôi có thể gọi các phương thức mymodule từ bất kỳ đâu và dưới dạng phương thức lớp Model.mymodule_methodhoặc phương thức thể hiệnmymodel.mymodule_method

Có thể một số chuyên gia có thể giải thích ý nghĩa của điều này. Bây giờ, sử dụng nó có nguy cơ của riêng bạn.

Chỉnh sửa: Sau đó, tôi nghĩ cách ứng phó tốt hơn sẽ là:

tạo một trình khởi tạo như thế này:

#config/initializers/myapp_init.rb
require ‘my_module’

Bao gồm mô-đun nếu cần, như sau:

1) nếu bạn muốn sử dụng nó làm "Phương thức lớp", hãy sử dụng "mở rộng":

class Myclass < ActiveRecord::Base
   extend MyModule
   def self.method1
      Myclass.my_module_method
   end
end

2) nếu bạn muốn sử dụng nó làm "Phương thức phiên bản", hãy bao gồm nó bên trong định nghĩa Lớp:

class Myclass < ActiveRecord::Base
include MyModule
   def method1
      self.my_module_method 
   end
end

3) hãy nhớ rằng include MyModuleđề cập đến một tệp my_module.rbtrong đường dẫn tải của bạn mà trước tiên phải được yêu cầu


3
Tôi đã tạo mô-đun của mình trên libthư mục, do đó tôi đã thêm config.autoload_paths += %W(#{config.root}/lib)vào config/application.rbtệp. Sau đó, tôi đã làm theo gợi ý của bạn để thêm config/initializers/myapp_init.rbtệp và nội dung của nó. Mọi thứ đều tốt. Cảm ơn rất nhiều :)
SMMousavi

Mặc dù requirehoạt động đối với tôi và tự động tải không (phương pháp mô-đun không xác định), nhận xét này cho biết bạn không nên sử dụngrequire .
Dennis

3

Để sử dụng mô-đun lib/my_module.rbtrong các mô hình và bộ điều khiển của bạn:

Trong config/application.rb:

config.watchable_dirs['lib'] = [:rb]

Trong mô hình của bạn (ý tưởng tương tự cho bộ điều khiển của bạn):

require_dependency 'my_module'

class MyModel < ActiveRecord::Base
  include MyModule

  MyModule.some_method
end

Phương pháp này được mô tả chi tiết hơn tại http://hakunin.com/rails3-load-paths


0

Có thể xảy ra trường hợp bạn muốn tải rõ ràng (các) tệp trong thư mục lib tại thời điểm khởi tạo ứng dụng.
Trong config / application.rb của tôi, tôi có một mục nhập là,
config.autoload_paths += %W(#{config.root}/lib)

Ngoài ra , đây có thể là trường hợp tên mô-đun / cấu trúc phân cấp không giống như trong tệp hoặc vị trí / tên tệp không giống với cấu trúc phân cấp đó, vì vậy tự động tải của tệp đó cũng không được. Vì vậy, khi tôi thêm một mục ở cuối config / application.rb as,
require "./lib/file_name_without_extention
nó hoạt động tốt.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.