রুবিতে এনামস কীভাবে প্রয়োগ করবেন?


323

রুবিতে এনাম আইডিয়াম বাস্তবায়নের সর্বোত্তম উপায় কী? আমি এমন কিছু সন্ধান করছি যা আমি জাভা / সি # এনামগুলির মতো (প্রায়) ব্যবহার করতে পারি।


7
@ ওরামো, ভাল প্রশ্ন এবং সেরা উত্তরের জন্য দুর্দান্ত পছন্দ। এটি পছন্দ করুন বা ঘৃণা করুন, আপনি কোনও টাইপ-সুরক্ষা এবং (কমপক্ষে রুবিতে) কোনও টাইপ-সুরক্ষা পাবেন না। আমি যখন সি # তে এবং পরে জাভাতে এনামগুলি আবিষ্কার করলাম তখন আমি শিহরিত হয়েছিলাম (কোনও মান বাছাই করুন, তবে এগুলি থেকে!), রুবি কোনও অবস্থাতেই এটি করার কোনও সত্যিকারের উপায় সরবরাহ করে না।
ড্যান রোজনস্টার্ক

2
এই প্রশ্নটির সাথে সমস্যাটি হল জাভা এবং সি # এনামগুলি নাটকীয়ভাবে আলাদা জিনিস। একটি জাভা এনাম সদস্য একটি অবজেক্ট উদাহরণ এবং একটি সিঙ্গলটন। একটি জাভা এনামের কনস্ট্রাক্টর থাকতে পারে। বিপরীতে, সি # এনামগুলি আদিম মানগুলির ভিত্তিতে তৈরি। প্রশ্নকারী কোন আচরণের সন্ধান করছে? যদিও এটি সম্ভবত সি # কেস চাওয়া হয়েছে, জাভা স্পষ্টভাবে সি বা সি ++ এর পরিবর্তে উল্লেখ করা হয়েছে, তাই কিছুটা সন্দেহ রয়েছে। যেমন পরামর্শ দেওয়া যায় যে রুবিতে 'নিরাপদ' হওয়ার কোনও উপায় নেই, এটি স্বচ্ছভাবে মিথ্যা, তবে আপনাকে আরও পরিশীলিত কিছু প্রয়োগ করতে হবে।
ব্যবহারকারী 1164178

উত্তর:


317

দুটি উপায়. প্রতীক ( :fooস্বরলিপি) বা ধ্রুবক ( FOOস্বরলিপি)।

আপনি যখন আক্ষরিক স্ট্রিং সহ লিটার কোড ছাড়াই পঠনযোগ্যতা বাড়াতে চান সিম্বলগুলি উপযুক্ত।

postal_code[:minnesota] = "MN"
postal_code[:new_york] = "NY"

গুরুত্বপূর্ণ যখন আপনার অন্তর্নিহিত মান থাকে তখন ধ্রুবকগুলি উপযুক্ত। কেবল আপনার ধ্রুবককে ধরে রাখতে একটি মডিউল ঘোষণা করুন এবং তারপরে স্থিরদের ঘোষণা করুন।

module Foo
  BAR = 1
  BAZ = 2
  BIZ = 4
end

flags = Foo::BAR | Foo::BAZ # flags = 3

2
এই এনামগুলি খুব বেশি ডাটাবেসে সংরক্ষণ করা হলে কী হবে? প্রতীক স্বরলিপি কাজ করবে? আমি সন্দেহ করি ...
ফ্যাং এনগুইন

আমি যদি কোনও ডাটাবেসে সঞ্চয় করে থাকি তবে আমি ধ্রুবকগুলির ব্যবহার করব would অবশ্যই তখন আপনাকে ডিবি থেকে তথ্য বের করে আনার সময় কিছু ধরণের অনুসন্ধান করতে হবে। :minnesota.to_sচিহ্নের স্ট্রিং সংস্করণটি সংরক্ষণ করতে কোনও ডাটাবেসে সংরক্ষণ করার সময় আপনি এমন কিছু ব্যবহার করতে পারেন । রেলস, আমি বিশ্বাস করি, এর কয়েকটি মোকাবিলার জন্য কিছু সহায়ক পদ্ধতি রয়েছে।
mlibby

7
গ্রুপ মীমাংসার চেয়ে মডিউলটি কী ভাল হবে না - কারণ আপনি এটির কোনও উদাহরণ তৈরি করছেন না?
থমথম

3
শুধু একটি মন্তব্য। নামগুলির কনভেনশন সম্পর্কে রুবি কিছুটা ব্যথা করছেন তবে যতক্ষণ না আপনি সেগুলির উপরে ভ্রমণ করেন ততক্ষণ এগুলি সম্পর্কে সত্যই স্পষ্ট নয়। এনামগুলির নামগুলি অবশ্যই সমস্ত ক্যাপ থাকতে হবে এবং মডিউলটি ধ্রুবকের একটি মডিউল তা জানতে রুবীর জন্য মডিউল নামের প্রথম অক্ষরটি মূলধন করা উচিত।
রোকুজোলাদি

