2012-03-07 27 views
14

trong Ruby tôi có thể tự động điền các biến mẫu bằng cách nào đó trong phương thức khởi tạo không?trong Ruby tôi có thể tự động điền các biến mẫu bằng cách nào đó trong phương thức khởi tạo không?

Ví dụ nếu tôi có:

class Weekend 
    attr_accessor :start_date, :end_date, :title, :description, :location 

    def initialize(params) 
    # SOMETHING HERE TO AUTO POPULATE INSTANCE VARIABLES WITH APPROPRIATE PARAMS 
    end 

end 

Trả lời

14

Bạn có thể sử dụng instance_variable_set như thế này:

params.each do |key, value| 
    self.instance_variable_set("@#{key}".to_sym, value) 
end 
6

Để giữ cho mọi thứ đơn giản:

class Weekend 
    attr_accessor :start_date, :end_date, :title, :description, :location 

    def initialize(params) 
  @start_date = params[:start_date] # I don't really know the structure of params but you have the idea 
    @end_date = params[:end_date] 
    end 
end 

Bạn có thể làm điều gì đó thông minh hơn với một twist của Lập trình meta nhưng điều này thực sự cần thiết?

+0

Tôi ghét trả lời từ iphone và xem đánh dấu hư hỏng ... – apneadiving

+2

Tôi hiểu mong muốn tránh metaprog không cần thiết, nhưng điều này không thực sự là mã ngắn gọn mà OP yêu cầu. Bạn phải chỉ định thủ công từng tên trường. – Kelvin

2

Tôi đề nghị

class Weekend 
    @@available_attributes = [:start_date, :end_date, :title, :description, :location] 
    attr_accessor *@@available_attributes 

    def initialize(params) 
    params.each do |key,value| 
     self.send(:"#{key}=",value) if @@available_attributes.include?(key.to_sym) 
    end 
    end 
end 
+0

Làm thế nào về hằng số 'AVAILABLE_ATTRIBUTES' thay vì một biến lớp? – jhirsch

1

Ruby có thể là điều đáng sợ đơn giản đôi khi. Không có vòng lặp!

class Weekend < Struct.new(:start_date, :end_date, :title, :description, :location) 
    # params: Hash with symbols as keys 
    def initialize(params) 
    # arg splatting to the rescue 
    super(* params.values_at(* self.class.members)) 
    end 
end 

Lưu ý rằng bạn thậm chí không cần phải sử dụng kế thừa - một mới Struct thể được tùy chỉnh trong quá trình tạo:

Weekend = Struct.new(:start_date, :end_date, :title, :description, :location) do 
    def initialize(params) 
    # same as above 
    end 
end 

Test:

weekend = Weekend.new(
    :start_date => 'start_date value', 
    :end_date => 'end_date value', 
    :title => 'title value', 
    :description => 'description value', 
    :location => 'location value' 
) 

p [:start_date , weekend.start_date ] 
p [:end_date , weekend.end_date ] 
p [:title  , weekend.title  ] 
p [:description, weekend.description ] 
p [:location , weekend.location ] 

Lưu ý rằng đây không thực sự đặt các biến mẫu. Bạn lớp học sẽ có getters opaque và setters. Nếu bạn không muốn phơi bày chúng, bạn có thể quấn thêm một lớp khác xung quanh nó. Dưới đây là một ví dụ:

# this gives you more control over readers/writers 
require 'forwardable' 
class Weekend 
    MyStruct = ::Struct.new(:start_date, :end_date, :title, :description, :location) 
    extend Forwardable 
    # only set up readers 
    def_delegators :@struct, *MyStruct.members 

    # params: Hash with symbols as keys 
    def initialize(params) 
    # arg splatting to the rescue 
    @struct = MyStruct.new(* params.values_at(* MyStruct.members)) 
    end 
end 
+0

thx. đây có phải là cách làm ruby ​​thông thường không? – BKSpurgeon

+0

@BKSpurgeon Tôi không biết mức độ phổ biến của nó. Nếu bạn dự định sử dụng nó trong một dự án nhóm, tôi đề nghị hỏi nhóm xem họ có hài lòng với nó hay không. – Kelvin

2

Tôi nghĩ rằng bạn chỉ có thể đặt:

Weekend < Struct.new(:start_date, :end_date, :title, :description, :location) 

Và sau đó thêm bất cứ điều gì khác để lớp cuối tuần với:

class Weekend 
#whatever you need to add here 
end 
+1

Tôi đã trở lại để trả lời câu hỏi này tôi đã thấy hai năm trước đây chỉ để tìm một người đưa ra câu trả lời tôi đã có trong tâm trí một năm trước đây. (nhưng tôi thích 'lớp cuối tuần nurettin

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