রুবেল অন রেলে একটি সেটার পদ্ধতি ওভাররাইড করার সঠিক উপায় কী?


184

আমি রুবেল ৩.২.২-এ রুবি ব্যবহার করছি এবং আমি জানতে চাই যে আমার ক্লাসের অ্যাট্রিবিউটের জন্য সেটার পদ্ধতিটি ওভাররাইড করার জন্য নিম্নলিখিতটি একটি "যথাযথ" / "সঠিক" / "নিশ্চিত" উপায় কিনা।

attr_accessible :attribute_name

def attribute_name=(value)
  ... # Some custom operation.

  self[:attribute_name] = value
end

উপরের কোডটি প্রত্যাশার মতো কাজ করছে বলে মনে হচ্ছে। তবে, আমি জানতে চাই যে উপরের কোডটি ব্যবহার করে, ভবিষ্যতে আমার সমস্যা হবে বা কমপক্ষে, কীভাবে "আমার প্রত্যাশা করা উচিত" / "রেলের উপর রুবি" হতে পারে ? যদি সেটার পদ্ধতিটি ওভাররাইড করার সঠিক উপায় না হয় তবে সঠিক উপায়টি কী?


দ্রষ্টব্য : আমি যদি কোডটি ব্যবহার করি

attr_accessible :attribute_name

def attribute_name=(value)
  ... # Some custom operation.

  self.attribute_name = value
end

আমি নিম্নলিখিত ত্রুটি পেয়েছি:

SystemStackError (stack level too deep):
  actionpack (3.2.2) lib/action_dispatch/middleware/reloader.rb:70

4
আমি "" যথাযথ "/" সঠিক "/" নিশ্চিত "" প্রয়োগ করা পরিভাষা পছন্দ করি love আপনি যখন এটি 3 টি উপায় দেন এটি সত্যই নিশ্চিত করে যে কোনও ভুল ব্যাখ্যা নেই। ভাল করেছ!
জে

5
@ জে - "সূক্ষ্ম ইতালিয়ানজম"; -)
ব্যাকো

2
কেবল স্পষ্ট করে বলতে গেলে, "স্ট্যাকের স্তরটি খুব গভীর" এটি তার পুনরাবৃত্ত কল ... এটি নিজেই কল করার বিষয়টি উল্লেখ করছে।
নিপ্পাইসরাস

উত্তর:


294

================================================== ========================= আপডেট: জুলাই 19, 2017

এখন রেল ডকুমেন্টেশনওsuper এই জাতীয় ব্যবহারের পরামর্শ দিচ্ছে :

class Model < ActiveRecord::Base

  def attribute_name=(value)
    # custom actions
    ###
    super(value)
  end

end

================================================== =========================

আসল উত্তর

আপনি যদি মডেলগুলির মাধ্যমে অ্যাক্সেস করার সময় কোনও সারণীর কলামগুলির জন্য সেটার পদ্ধতিগুলি ওভাররাইড করতে চান তবে এটি করার উপায়।

class Model < ActiveRecord::Base
  attr_accessible :attribute_name

  def attribute_name=(value)
    # custom actions
    ###
    write_attribute(:attribute_name, value)
    # this is same as self[:attribute_name] = value
  end

end

রেল ডকুমেন্টেশনে ওভাররাইডিং ডিফল্ট অ্যাক্সেসরগুলি দেখুন ।

সুতরাং, আপনার প্রথম পদ্ধতিটি হল রেলের অন মডেলের মডেলগুলিতে কলাম সেটটারগুলিকে ওভাররাইড করার সঠিক উপায়। মডেলটির বৈশিষ্ট্য হিসাবে টেবিলের কলামগুলিতে অ্যাক্সেস পেতে এই অ্যাক্সেসরগুলি ইতিমধ্যে রেল সরবরাহ করেছে। এটিকে আমরা অ্যাক্টিভেকর্ড ওআরএম ম্যাপিং বলি।

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

তবে খাঁটি রুবিতে, আপনি যদি কোনও ক্লাসের জন্য অ্যাক্সেসরগুলি সংজ্ঞায়িত করেছেন এবং সেটারটিকে ওভাররাইড করতে চান, আপনাকে উদাহরণস্বরূপ ভেরিয়েবলটি এই জাতীয়ভাবে ব্যবহার করতে হবে:

class Person
  attr_accessor :name
end

class NewPerson < Person
  def name=(value)
    # do something
    @name = value
  end
end

আপনি কী attr_accessorকরেন তা একবার বুঝতে পারলে এটি আরও সহজ হবে । কোডটি attr_accessor :nameএই দুটি পদ্ধতির সমান (গেটর এবং সেটার)

def name # getter
  @name
end

def name=(value) #  setter
  @name = value
end