3
সম্পূর্ণ সত্য নয়। ধ্রুবকের প্রথম অক্ষর অবশ্যই মূলধন করা উচিত, তবে সমস্ত অক্ষর হওয়ার দরকার নেই। এটি সম্মেলনের পছন্দের বিষয়। উদাহরণস্বরূপ, সমস্ত মডিউল নাম এবং শ্রেণীর নামগুলি আসলে খুব ধ্রুবক।
মাইকেল ব্রাউন

59

আমি অবাক হয়েছি যে কেউ নিম্নলিখিতগুলির মতো কিছু সরবরাহ করেনি ( আরএপিআই রত্ন থেকে কাটা ):

class Enum

  private

  def self.enum_attr(name, num)
    name = name.to_s

    define_method(name + '?') do
      @attrs & num != 0
    end

    define_method(name + '=') do |set|
      if set
        @attrs |= num
      else
        @attrs &= ~num
      end
    end
  end

  public

  def initialize(attrs = 0)
    @attrs = attrs
  end

  def to_i
    @attrs
  end
end

যা এর মতো ব্যবহার করা যেতে পারে:

class FileAttributes < Enum
  enum_attr :readonly,       0x0001
  enum_attr :hidden,         0x0002
  enum_attr :system,         0x0004
  enum_attr :directory,      0x0010
  enum_attr :archive,        0x0020
  enum_attr :in_rom,         0x0040
  enum_attr :normal,         0x0080
  enum_attr :temporary,      0x0100
  enum_attr :sparse,         0x0200
  enum_attr :reparse_point,  0x0400
  enum_attr :compressed,     0x0800
  enum_attr :rom_module,     0x2000
end

উদাহরণ:

>> example = FileAttributes.new(3)
=> #<FileAttributes:0x629d90 @attrs=3>
>> example.readonly?
=> true
>> example.hidden?
=> true
>> example.system?
=> false
>> example.system = true
=> true
>> example.system?
=> true
>> example.to_i
=> 7

এটি ডাটাবেস পরিস্থিতিতে, বা সি স্টাইলের ধ্রুবক / এনামগুলির সাথে ডিল করার সময় ( এফএফআই ব্যবহার করার ক্ষেত্রে যেমনটি হয় , যা আরএপিআই এর ব্যাপক ব্যবহার করে) well

এছাড়াও, আপনাকে টাইপগুলি সম্পর্কে নীরব ব্যর্থতা তৈরির বিষয়ে চিন্তা করতে হবে না, যেমন আপনি হ্যাশ-টাইপ সমাধান ব্যবহার করে যাচ্ছেন।


1
এই নির্দিষ্ট সমস্যাটি সমাধান করার জন্য এটি দুর্দান্ত উপায়, তবে যে কারণে কেউ এটির পরামর্শ দেয়নি সম্ভবত এটি সত্য যে এটি # সি / জাভা এনামের মতো নয় তার সাথে সম্পর্কযুক্ত।
mlibby

1
এটি কিছুটা অসম্পূর্ণ, তবে কীভাবে আপনি গতিশীল পদ্ধতির সাহায্যে সমাধানগুলি বাস্তবায়িত করতে পারেন সে বিষয়ে দুর্দান্ত ইঙ্গিত দেয়। এটি ফ্ল্যাগস্যাট্রিবিউট সেটের সাথে সি # এনমের সাথে কিছু সাদৃশ্য বহন করে, তবে উপরে প্রতীক / ধ্রুবক ভিত্তিক সমাধানগুলির মতো এটি অনেকেরই একটি উত্তর। সমস্যাটি হ'ল মূল প্রশ্নটি, যা এর উদ্দেশ্যতে জঞ্জাল হয়েছে (সি # এবং জাভা বিনিময়যোগ্য নয়)। রুবিতে অবজেক্টগুলিকে আইটেমাইজ করার অনেকগুলি উপায় রয়েছে; ডানটি নির্বাচন করা সমস্যার সমাধানের উপর নির্ভর করে। আপনার প্রয়োজন হয় না স্ল্যাশলিপি বৈশিষ্ট্যগুলি অনুলিপি করা ভুল পথে চালিত। সঠিক উত্তরটি প্রসঙ্গে নির্ভর করতে হবে।
ব্যবহারকারী 1164178

52

এটি করার সর্বাধিক অভিহিত পদ্ধতি হ'ল প্রতীকগুলি ব্যবহার করা। উদাহরণস্বরূপ, পরিবর্তে:

enum {
  FOO,
  BAR,
  BAZ
}

myFunc(FOO);

... আপনি কেবল প্রতীক ব্যবহার করতে পারেন:

