রুবিতে এনাম আইডিয়াম বাস্তবায়নের সর্বোত্তম উপায় কী? আমি এমন কিছু সন্ধান করছি যা আমি জাভা / সি # এনামগুলির মতো (প্রায়) ব্যবহার করতে পারি।
রুবিতে এনাম আইডিয়াম বাস্তবায়নের সর্বোত্তম উপায় কী? আমি এমন কিছু সন্ধান করছি যা আমি জাভা / সি # এনামগুলির মতো (প্রায়) ব্যবহার করতে পারি।
উত্তর:
দুটি উপায়. প্রতীক ( :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
:minnesota.to_s
চিহ্নের স্ট্রিং সংস্করণটি সংরক্ষণ করতে কোনও ডাটাবেসে সংরক্ষণ করার সময় আপনি এমন কিছু ব্যবহার করতে পারেন । রেলস, আমি বিশ্বাস করি, এর কয়েকটি মোকাবিলার জন্য কিছু সহায়ক পদ্ধতি রয়েছে।
আমি অবাক হয়েছি যে কেউ নিম্নলিখিতগুলির মতো কিছু সরবরাহ করেনি ( আরএপিআই রত্ন থেকে কাটা ):
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
এছাড়াও, আপনাকে টাইপগুলি সম্পর্কে নীরব ব্যর্থতা তৈরির বিষয়ে চিন্তা করতে হবে না, যেমন আপনি হ্যাশ-টাইপ সমাধান ব্যবহার করে যাচ্ছেন।
এটি করার সর্বাধিক অভিহিত পদ্ধতি হ'ল প্রতীকগুলি ব্যবহার করা। উদাহরণস্বরূপ, পরিবর্তে:
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)
এটি এনামগুলির তুলনায় কিছুটা বেশি উন্মুক্ত, তবে এটি রুবি স্পিরিটের সাথে ভাল মানায়।
প্রতীকগুলিও খুব ভাল পারফর্ম করে। সমতার জন্য দুটি চিহ্নের তুলনা করা, উদাহরণস্বরূপ, দুটি স্ট্রিং তুলনা করার চেয়ে অনেক দ্রুত।
আমি নিম্নলিখিত পদ্ধতির ব্যবহার:
class MyClass
MY_ENUM = [MY_VALUE_1 = 'value1', MY_VALUE_2 = 'value2']
end
আমি নিম্নলিখিত সুবিধার জন্য এটি পছন্দ:
MY_ENUM
MY_VALUE_1
প্রতীকসমূহ ভাল হতে পারে আপনি, বাইরের ক্লাসের নাম লিখে যদি আপনি অন্য ক্লাসে ব্যবহার করছেন না কারণ ( MyClass::MY_VALUE_1
)
আপনি যদি 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
Conversation
বর্গের অনেকগুলি উদাহরণ তৈরি করতে দেয় - আমি বিশ্বাস করি এটি অবশ্যই 1 টি উদাহরণের অনুমতি দেবে।
এটি রুবিতে এনামগুলিতে আমার দৃষ্টিভঙ্গি। আমি সংক্ষিপ্ত এবং মিষ্টি জন্য যাচ্ছি, অগত্যা সর্বাধিক সি পছন্দ মত। কোন চিন্তা?
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
রুবি-এনাম রত্নটি দেখুন, https://github.com/d block/ruby-enum ।
class Gender
include Enum
Gender.define :MALE, "male"
Gender.define :FEMALE, "female"
end
Gender.all
Gender::MALE
সম্ভবত সবচেয়ে ভাল লাইটওয়েট পদ্ধতির হবে
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
class ABC; end
আমি জানি লোকটি এই প্রশ্নটি পোস্ট করার পরে অনেক দিন হয়েছে, তবে আমার একই প্রশ্ন ছিল এবং এই পোস্টটি আমাকে উত্তর দেয়নি। সংখ্যাটি কী উপস্থাপন করে, সহজ তুলনা করা যায় এবং এনামকে উপস্থাপনকারী কলামটি অনুসন্ধানের জন্য বেশিরভাগ অ্যাক্টিভেকর্ড সমর্থনটি দেখার জন্য আমি একটি সহজ উপায় চেয়েছিলাম।
আমি কিছুই পেলাম না, তাই আমি ইয়িনুম নামে একটি দুর্দান্ত বাস্তবায়ন করেছি যা আমার সন্ধানের জন্য সমস্ত কিছু অনুমতি দিয়েছে। টন চশমা তৈরি, তাই আমি নিশ্চিত এটি নিরাপদ।
কিছু উদাহরণ বৈশিষ্ট্য:
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
আপনি যদি চিহ্নগুলির সাথে টাইপগুলি নিয়ে উদ্বিগ্ন হন তবে নিশ্চিত হন যে আপনি অ-অস্তিত্ব কী দিয়ে কোনও মান অ্যাক্সেস করার সময় আপনার কোড একটি ব্যতিক্রম উত্থাপন করেছে। আপনি এটির 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
সাধারণত, আপনাকে ধ্রুবকগুলির সাথে টাইপোর সুরক্ষার বিষয়ে চিন্তা করতে হবে না। যদি আপনি একটি স্থির নাম ভুল বানান করে থাকেন তবে এটি সাধারণত একটি ব্যতিক্রম বাড়ে।
FOO_VALUES = {missing: 0, something: 1, something_else: 2, ...}
এই সংজ্ঞায়িত কী প্রতীক। missing
, something
ইত্যাদি, এবং এছাড়াও তাদের যুক্ত মান মাধ্যমে তুলনীয় তোলে।)
কেউ এগিয়ে গিয়ে রেনুম নামে একটি রুবি রত্ন লিখেছিল । এটি আচরণের মতো নিকটতম জাভা / সি # পাওয়ার দাবি করেছে। ব্যক্তিগতভাবে আমি এখনও রুবি শিখছি, এবং যখন আমি একটি নির্দিষ্ট শ্রেণীর একটি স্ট্যাটিক এনাম, সম্ভবত একটি হ্যাশ তৈরি করতে চেয়েছিলাম তখন গুগলের মাধ্যমে এটি ঠিক খুঁজে পাওয়া যায় নি।
এটি আপনি জাভা বা সি # এনামগুলি কীভাবে ব্যবহার করেন তা নির্ভর করে। আপনি এটি কীভাবে ব্যবহার করবেন তা সমাধানের জন্য আপনি রুবি বেছে নেবেন।
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"}>
Set[:a, :b, :c]
?
সম্প্রতি আমরা একটি রত্ন প্রকাশ করেছি যা রুবিতে এনামগুলি প্রয়োগ করে । আমার পোস্টে আপনি আপনার প্রশ্নের উত্তর পাবেন। এছাড়াও আমি সেখানে বর্ণনা করেছি যে কেন আমাদের বাস্তবায়ন বিদ্যমানগুলির তুলনায় ভাল (প্রকৃতপক্ষে রবিতে এই বৈশিষ্ট্যের অনেকগুলি বাস্তব রূপ এখনও রয়েছে)।
আর একটি সমাধান ওপেনস্ট্রাক্ট ব্যবহার করছে। এটি বেশ সোজা এগিয়ে এবং পরিষ্কার।
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'
প্রতীকগুলি হ'ল রুবি উপায়। তবে, কখনও কখনও কিছু সি কোড বা কিছু বা জাভার সাথে কথা বলা দরকার যা বিভিন্ন জিনিসের জন্য কিছু এনামকে প্রকাশ করে।
#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
।
server_Symb.each_with_index { |e,i| server_Enum[e] = i}
। দরকার নেই i = 0
।
আমি 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
এটি কিছুটা অতিরিক্ত অতিরিক্ত মনে হয়, তবে এটি এমন একটি পদ্ধতি যা আমি কয়েকবার ব্যবহার করেছি, বিশেষত যেখানে আমি এক্সএমএল বা এর মতো কিছু সংহত করছি।
#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
.key
বা .invert
বরং একটি তুলনায় :VAL
কী ( stackoverflow.com/a/10989394/2208016 )
key
বাinvert
বেশিরভাগ লোক প্রতীক ব্যবহার করে (এটি :foo_bar
সিনট্যাক্স)। তারা এক ধরণের অনন্য অস্বচ্ছ মান। প্রতীকগুলি কোনও এনাম-স্টাইলের ধরণের নয়, তাই তারা সি এর এনাম ধরণের সত্যিকারের বিশ্বস্ত উপস্থাপনা নয় তবে এটি এটি যতটা সুন্দর তা লাভজনক।
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 হয় রাজনৈতিক
কখনও কখনও আমার যা দরকার তা হ'ল এনামের মান আনতে এবং জাভা বিশ্বের সাথে মিল রেখে এর নামটি সনাক্ত করতে সক্ষম হওয়া।
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 এবং এর মতো স্টাফ।
আরেকটি পন্থা একটি হ্যাশ নিম্নলিখিত বর্ণনা অনুযায়ী নাম এবং মান সম্বলিত একটি রুবি বর্গ ব্যবহার করা RubyFleebie ব্লগ পোস্টে । এটি আপনাকে মান এবং ধ্রুবকের মধ্যে সহজে রূপান্তর করতে দেয় (বিশেষত যদি আপনি একটি নির্দিষ্ট মানটির জন্য নামের সন্ধানের জন্য কোনও শ্রেণিবদ্ধ পদ্ধতি যোগ করেন)।
আমি মনে করি প্রকারের মতো গণনা কার্যকর করার সর্বোত্তম উপায়টি প্রতীক সহকারে যেহেতু প্রায় পূর্ণসংখ্যা হিসাবে আচরণ করা হয় (যখন এটি সম্পাদন করার বিষয়টি আসে তখন অবজেক্ট_আইডি তুলনা করতে ব্যবহৃত হয়); আপনাকে সূচিকাগুলির বিষয়ে চিন্তা করার দরকার নেই এবং এগুলি আপনার কোড এক্সডি-তে খুব ঝরঝরে দেখাচ্ছে
ধারাবাহিক সমতা হ্যান্ডলিংয়ের সাথে একটি এনামের নকল করার আরেকটি উপায় (ডেভ থমাস থেকে নির্লজ্জভাবে গ্রহণ করা)। খোলা এনামগুলিকে (অনেক চিহ্নের মতো) এবং বন্ধ (পূর্বনির্ধারিত) এনামগুলিকে অনুমতি দেয়।
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
ইনাম চেষ্টা করে দেখুন। https://github.com/alfa-jpn/inum
class Color < Inum::Base
define :RED
define :GREEN
define :BLUE
end
Color::RED
Color.parse('blue') # => Color::BLUE
Color.parse(2) # => Color::GREEN