এছাড়াও আপনার দ্বিতীয় পদ্ধতিটি ব্যর্থ হয়েছে কারণ আপনি সেই পদ্ধতির attribute_name=অভ্যন্তরে একই পদ্ধতিটি কল করার কারণে এটি একটি অসীম লুপ তৈরি করবে ।


9
4 রেলের জন্য কেবল এড়িয়ে যান attr_accessibleকারণ এটি আর নেই, এবং এটি কাজ করা উচিত
zigomir

11
কেন ডাকবে না super?
নাথান লিলিয়ান্থল

1
আমার ধারণা ছিল যেহেতু অ্যাক্সেসর এবং লেখকেরা গতিশীলভাবে তৈরি হয়েছে, তাই superএটি কাজ করতে পারে না। তবে, মনে হয় এটি তেমনটি নয়। আমি কেবল এটি যাচাই করেছি এবং এটি আমার পক্ষে কাজ করে। এছাড়াও, এই প্রশ্নটি একই জিজ্ঞাসা করুন
রুবিপ্রিন্স

4
সাথে রয়েছে বিশাল গোটচা write_attribute। রূপান্তরগুলি এড়িয়ে যাবে। সচেতন থাকুন যে write_attributeতারিখগুলির সাথে সময় অঞ্চল রূপান্তরগুলি এড়ানো হবে যা প্রায় সবসময়ই অনাকাঙ্ক্ষিত থাকবে।
টিম স্কট

2
সুপার পাশাপাশি কাজ করবে তবে এর কিছু কারণ রয়েছে যা আপনি এটি আমাদের কাছে না চাইতে পারেন। উদাহরণস্বরূপ মঙ্গোড রত্নটিতে একটি বাগ রয়েছে যেখানে আপনি গেটর পদ্ধতিটি সুপার করলে আপনার অ্যারেতে চাপ দিতে পারে না। এটি বাগের কারণ মেমরিতে অ্যারে পরিচালনা করার উপায় রয়েছে। এছাড়াও @ নামটি মান সেটটি ফিরিয়ে দেবে বরং তারপরে যে পদ্ধতিটি আপনার ওভাররাইট করা হবে তাকে কল করুন। তবে উপরের সমাধানটিতে উভয়ই ঠিকঠাক কাজ করবে।
newdark-it

44

superকীওয়ার্ডটি ব্যবহার করুন :

def attribute_name=(value)
  super(value.some_custom_encode)
end

বিপরীতে, পাঠককে ওভাররাইড করতে:

def attribute_name
  super.some_custom_decode
end

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

এই পরিবর্তনের কারণে জেল পদ্ধতিটি ওভাররাইড করা ৪.২ রেলগুলিতে ঝুঁকিপূর্ণ হয়ে উঠেছে: github.com/rails/rails/commit/… পূর্বে ফর্ম সহায়করা ক্ষেত্রটির অচিহ্নবিজ্ঞানের মানটি কল করবে এবং আপনার কাস্টম গেটরকে কল করবে না। এখন তারা আপনার পদ্ধতিটিকে কল করে এবং তাই আপনি কীভাবে মূল্যকে অগ্রাহ্য করছেন তার উপর নির্ভর করে আপনার ফর্মগুলিতে বিভ্রান্তিকর ফলাফল আসবে।
ব্রেন্ডন মুর

16

রেলপথে 4

আপনার টেবিলে আপনার বয়সের বৈশিষ্ট্য রয়েছে বলে দিন

def age=(dob)   
    now = Time.now.utc.to_date
    age = now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
    super(age) #must add this otherwise you need to add this thing and place the value which you want to save. 
  end

দ্রষ্টব্য: রেল 4 তে নতুন আগতদের জন্য আপনাকে মডেলটিতে অ্যাট্রি_স্যাক্সেসেবল নির্দিষ্ট করার দরকার নেই । পরিবর্তে পারমিট পদ্ধতিটি ব্যবহার করে আপনাকে নিয়ামক স্তরে আপনার বৈশিষ্ট্যগুলি সাদা তালিকাভুক্ত করতে হবে ।


3

আমি খুঁজে পেয়েছি (কমপক্ষে অ্যাক্টিভেকর্ড সম্পর্ক সংগ্রহের জন্য) নিম্নলিখিত প্যাটার্নটি কাজ করে:

has_many :specialties

def specialty_ids=(values)
  super values.uniq.first(3)
end

(এটি পাস করা অ্যারেতে প্রথম 3 নন-অনুলিপি এন্ট্রিগুলি ধরে ফেলে))


0

attr_writerসেটার ওভাররাইট অ্যাটরাইট করতে ব্যবহার করে অ্যাট্রিবিউটর: বৈশিষ্ট্য_নাম _

  def attribute_name=(value)
    # manipulate value
    # then send result to the default setter
    super(result)
  end
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.