# You don't actually need to declare these, of course--this is
# just to show you what symbols look like.
:foo
:bar
:baz

my_func(:foo)

এটি এনামগুলির তুলনায় কিছুটা বেশি উন্মুক্ত, তবে এটি রুবি স্পিরিটের সাথে ভাল মানায়।

প্রতীকগুলিও খুব ভাল পারফর্ম করে। সমতার জন্য দুটি চিহ্নের তুলনা করা, উদাহরণস্বরূপ, দুটি স্ট্রিং তুলনা করার চেয়ে অনেক দ্রুত।


107
সুতরাং রুবি
স্পিরিটিটি

82
জনপ্রিয় রুবি ফ্রেমওয়ার্কগুলি রানটাইম রূপকগুলিতে প্রচুর পরিমাণে নির্ভর করে এবং অত্যধিক লোড-টাইম চেকিং করা রুবির বেশিরভাগ অভিব্যক্তিপূর্ণ শক্তি হরণ করে। সমস্যাগুলি এড়াতে, বেশিরভাগ রুবি প্রোগ্রামাররা পরীক্ষা-চালিত ডিজাইনের অনুশীলন করে, যা কেবল টাইপসগুলিতেই নয়, যুক্তির ত্রুটিগুলিও খুঁজে পেতে পারে।
এমএম

10
@ ইয়ার: ঠিক আছে, ভাষা ডিজাইন হ'ল ট্রেড অফস এবং ভাষা বৈশিষ্ট্যগুলি ইন্টারঅ্যাক্ট করে। আপনি যদি একটি ভাল, অত্যন্ত গতিশীল ভাষা চান তবে রুবির সাথে যান, প্রথমে আপনার ইউনিট পরীক্ষা লিখুন এবং ভাষার চেতনার সাথে যান। :-) যদি আপনি এটি সন্ধান করেন না তবে সেখানে কয়েক ডজন অন্যান্য দুর্দান্ত ভাষা রয়েছে, যার মধ্যে প্রতিটি আলাদা আলাদা বাণিজ্য করে।
ইমক

10
@ এমকে, আমি একমত, তবে আমার ব্যক্তিগত বিষয়টি হ'ল আমি রুবিতে বেশ স্বাচ্ছন্দ্য বোধ করি, তবে আমি রুবিতে রিফ্যাক্টরিং করতে স্বাচ্ছন্দ্য বোধ করি না। এবং এখন যেহেতু আমি ইউনিট পরীক্ষা লিখতে শুরু করেছি (শেষ অবধি), আমি বুঝতে পারি যে সেগুলি কোনও চঞ্চল নয়: আমার অনুমান 1) যে রুবি কোডটি প্রচুর পরিমাণে রিফ্যাক্টর হয় না যে অনুশীলনে এবং 2) রুবি শেষ নয় গতিশীল ভাষার ক্ষেত্রে লাইনটি, স্পষ্টভাবে কারণ এটি স্বয়ংক্রিয়ভাবে রিফ্যাক্টর করা শক্ত। আমার প্রশ্নটি দেখুন 2317579 যা আশ্চর্যজনকভাবে, ছোট্ট লোকেরা দ্বারা গ্রহণ করা হয়েছিল
ড্যান রোজনস্টার্ক

4
হ্যাঁ, তবে এই স্ট্রিংগুলি ব্যবহার করা # সি ভাষার ভাষায় থাকবে না, এটি কেবল একটি খারাপ অভ্যাস।
এড এস

38

আমি নিম্নলিখিত পদ্ধতির ব্যবহার:

class MyClass
  MY_ENUM = [MY_VALUE_1 = 'value1', MY_VALUE_2 = 'value2']
end

আমি নিম্নলিখিত সুবিধার জন্য এটি পছন্দ:

  1. এটি সম্পূর্ণরূপে দৃষ্টিভঙ্গিগুলিকে গ্রুপ করে
  2. এটি কিছু সংকলন-সময় যাচাই করে (কেবলমাত্র প্রতীক ব্যবহারের বিপরীতে)
  3. আমি সহজেই সমস্ত সম্ভাব্য মানগুলির তালিকাটি অ্যাক্সেস করতে পারি: ঠিক MY_ENUM
  4. আমি সহজেই স্বতন্ত্র মানগুলি অ্যাক্সেস করতে পারি: MY_VALUE_1
  5. এটিতে কেবল কোনও প্রতীক নয়, কোনও ধরণের মান থাকতে পারে

প্রতীকসমূহ ভাল হতে পারে আপনি, বাইরের ক্লাসের নাম লিখে যদি আপনি অন্য ক্লাসে ব্যবহার করছেন না কারণ ( MyClass::MY_VALUE_1)


