2013-08-31 20 views
25

Module#refine phương pháp có một lớp học và một khối và trả về một mô-đun tinh tế, vì vậy tôi nghĩ tôi có thể xác định:Cách tốt hơn để biến một lớp ruby ​​thành một mô-đun hơn là sử dụng các sàng lọc?

class Class 
    def include_refined(klass) 
    _refinement = Module.new do 
     include refine(klass) { 
     yield if block_given? 
     } 
    end 
    self.send :include, _refinement 
    end 
end 

và kiểm tra sau đi

class Base 
    def foo 
    "foo" 
    end 
end 

class Receiver 
    include_refined(Base) { 
    def foo 
     "refined " + super 
    end 
    } 
end 

describe Receiver do 
    it { should respond_to(:foo) } 
    its(:foo) { should eq("refined foo") } 
end 

Vì vậy, sử dụng cải tiến, tôi có thể biến một lớp học thành một mô-đun, tinh chỉnh hành vi của nó một cách nhanh chóng và bao gồm nó trong các lớp khác.

  • Có cách nào đơn giản hơn để biến lớp học thành mô-đun trong Ruby (ví dụ: trong ruby ​​< 2)?
  • Trong C-thực hiện rb_mod_refine chúng ta thấy

    refinement = rb_module_new(); 
    RCLASS_SET_SUPER(refinement, klass); 
    

    Đây chỉ là thiết lập các lớp cha của sự tinh tế để klass rằng bản việc thực hiện các lớp bên trong module tinh tế?

  • Tôi biết rằng nhiều thừa kế IS được thực hiện thông qua Mô-đun, nhưng cộng đồng sẽ nghĩ gì về số Class#include_refined ở trên? Sẽ hợp lý để trích xuất khía cạnh này ra khỏi các sàng lọc? "Địa phương" vá bên trong một Lớp thay vì sử dụng các công tắc "sử dụng" để kích hoạt các sàng lọc?
+1

Âm thanh như một giải pháp bất thường. Có bất kỳ trường hợp sử dụng thực tế nào trong Rails không? –

+1

@BillyChan Hãy tưởng tượng tôi muốn sử dụng tất cả các hành động được định nghĩa trong một số lớp điều khiển được định nghĩa trong một số gem (hoặc Rails :: Engine) trong bộ điều khiển của tôi, tất nhiên kế thừa từ 'ApplicationController' của tôi. Lấy [Tolk :: LocalesController] (https://github.com/tolk/tolk/blob/master/app/controllers/tolk/locales_controller.rb) chẳng hạn. –

+0

Tôi bối rối là tại sao bạn muốn làm điều này. Tại sao không định nghĩa nó như là một mô-đun, và nếu bạn cần phải khởi tạo một cái gì đó với _just những phương thức đó, bạn có thể tạo một lớp không làm gì ngoài việc bao gồm các mô-đun. – prater

Trả lời

1

Andrea, cảm ơn bạn đã cung cấp thông tin trong nhận xét. Xin lỗi vì thiếu kiến ​​thức của tôi để hiểu điều này thực sự cần thiết mặc dù nó nghe có vẻ có thể làm được theo nghiên cứu của bạn.

Tôi không nghĩ chúng ta cần phải đi quá thấp để làm điều gì đó trong Rails.

Nếu tôi định làm tương tự trên Engine, tôi sẽ thử các ý tưởng sau đây, từ dễ đến khó.

  1. Trong các tuyến đường, hãy lắp toàn bộ động cơ vào đúng tuyến đường.

    Tôi sợ việc sử dụng phổ biến nhất này không thể phù hợp với nhu cầu của bạn

  2. Trong routes.rb, Tùy chỉnh đường cơ cho bộ điều khiển cụ thể trong lộ trình ứng dụng.

    Phát triển, làm động cơ, có thể thực hiện dễ dàng. Nhưng tôi biết không phải mọi động cơ đều có thể thực hiện điều này.

  3. Trong routes.rb, chuyển hướng tập hợp cụ thể hoặc toàn bộ tuyến đường đến các tuyến đường cơ của

  4. Trong hành động của ứng dụng, chuyển hướng đến hành động động cơ cụ thể trong hành động của ứng dụng.

    này nên được tùy chỉnh đủ cho hành động cụ thể

    class FoosController < ApplicationController 
        def foo 
        redirect_to some_engine_path if params[:foo] == 'bar' 
        end 
    
  5. Inherit điều khiển của động cơ - một tập hợp các hành động, và nếu tất cả ở trên không thể phù hợp với

    * lớp học của động cơ là có sẵn trong tất cả các ứng dụng, bạn có thể kế thừa một bộ điều khiển từ chúng, thay vì ApplicationController bình thường.

    # class FoosController < ApplicationController 
    class FoosController < BarEngine::BarsController 
    

    * Vì hầu hết bộ điều khiển của động cơ kế thừa từ ApplicationController, kế thừa này vẫn cho phép bạn sử dụng những thứ của riêng bạn từ ApplicationController, không có tác dụng xấu.

  6. Nếu tất cả những điều trên không thể thực hiện, tôi có thể cố gắng phân phát tùy chỉnh tại địa phương hoặc từ repo github của tôi.

Kết luận, ở trên có thể giải quyết hầu hết các trường hợp và bản thân tôi thích số 5 khi có thể và cần thiết.

+2

cảm ơn cho câu trả lời nhưng tôi đã không thực sự có nghĩa là để bắt đầu một chủ đề về đường ray. Bằng cách này, tôi cũng thích 5. Khi bạn chỉ ra 'hầu hết' bộ điều khiển động cơ (xem Devise) kế thừa từ 'ApplicationController' nhưng' Tolk :: ApplicationController' (mà tôi đề cập ở trên) thì không. –

3

Tôi thực sự vui với Ruby 2.1 (và sau này) phạm vi cấp độ "riêng tư" cấp độ tinh lọc. Ví dụ của tôi ở trên có thể được lặp lại là:

# spec/modulify_spec.rb 
module Modulify 
    refine(Class) do 
    def include_refined(klass) 
     _refined = Module.new do 
     include refine(klass) { yield if block_given? } 
     end 
     include _refined 
    end 
    end 
end 

class A 
    def a 
    "I am an 'a'" 
    end 
end 

class B 
    using Modulify 

    include_refined(A) do 
    def a 
     super + " and not a 'b'" 
    end 
    end 

    def b 
    "I cannot say: " + a 
    end 
end 

RSpec.describe B do 
    it "can use refined methods from A" do 
    expect(subject.b).to eq "I cannot say: I am an 'a' and not a 'b'" 
    end 
end 

và phù hợp với giải pháp cho vấn đề ban đầu.

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