2013-03-24 34 views
17

Cách tốt nhất để thực hiện một chút DRY trong công thức nấu ăn là gì? I E. chỉ cần tách ra các bit nhỏ của mã Ruby, vì vậy tôi không sao chép dán nó nhiều lần.DRY trong công thức Chef

Sau đây thất bại tất nhiên, với:

NoMethodError: undefined method `connect_root' for Chef::Resource::RubyBlock 

Tôi có thể có nhiều ruby_blocks trong một công thức, khi họ làm những việc khác nhau và cần phải có khác nhau not_if khối để được truley idempotent.

def connect_root(root_password) 
    m = Mysql.new("localhost", "root", root_password) 
    begin 
    yield m 
    ensure 
    m.close 
    end 
end 

ruby_block "set readonly" do 
    block do 
    connect_root node[:mysql][:server_root_password] do |connection| 
     command = 'SET GLOBAL read_only = ON' 
     Chef::Log.info "#{command}" 
     connection.query(command) 
    end 
    end 
    not_if do 
    ro = nil 
    connect_root node[:mysql][:server_root_password] do |connection| 
     connection.query("SELECT @@read_only as ro") {|r| r.each_hash {|h| 
     ro = h['ro'] 
     } } 
    end 
    ro 
    end 
end 

Trả lời

23

Như bạn đã biết, bạn không thể xác định hàm trong công thức nấu ăn. Đối với các thư viện đó được cung cấp. Bạn nên tạo một tập tin (ví dụ mysql_helper.rb) bên thư viện thư mục trong sách dạy nấu ăn của bạn như sau:

module MysqlHelper 
    def self.connect_root(root_password) 
    m = Mysql.new("localhost", "root", root_password) 
    begin 
     yield m 
    ensure 
     m.close 
    end 
    end 
end 

phải là một mô-đun, không phải là một lớp. Cũng lưu ý rằng chúng ta định nghĩa nó là static (sử dụng self.method_name). Sau đó, bạn sẽ có thể sử dụng các hàm được xác định trong mô-đun này trong công thức nấu ăn của mình bằng tên mô-đun với tên phương thức:

MysqlHelper.connect_root node[:mysql][:server_root_password] do |connection| 
    [...] 
end 
+0

Tôi đã không thử nó, nhưng nó là một câu trả lời hoàn chỉnh, ví dụ. Cảm ơn! Tôi rất buồn khi thấy rằng tôi phải tạo ra một thư viện nấu ăn đầu bếp cho một chức năng nhỏ mà sẽ không được sử dụng ở bất cứ nơi nào khác. Nhưng bất cứ điều gì. – DragonFax

+1

Nếu bạn muốn sử dụng các phương thức thể hiện, do đó bạn không cần phải thêm tiền tố bằng tên lớp, bạn chỉ cần thực hiện ':: Chef :: Recipe.send (: include, MysqlHelper)' và sau đó bạn có thể gọi 'connect_root 'trực tiếp. –

+0

Cảm ơn bạn @JohnMorales. Câu trả lời được chấp nhận là hoàn hảo, tuy nhiên dòng bạn thêm vào (hiển thị bên dưới) đã làm việc để hoàn thành: :: Chef :: Recipe.send (: include, MysqlHelper) – KLaw

1

Để lưu nội dung, tôi vừa tạo thư viện với nội dung sau. Nhưng điều đó có vẻ quá mức cần thiết cho DRY trong một tệp. Tôi cũng không thể tìm ra cách để có được bất kỳ không gian tên nào khác cho mô-đun để sử dụng, để làm việc.

class Chef 
    class Resource 
    def connect_root(root_password) 
     ... 
+8

Tài liệu cho thư viện trong sách dạy nấu ăn đầu bếp không đầy đủ và không rõ ràng. – DragonFax

+2

Bạn không nên monkeypatch lớp tài nguyên. Nó là tốt hơn để tạo ra một mô-đun và phương pháp địa chỉ thông qua các mô-đun. –

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