4
আমি মনে করি এটিই সেরা উত্তর। কার্যকারিতা, বাক্য গঠন এবং ন্যূনতম কোড ওভারহেড জাভা / সি # এর নিকটে আসে। এছাড়াও আপনি সংজ্ঞাগুলিকে এক স্তরের থেকেও গভীরতর করতে পারেন এবং মাইক্লাস :: MY_ENUM.flatten সহ সমস্ত মান পুনরুদ্ধার করতে পারেন। পার্শ্ব নোট হিসাবে আমি এখানে বড় হাতের নামগুলি ব্যবহার করব যেমনটি রুবীর ধ্রুবকগুলির মান। মাইক্লাস :: একটি সাবক্লাসের রেফারেন্সের জন্য মাইএনাম ভুল হতে পারে।
জানোশ

@ জানোশ, আমি নামগুলি আপডেট করেছি। পরামর্শের জন্য ধন্যবাদ
আলেক্সি

আমি এখনও কিছুটা বিভ্রান্ত, এবং লিঙ্কটি 410'd (না, 404 নয়)। এই এনামটি কীভাবে ব্যবহৃত হবে আপনি উদাহরণ দিতে পারেন?
শেলভাকু

17

আপনি যদি 4.2 বা ততোধিক রেল ব্যবহার করেন তবে আপনি রেল এনামগুলি ব্যবহার করতে পারেন।

আর কোনও রত্ন অন্তর্ভুক্ত না করেই এখন কারাগুলিতে ডিফল্টভাবে এনাম রয়েছে।

এটি জাভা, সি ++ এনমগুলির সাথে খুব অনুরূপ (এবং আরও বৈশিষ্ট্যযুক্ত) is

Http://edgeapi.rubyonrails.org/class/ActiveRecord/Enum.html থেকে উদ্ধৃত :

class Conversation < ActiveRecord::Base
  enum status: [ :active, :archived ]
end

# conversation.update! status: 0
conversation.active!
conversation.active? # => true
conversation.status  # => "active"

# conversation.update! status: 1
conversation.archived!
conversation.archived? # => true
conversation.status    # => "archived"

# conversation.update! status: 1
conversation.status = "archived"

# conversation.update! status: nil
conversation.status = nil
conversation.status.nil? # => true
conversation.status      # => nil

7
যেমনটি আপনি বলেছেন - দরকারী নয় যদি ওপি রেলগুলি ব্যবহার না করে (বা আরও সঠিকভাবে অবজেক্টটি অ্যাক্টিভেকর্ডের নয়)। আমার ডাউনভোটকে কেবল ব্যাখ্যা করা সবই।
জের

2
এগুলি রুবিতে এনাম নয়, এটি আপনার ডাটাবেসে এনামসের একটি অ্যাক্টিভেকর্ড ইন্টারফেস। কোনও সাধারণীকরণযোগ্য সমাধান নয় যা অন্য কোনও ব্যবহারের ক্ষেত্রে প্রয়োগ করা যেতে পারে।
অ্যাডাম লাসেক

আমি আমার উত্তরে এটি উল্লেখ করেছি।
13:38

এটিই সেরা উত্তর আইএফএফ, রেলগুলি ব্যবহার করে।
TheUiderSide

আমি এটি পছন্দ করি না কারণ এটি অবশ্যই একটি রেল ডাটাবেসে (কাজ করার জন্য) সংরক্ষণ করা উচিত এবং কারণ এটি Conversationবর্গের অনেকগুলি উদাহরণ তৈরি করতে দেয় - আমি বিশ্বাস করি এটি অবশ্যই 1 টি উদাহরণের অনুমতি দেবে।
অগ্রগতি

8

এটি রুবিতে এনামগুলিতে আমার দৃষ্টিভঙ্গি। আমি সংক্ষিপ্ত এবং মিষ্টি জন্য যাচ্ছি, অগত্যা সর্বাধিক সি পছন্দ মত। কোন চিন্তা?

module Kernel
  def enum(values)
    Module.new do |mod|
      values.each_with_index{ |v,i| mod.const_set(v.to_s.capitalize, 2**i) }

      def mod.inspect
        "#{self.name} {#{self.constants.join(', ')}}"
      end
    end
  end
end

States = enum %w(Draft Published Trashed)
=> States {Draft, Published, Trashed} 

States::Draft
=> 1

States::Published
=> 2

States::Trashed
=> 4

States::Draft | States::Trashed
=> 3


8

সম্ভবত সবচেয়ে ভাল লাইটওয়েট পদ্ধতির হবে

module MyConstants
  ABC = Class.new
  DEF = Class.new
  GHI = Class.new
end

এইভাবে মানগুলি জাভা / সি # এর মতো নাম যুক্ত করে:

MyConstants::ABC
=> MyConstants::ABC

সমস্ত মান পেতে, আপনি করতে পারেন

MyConstants.constants
=> [:ABC, :DEF, :GHI] 

আপনি যদি এনামের অর্ডিনাল মান চান তবে আপনি এটি করতে পারেন

MyConstants.constants.index :GHI
=> 2

1
আইএমএইচও এটি খুব ঘনিষ্ঠভাবে জাভা থেকে ব্যবহার এবং উদ্দেশ্য (প্রকারের সুরক্ষা) এর প্রতিলিপি তৈরি করে, এছাড়াও পছন্দ হিসাবে বিবেচনা করে ধ্রুবকগুলি এর মতো সংজ্ঞায়িত করা যায়:class ABC; end
উইক

8

আমি জানি লোকটি এই প্রশ্নটি পোস্ট করার পরে অনেক দিন হয়েছে, তবে আমার একই প্রশ্ন ছিল এবং এই পোস্টটি আমাকে উত্তর দেয়নি। সংখ্যাটি কী উপস্থাপন করে, সহজ তুলনা করা যায় এবং এনামকে উপস্থাপনকারী কলামটি অনুসন্ধানের জন্য বেশিরভাগ অ্যাক্টিভেকর্ড সমর্থনটি দেখার জন্য আমি একটি সহজ উপায় চেয়েছিলাম।

আমি কিছুই পেলাম না, তাই আমি ইয়িনুম নামে একটি দুর্দান্ত বাস্তবায়ন করেছি যা আমার সন্ধানের জন্য সমস্ত কিছু অনুমতি দিয়েছে। টন চশমা তৈরি, তাই আমি নিশ্চিত এটি নিরাপদ।

কিছু উদাহরণ বৈশিষ্ট্য:

COLORS = Enum.new(:COLORS, :red => 1, :green => 2, :blue => 3)
=> COLORS(:red => 1, :green => 2, :blue => 3)
COLORS.red == 1 && COLORS.red == :red
=> true

class Car < ActiveRecord::Base    
  attr_enum :color, :COLORS, :red => 1, :black => 2
end
car = Car.new
car.color = :red / "red" / 1 / "1"
car.color
=> Car::COLORS.red
car.color.black?
=> false
Car.red.to_sql
=> "SELECT `cars`.* FROM `cars` WHERE `cars`.`color` = 1"
Car.last.red?
=> true

5

আপনি যদি চিহ্নগুলির সাথে টাইপগুলি নিয়ে উদ্বিগ্ন হন তবে নিশ্চিত হন যে আপনি অ-অস্তিত্ব কী দিয়ে কোনও মান অ্যাক্সেস করার সময় আপনার কোড একটি ব্যতিক্রম উত্থাপন করেছে। আপনি এটির fetchপরিবর্তে এটি ব্যবহার করে করতে পারেন []:

my_value = my_hash.fetch(:key)

বা হ্যাশটিকে ডিফল্টরূপে ব্যতিক্রম বাড়িয়ে যদি আপনি একটি অস্তিত্ব কী সরবরাহ করেন:

my_hash = Hash.new do |hash, key|
  raise "You tried to access using #{key.inspect} when the only keys we have are #{hash.keys.inspect}"
end

যদি হ্যাশটি ইতিমধ্যে বিদ্যমান থাকে তবে আপনি ব্যতিক্রম উত্থাপনের আচরণটি যুক্ত করতে পারেন:

my_hash = Hash[[[1,2]]]
my_hash.default_proc = proc do |hash, key|
  raise "You tried to access using #{key.inspect} when the only keys we have are #{hash.keys.inspect}"
end

সাধারণত, আপনাকে ধ্রুবকগুলির সাথে টাইপোর সুরক্ষার বিষয়ে চিন্তা করতে হবে না। যদি আপনি একটি স্থির নাম ভুল বানান করে থাকেন তবে এটি সাধারণত একটি ব্যতিক্রম বাড়ে।


দেখে মনে হচ্ছে আপনি এতগুলি স্পষ্ট করে কিছু না বলে হ্যাশগুলি দিয়ে এমুলেশনগুলি অনুকরণ করার পক্ষে পরামর্শ দিচ্ছেন । এটি বলার জন্য আপনার উত্তরটি সম্পাদনা করা ভাল ধারণা হতে পারে। : (আমি বর্তমানে রুবি মধ্যে enums ভালো কিছু জন্য প্রয়োজন আছে, এবং তা সমাধানে আমার প্রথম পদ্ধতির হ্যাশ ব্যবহার করা FOO_VALUES = {missing: 0, something: 1, something_else: 2, ...}এই সংজ্ঞায়িত কী প্রতীক। missing, somethingইত্যাদি, এবং এছাড়াও তাদের যুক্ত মান মাধ্যমে তুলনীয় তোলে।)
Teemu লইস্তি

আমি বলতে চাইছি, উত্তরের একেবারে শুরুতে না বলে।
টিমু লেইস্তি

4

কেউ এগিয়ে গিয়ে রেনুম নামে একটি রুবি রত্ন লিখেছিল । এটি আচরণের মতো নিকটতম জাভা / সি # পাওয়ার দাবি করেছে। ব্যক্তিগতভাবে আমি এখনও রুবি শিখছি, এবং যখন আমি একটি নির্দিষ্ট শ্রেণীর একটি স্ট্যাটিক এনাম, সম্ভবত একটি হ্যাশ তৈরি করতে চেয়েছিলাম তখন গুগলের মাধ্যমে এটি ঠিক খুঁজে পাওয়া যায় নি।


আমার কখনও রুবিতে এনামের দরকার নেই। প্রতীক এবং ধ্রুবকগুলি মূio় এবং একই সমস্যাগুলি সমাধান করে, তাই না?
চাক

সম্ভবত চক; তবে রুবিতে এনামের জন্য গুগল করা আপনাকে এতদূর পাবে না। এটি আপনাকে সরাসরি সমতুল্য ব্যক্তিদের সর্বোত্তম প্রয়াসের ফলাফল প্রদর্শন করবে। যা আমাকে অবাক করে তোলে, ধারণাটি একসাথে জড়িয়ে রাখার বিষয়ে খুব সুন্দর কিছু আছে।
dlamblin 1

@ চক চিহ্ন এবং ধ্রুবকগুলি প্রয়োগ করে না, উদাহরণস্বরূপ, একটি মান একটি ছোট মানগুলির একটি হতে হবে।
ডেভিড মোলস

3

এটি আপনি জাভা বা সি # এনামগুলি কীভাবে ব্যবহার করেন তা নির্ভর করে। আপনি এটি কীভাবে ব্যবহার করবেন তা সমাধানের জন্য আপনি রুবি বেছে নেবেন।

Setউদাহরণস্বরূপ নেটিভ প্রকারটি ব্যবহার করে দেখুন:

>> enum = Set['a', 'b', 'c']
=> #<Set: {"a", "b", "c"}>
>> enum.member? "b"
=> true
>> enum.member? "d"
=> false
>> enum.add? "b"
=> nil
>> enum.add? "d"
=> #<Set: {"a", "b", "c", "d"}>

9
প্রতীক ব্যবহার করবেন না কেন Set[:a, :b, :c]?
ড্যান রোজনস্টার্ক

2
আইএমও, এখানে প্রতীক ব্যবহার করার জন্য আরও ভাল অনুশীলন।
কলিন কবরগুলি

3

সম্প্রতি আমরা একটি রত্ন প্রকাশ করেছি যা রুবিতে এনামগুলি প্রয়োগ করে । আমার পোস্টে আপনি আপনার প্রশ্নের উত্তর পাবেন। এছাড়াও আমি সেখানে বর্ণনা করেছি যে কেন আমাদের বাস্তবায়ন বিদ্যমানগুলির তুলনায় ভাল (প্রকৃতপক্ষে রবিতে এই বৈশিষ্ট্যের অনেকগুলি বাস্তব রূপ এখনও রয়েছে)।


এটি স্বতঃবৃদ্ধিকরণের মানগুলিকে স্পষ্টভাবে উল্লেখ না করে অনুমতি দেয়। +1
বিকৃত করুন

3

আর একটি সমাধান ওপেনস্ট্রাক্ট ব্যবহার করছে। এটি বেশ সোজা এগিয়ে এবং পরিষ্কার।

https://ruby-doc.org/stdlib-2.3.1/libdoc/ostruct/rdoc/OpenStruct.html

উদাহরণ:

# bar.rb
require 'ostruct' # not needed when using Rails

# by patching Array you have a simple way of creating a ENUM-style
class Array
   def to_enum(base=0)
      OpenStruct.new(map.with_index(base).to_h)
   end
end

class Bar

    MY_ENUM = OpenStruct.new(ONE: 1, TWO: 2, THREE: 3)
    MY_ENUM2 = %w[ONE TWO THREE].to_enum

    def use_enum (value)
        case value
        when MY_ENUM.ONE
            puts "Hello, this is ENUM 1"
        when MY_ENUM.TWO
            puts "Hello, this is ENUM 2"
        when MY_ENUM.THREE
            puts "Hello, this is ENUM 3"
        else
            puts "#{value} not found in ENUM"
        end
    end

end

# usage
foo = Bar.new    
foo.use_enum 1
foo.use_enum 2
foo.use_enum 9


# put this code in a file 'bar.rb', start IRB and type: load 'bar.rb'

2

প্রতীকগুলি হ'ল রুবি উপায়। তবে, কখনও কখনও কিছু সি কোড বা কিছু বা জাভার সাথে কথা বলা দরকার যা বিভিন্ন জিনিসের জন্য কিছু এনামকে প্রকাশ করে।


#server_roles.rb
module EnumLike

  def EnumLike.server_role
    server_Symb=[ :SERVER_CLOUD, :SERVER_DESKTOP, :SERVER_WORKSTATION]
    server_Enum=Hash.new
    i=0
    server_Symb.each{ |e| server_Enum[e]=i; i +=1}
    return server_Symb,server_Enum
  end

end

এটি এর পরে এটি ব্যবহার করা যেতে পারে


require 'server_roles'

sSymb, sEnum =EnumLike.server_role()

foreignvec[sEnum[:SERVER_WORKSTATION]]=8

এটি অবশ্যই বিমূর্ত করা যেতে পারে এবং আপনি আমাদের নিজস্ব এনুম ক্লাস রোল করতে পারেন


আপনি server_Symbকোনও নির্দিষ্ট কারণে ভেরিয়েবলগুলিতে দ্বিতীয় শব্দটি মূলধন করছেন (উদাহরণস্বরূপ )? নির্দিষ্ট কারণ না থাকলে এটি ভেরিয়েবলগুলি হওয়ার snake_case_with_all_lower_caseজন্য এবং প্রতীকগুলির জন্য মূ .় :lower_case
অ্যান্ড্রু গ্রিম

1
@Andrew; এই উদাহরণটি একটি বাস্তব বিশ্বের জিনিস থেকে নেওয়া হয়েছিল এবং নেটওয়ার্ক প্রোটোকল ডকুমেন্টেশন xxx_Yyy ব্যবহৃত হয়েছিল, তাই বেশ কয়েকটি ভাষায় কোড একই ধারণাটি ব্যবহার করেছিল যাতে কেউ নির্দিষ্টকরণের পরিবর্তনগুলি অনুসরণ করতে পারে।
জোনকে

1
কোড golfing: server_Symb.each_with_index { |e,i| server_Enum[e] = i}। দরকার নেই i = 0
অ্যান্ড্রু গ্রিম 21

2

আমি enums বাস্তবায়ন করেছি

module EnumType

  def self.find_by_id id
    if id.instance_of? String
      id = id.to_i
    end 
    values.each do |type|
      if id == type.id
        return type
      end
    end
    nil
  end

  def self.values
    [@ENUM_1, @ENUM_2] 
  end

  class Enum
    attr_reader :id, :label

    def initialize id, label
      @id = id
      @label = label
    end
  end

  @ENUM_1 = Enum.new(1, "first")
  @ENUM_2 = Enum.new(2, "second")

end

তারপরে অপারেশন করা সহজ

EnumType.ENUM_1.label

...

enum = EnumType.find_by_id 1

...

valueArray = EnumType.values

2

এটি কিছুটা অতিরিক্ত অতিরিক্ত মনে হয়, তবে এটি এমন একটি পদ্ধতি যা আমি কয়েকবার ব্যবহার করেছি, বিশেষত যেখানে আমি এক্সএমএল বা এর মতো কিছু সংহত করছি।

#model
class Profession
  def self.pro_enum
    {:BAKER => 0, 
     :MANAGER => 1, 
     :FIREMAN => 2, 
     :DEV => 3, 
     :VAL => ["BAKER", "MANAGER", "FIREMAN", "DEV"]
    }
  end
end

Profession.pro_enum[:DEV]      #=>3
Profession.pro_enum[:VAL][1]   #=>MANAGER

এটি আমাকে AC # এনুমের কঠোরতা দেয় এবং এটি মডেলের সাথে যুক্ত।


আমি এই পদ্ধতির পরামর্শ না কারণ এটি আপনি নিজে মান সেটিং এবং আপনি এ আদেশ সঠিক নিশ্চিত উপর নির্ভর :VAL। অ্যারে দিয়ে শুরু করা এবং হ্যাশটি ব্যবহার করে তৈরি করা ভাল হবে.map.with_index
ডেভমঙ্গুজ

1
সঠিক পয়েন্টটি নিজেকে এমন একটি মানকে বেঁধে রাখছে যা তৃতীয় পক্ষগুলি দ্বারা নির্ধারিত হয়। এটি প্রতি সেটের এক্সটেনসিবিলিটি সম্পর্কে নয়, তবে বহিরাগত প্রতিবন্ধকতাগুলির সাথে মোকাবিলা করার বিষয়ে যা আপনার প্রক্রিয়া সীমানার মধ্যে কম্পিউটারের প্রভাবকে প্রভাবিত করে।
jjk

ন্যায্য বিন্দু! যে ক্ষেত্রে এটা স্পষ্টভাবে মান নির্দিষ্ট করার জ্ঞান করে তোলে, কিন্তু আমি সঙ্গে বিপরীত লুকআপ কি আনত করা চাই .keyবা .invertবরং একটি তুলনায় :VALকী ( stackoverflow.com/a/10989394/2208016 )
DaveMongoose

হ্যাঁ, এটি (ফিরে আপনার কাছে) একটি সুস্পষ্ট বিন্দু। আমার রুবি ছিল অবহেলিত এবং অনর্থক। ডিফ ব্যবহার keyবাinvert
jjk

1

বেশিরভাগ লোক প্রতীক ব্যবহার করে (এটি :foo_barসিনট্যাক্স)। তারা এক ধরণের অনন্য অস্বচ্ছ মান। প্রতীকগুলি কোনও এনাম-স্টাইলের ধরণের নয়, তাই তারা সি এর এনাম ধরণের সত্যিকারের বিশ্বস্ত উপস্থাপনা নয় তবে এটি এটি যতটা সুন্দর তা লাভজনক।


1
irb(main):016:0> num=[1,2,3,4]
irb(main):017:0> alph=['a','b','c','d']
irb(main):018:0> l_enum=alph.to_enum
irb(main):019:0> s_enum=num.to_enum
irb(main):020:0> loop do
irb(main):021:1* puts "#{s_enum.next} - #{l_enum.next}"
irb(main):022:1> end

আউটপুট:

1 - এ
2 - বি
3 - সি
4 - ডি


to_enumআপনি একটি enumera দেয় তোর , যেহেতু enumমধ্যে C # / জাভা অর্থে একটি enumera হয় রাজনৈতিক
DaveMongoose

1
module Status
  BAD  = 13
  GOOD = 24

  def self.to_str(status)
    for sym in self.constants
      if self.const_get(sym) == status
        return sym.to_s
      end
    end
  end

end


mystatus = Status::GOOD

puts Status::to_str(mystatus)

আউটপুট:

GOOD

1

কখনও কখনও আমার যা দরকার তা হ'ল এনামের মান আনতে এবং জাভা বিশ্বের সাথে মিল রেখে এর নামটি সনাক্ত করতে সক্ষম হওয়া।

module Enum
     def get_value(str)
       const_get(str)
     end
     def get_name(sym)
       sym.to_s.upcase
     end
 end

 class Fruits
   include Enum
   APPLE = "Delicious"
   MANGO = "Sweet"
 end

 Fruits.get_value('APPLE') #'Delicious'
 Fruits.get_value('MANGO') # 'Sweet'

 Fruits.get_name(:apple) # 'APPLE'
 Fruits.get_name(:mango) # 'MANGO'

এটি আমার কাছে এনামের উদ্দেশ্যে কাজ করে এবং এটি খুব এক্সটেনসিবল রাখে। আপনি এনাম ক্লাসে আরও পদ্ধতি যুক্ত করতে পারেন এবং সমস্ত সংজ্ঞায়িত এনামগুলিতে ভায়োলা বিনামূল্যে পান। উদাহরণ স্বরূপ. get_all_names এবং এর মতো স্টাফ।


0

আরেকটি পন্থা একটি হ্যাশ নিম্নলিখিত বর্ণনা অনুযায়ী নাম এবং মান সম্বলিত একটি রুবি বর্গ ব্যবহার করা RubyFleebie ব্লগ পোস্টে । এটি আপনাকে মান এবং ধ্রুবকের মধ্যে সহজে রূপান্তর করতে দেয় (বিশেষত যদি আপনি একটি নির্দিষ্ট মানটির জন্য নামের সন্ধানের জন্য কোনও শ্রেণিবদ্ধ পদ্ধতি যোগ করেন)।


0

আমি মনে করি প্রকারের মতো গণনা কার্যকর করার সর্বোত্তম উপায়টি প্রতীক সহকারে যেহেতু প্রায় পূর্ণসংখ্যা হিসাবে আচরণ করা হয় (যখন এটি সম্পাদন করার বিষয়টি আসে তখন অবজেক্ট_আইডি তুলনা করতে ব্যবহৃত হয়); আপনাকে সূচিকাগুলির বিষয়ে চিন্তা করার দরকার নেই এবং এগুলি আপনার কোড এক্সডি-তে খুব ঝরঝরে দেখাচ্ছে


0

ধারাবাহিক সমতা হ্যান্ডলিংয়ের সাথে একটি এনামের নকল করার আরেকটি উপায় (ডেভ থমাস থেকে নির্লজ্জভাবে গ্রহণ করা)। খোলা এনামগুলিকে (অনেক চিহ্নের মতো) এবং বন্ধ (পূর্বনির্ধারিত) এনামগুলিকে অনুমতি দেয়।

class Enum
  def self.new(values = nil)
    enum = Class.new do
      unless values
        def self.const_missing(name)
          const_set(name, new(name))
        end
      end

      def initialize(name)
        @enum_name = name
      end

      def to_s
        "#{self.class}::#@enum_name"
      end
    end

    if values
      enum.instance_eval do
        values.each { |e| const_set(e, enum.new(e)) }
      end
    end

    enum
  end
end

Genre = Enum.new %w(Gothic Metal) # creates closed enum
Architecture = Enum.new           # creates open enum

Genre::Gothic == Genre::Gothic        # => true
Genre::Gothic != Architecture::Gothic # => true

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.