অ্যাক্টিভেকর্ডে আমি কীভাবে ডিফল্ট মান সেট করতে পারি?


417

অ্যাক্টিভেকর্ডে আমি কীভাবে ডিফল্ট মান সেট করতে পারি?

আমি প্রতকের একটি পোস্ট দেখি যা একটি কুৎসিত, জটিল কোডের বর্ণনা দেয়: http://m.onkey.org/2007/7/24/how-to-set-default-values-in-yur-model

class Item < ActiveRecord::Base  
  def initialize_with_defaults(attrs = nil, &block)
    initialize_without_defaults(attrs) do
      setter = lambda { |key, value| self.send("#{key.to_s}=", value) unless
        !attrs.nil? && attrs.keys.map(&:to_s).include?(key.to_s) }
      setter.call('scheduler_type', 'hotseat')
      yield self if block_given?
    end
  end
  alias_method_chain :initialize, :defaults
end

আমি নীচের উদাহরণগুলি চারপাশে গুগল করতে দেখেছি:

  def initialize 
    super
    self.status = ACTIVE unless self.status
  end

এবং

  def after_initialize 
    return unless new_record?
    self.status = ACTIVE
  end

আমি এটি লোকেরা তাদের স্থানান্তরিত করার ক্ষেত্রেও দেখেছি, তবে আমি এটি মডেল কোডে সংজ্ঞায়িত দেখতে চাই see

অ্যাক্টিভেকর্ড মডেলটিতে ক্ষেত্রগুলির জন্য ডিফল্ট মান নির্ধারণের কোনও আধ্যাত্মিক উপায় আছে?


দেখে মনে হচ্ছে আপনি এই প্রশ্নের উত্তর নিজেই দিয়েছেন, দুটি ভিন্ন রূপে :)
অ্যাডাম বাইরটেক

19
মনে রাখবেন যে 'স্ব.স্ট্যাটাস = অ্যাকটিভ'-এর "মানক" রুবি আইডিয়াম যদি স্ব-স্ট্যাটাস না হয় তবে' সেলফ স্ট্যাটাস || = অ্যাক্টিভ '
মাইক উডহাউস

1
জেফ পেরিনের উত্তর বর্তমানে গৃহীত হিসাবে চিহ্নিত হিসাবে রয়েছে তার থেকে অনেক ভাল। ডিফল্ট মানগুলি সেট করার জন্য ডিফল্ট_স্কোপ একটি অগ্রহণযোগ্য সমাধান, কারণ এটিতে ক্যোয়ারির আচরণের পরিবর্তন করার বিশাল আকারের প্রভাব রয়েছে E
লরেন্স


2
এই প্রশ্নের সমস্ত উত্সাহ দেওয়া, আমি বলব যে অ্যাক্টিভেকর্ডের জন্য রুবির একটি
সেটডাফল্ট

উত্তর:


557

উপলব্ধ প্রতিটি পদ্ধতির সাথে বেশ কয়েকটি সমস্যা রয়েছে তবে আমি বিশ্বাস করি যে কলব্যাককে সংজ্ঞায়িত করা after_initializeনিম্নলিখিত কারণগুলির জন্য যাওয়ার উপায়:

  1. default_scopeনতুন মডেলের জন্য মানগুলি সূচনা করবে, তবে তারপরে এটি সেই সুযোগে পরিণত হবে যা আপনি মডেলটি সন্ধান করেন। আপনি যদি কিছু নম্বর 0 তে শুরু করতে চান তবে আপনি যা চান তা এটি নয়
  2. আপনার মাইগ্রেশনে ডিফল্ট সংজ্ঞায়িত করা সময়ের অংশও কাজ করে ... যেমনটি ইতিমধ্যে উল্লেখ করা হয়েছে যে আপনি কেবল মডেল.নুকে কল করলেই এটি কার্যকর হবে না
  3. ওভাররাইডিং initializeকাজ করতে পারে, তবে কল করতে ভুলবেন না super!
  4. ফিউশন এর মতো একটি প্লাগইন ব্যবহার করা কিছুটা হাস্যকর হয়ে উঠছে। এটি রুবি, কিছু ডিফল্ট মান শুরু করার জন্য আমাদের কি সত্যিই একটি প্লাগইন দরকার?
  5. ওভাররাইডিংটি ails.৩.৩ রেল হিসাবে অবহিত করা after_initialize হয় যখন আমি after_initializeরেল 3.0.০.৩ এ ওভাররাইড করি আমি কনসোলে নিম্নলিখিত সতর্কতা পাই:

প্রসারণ সতর্কতা: বেস # after_initialize অবমূল্যায়ন করা হয়েছে, দয়া করে এর পরিবর্তে বেস.পরে_অনিটালাইজ করুন: পদ্ধতিটি ব্যবহার করুন। (ব্যবহারকারী / আমাকে / আমার অ্যাপ / অ্যাপ / মডেল / মাই মডেল থেকে কল করা হয়েছে: 15)

সুতরাং আমি বলব একটি after_initializeকলব্যাক লিখুন যা আপনাকে ডিফল্ট বৈশিষ্ট্যগুলি ছাড়াও যেমন সমিতিতে ডিফল্ট সেট করতে দেয়:

  class Person < ActiveRecord::Base
    has_one :address
    after_initialize :init

    def init
      self.number  ||= 0.0           #will set the default value only if it's nil
      self.address ||= build_address #let's you set a default association
    end
  end    

আপনার মডেলগুলির আরম্ভকরণের জন্য এখন আপনার কাছে কেবলমাত্র একটি জায়গা রয়েছে। আমি এই পদ্ধতিটি ব্যবহার করছি যতক্ষণ না কেউ আরও ভালর সাথে আসে।

আদেশ সহকারে:

  1. বুলিয়ান ক্ষেত্রগুলির জন্য এটি করুন:

    self.bool_field = true if self.bool_field.nil?

    আরও তথ্যের জন্য এই উত্তরে পল রাসেলের মন্তব্য দেখুন

  2. আপনি শুধুমাত্র একটি মডেল জন্য কলামের একটি উপসেট নির্বাচন করেন তাহলে (অর্থাত; ব্যবহার selectমতো ক্যোয়ারীতে Person.select(:firstname, :lastname).all) আপনি একটি পাবেন MissingAttributeErrorআপনার যদি initপদ্ধতি কলামে কোনো মধ্যে অন্তর্ভুক্ত করা হয়েছে ব্যবহারের selectদফা। আপনি এই মামলার বিরুদ্ধে যেমন রক্ষা করতে পারেন:

    self.number ||= 0.0 if self.has_attribute? :number

    এবং একটি বুলিয়ান কলামের জন্য ...

    self.bool_field = true if (self.has_attribute? :bool_value) && self.bool_field.nil?

    এছাড়াও খেয়াল করুন যে রেল ৩.২ এর আগে বাক্য গঠনটি আলাদা ছিল (নীচে ক্লিফ ডার্লিংয়ের মন্তব্য দেখুন)


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

106
self.bool_field ||= trueএটির জন্য একটি নোট - আপনার যদি বুলিয়ান ক্ষেত্র থাকে যা আপনি ডিফল্ট করতে চান তবে তা করবেন না , কারণ এটি ক্ষেত্রটিকে সত্যে বাধ্য করতে বাধ্য করবে এমনকি যদি আপনি স্পষ্টভাবে এটি মিথ্যা হিসাবে শুরু করেন। পরিবর্তে না self.bool_field = true if self.bool_field.nil?
পল রাসেল

2
পয়েন্ট # 2 সম্পর্কিত, মডেল.ইউ মাইগ্রেশনে সংজ্ঞায়িত ডিফল্টগুলির সাথে বা কেবল টেবিল কলামগুলির জন্য ডিফল্ট মানগুলির সাথে একত্রে কাজ করে (কেবল আমার জন্য?) তবে আমি স্বীকার করেছি যে জেফের পদ্ধতিটি উত্তর_কালীন কলব্যাকের উপর ভিত্তি করে সম্ভবত করার সেরা উপায়। কেবল একটি প্রশ্ন: এটি কি নোংরা তবুও সংরক্ষিত অবজেক্টের সাথে কাজ করে? আপনার উদাহরণে, Person.new.number_was ০.০ ফিরিয়ে দেবে?
লরেন্ট ফারসি

21
সক্রিয় রেকর্ড সহ নির্দিষ্ট কলামগুলি নির্বাচন করার সাথে মিলিত এই পদ্ধতির ব্যবহার করার সময় সাবধানতা। এক্ষেত্রে কেবল ক্যোয়ারীতে বর্ণিত বৈশিষ্ট্যগুলি বস্তুটিতে পাওয়া যাবে এবং আর ডি কোডটি একটি নিক্ষেপ করবে MissingAttributeError। আপনি দেখানো হয়েছে একটি অতিরিক্ত চেক যুক্ত করতে পারেন: self.number ||= 0.0 if self.has_attribute? :number Booleans জন্য: self.bool_field = true if (self.has_attribute? :bool_value) && self.bool_field.nil?। এটি রেলস ৩.২++ - এর আগে, ব্যবহার করুন self.attributes.has_key?এবং আপনার প্রতীকের পরিবর্তে একটি স্ট্রিং দরকার।
ক্লিফ ডার্লিং

6
অ্যাসোসিয়েশনগুলির সাথে এটি করার ফলে এই সংঘগুলি অনুসন্ধানের জন্য আগ্রহী হবে। শুরু initializeসঙ্গে return if !new_record?কর্মক্ষমতা সমস্যা এড়ানোর জন্য।
কাইল ম্যাসেই

68

রেল 5+

আপনি আপনার মডেলগুলির মধ্যে অ্যাট্রিবিউট পদ্ধতিটি ব্যবহার করতে পারেন , যেমন:

class Account < ApplicationRecord
  attribute :locale, :string, default: 'en'
end

আপনি defaultপ্যারামিটারে একটি ল্যাম্বডাও পাস করতে পারেন । উদাহরণ:

attribute :uuid, UuidType.new, default: -> { SecureRandom.uuid }

3
আহহহহ এই সেই রত্নটি আমি খুঁজছিলাম! ডিফল্ট একটি প্রক্টও গ্রহণ করতে পারে, উদাহরণস্বরূপ: ডিফল্ট: -> {টাইম কোডারেন্ট.টো_ডেট}
স্কেচেট

1
দ্বিতীয় আর্গুমেন্ট হিসাবে প্রকারটি নির্দিষ্ট করে দেওয়ার বিষয়টি নিশ্চিত করুন, অন্যথায় টাইপটি হবে Valueএবং কোনও টাইপকাস্টিং করা হবে না।
নাল

আমার আনন্দের সাথে, এটি স্টোর_সেসসরের সাথেও কাজ করে, উদাহরণস্বরূপ store_accessor :my_jsonb_column, :localeআপনি তারপরে সংজ্ঞা দিতে পারবেনattribute :locale, :string, default: 'en'
রায়ান রোমানচুক

ওহ এটি দুর্দান্ত, একটি ফর্মটি দেখানোর জন্য আমার ডিফল্ট প্রয়োজন এবং এটি দুর্দান্ত কাজ করে। ধন্যবাদ লুকাস।
পল ওয়াটসন

একটি এখনও এ সেট করতে পারেন nil। তারা হতে পারে না যদি nilডিবি not null+ + ডিবি ডিফল্ট + github.com/sshaw/keep_defaults আমার অভিজ্ঞতা থেকে যেতে উপায় হয়
sshaw

47

আমরা মাইগ্রেশনের মাধ্যমে ডেটাবেজে ডিফল্ট মানগুলি রেখেছি ( :defaultপ্রতিটি কলাম সংজ্ঞাতে বিকল্পটি নির্দিষ্ট করে ) এবং অ্যাক্টিভ রেকর্ডকে প্রতিটি বৈশিষ্ট্যের জন্য ডিফল্ট সেট করতে এই মানগুলি ব্যবহার করতে দিন।

আইএমএইচও, এই পদ্ধতিটি এআর নীতির সাথে একত্রিত: কনফিগারেশন ওভার কনফিগারেশন, ডিআরওয়াই, টেবিল সংজ্ঞাটি মডেলটিকে চালিত করে, অন্যভাবে নয়।

নোট করুন যে ডিফল্টগুলি এখনও অ্যাপ্লিকেশন (রুবি) কোডে রয়েছে, যদিও মডেলটিতে নয় তবে মাইগ্রেশন (গুলি)।


3
আর একটি সমস্যা হ'ল যখন আপনি কোনও বিদেশী কীটির জন্য একটি ডিফল্ট মান চান। আপনি বিদেশী কী ক্ষেত্রে কোনও আইডি মান হার্ড-কোড করতে পারবেন না কারণ বিভিন্ন ডিবিতে আইডি আলাদা হতে পারে।
shmichael

2
তবুও আরেকটি সমস্যা হ'ল এইভাবে আপনি অ-অবিচ্ছিন্ন অ্যাকসেসর (ডিবি কলাম নয় এমন গুণাবলী) আরম্ভ করতে পারবেন না।
ভিক্টর ট্রেন

2
অন্য সমস্যাটি হ'ল আপনি অগত্যা সমস্ত ডিফল্ট মান এক জায়গায় দেখতে পাচ্ছেন না। তারা বিভিন্ন স্থানান্তর মাধ্যমে ছড়িয়ে ছিটিয়ে থাকতে পারে।
ডেকলান

8
ডেকলান করুন, ডিবি / schema.rb
বেঞ্জামিন Atkin

6
আমি ভবিষ্যতের পাঠকদের জন্য উল্লেখ করতে চাই: কমপক্ষে আমি যা পড়েছি তা থেকে এটি এআর নীতির বিপরীত। মডেলগুলির পক্ষে যুক্তিটি মডেল শ্রেণীর মধ্যে থাকা উচিত এবং ডাটাবেসগুলি যথাসম্ভব অজ্ঞ হওয়া উচিত। আমার কাছে ডিফল্ট মানগুলি কোনও মডেল সম্পর্কে নির্দিষ্ট যুক্তি গঠন করে ic
দারথেস

40

কিছু সাধারণ কেস ডাটাবেস স্কিমাতে একটি ডিফল্ট সংজ্ঞায়িত করে পরিচালনা করা যায় তবে এটি গণ্যমানের মান এবং অন্যান্য মডেলের কীগুলি সহ বেশ কয়েকটি ট্রিকিয়ার কেস পরিচালনা করতে পারে না। এই ক্ষেত্রে আমি এটি করি:

after_initialize :defaults

def defaults
   unless persisted?
    self.extras||={}
    self.other_stuff||="This stuff"
    self.assoc = [OtherModel.find_by_name('special')]
  end
end

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

শর্তটি কলব্যাকের অনুরোধে সরিয়ে নেওয়া হলে ব্র্যাড মুরের উত্তরটি দেখে এটি আরও পরিষ্কার হয়:

after_initialize :defaults, unless: :persisted?
              # ":if => :new_record?" is equivalent in this context

def defaults
  self.extras||={}
  self.other_stuff||="This stuff"
  self.assoc = [OtherModel.find_by_name('special')]
end

4
এটি একটি সত্যই গুরুত্বপূর্ণ বিষয়। আমার কল্পনা করতে হবে যে বেশিরভাগ ক্ষেত্রে একটি রেকর্ডে ডিফল্ট সেট করা কেবল একটি নতুন রেকর্ড অব্যাহত রাখার আগে করা হয়, স্থির রেকর্ডটি লোড করার সময় নয়।
রাসেল সিলভা

থেক্স ডুড, তুমি আমার দিনকে বাঁচিয়েছ
স্টেফানফ্রিডরিচ

2
কীভাবে :before_create?
ফ্র্যাংকলিন ইউ

কীভাবে: আগে_সৃজন হ্যান্ডেল পৃথক নতুন এবং কলগুলি সংরক্ষণ করে? আমি এটি পরীক্ষা করে দেখতে চাই এবং এটিতে স্যুইচ করার আগে সত্যিই বুঝতে পারি।
জোসেফ লর্ড

17

পরে_নিটায়ালাইজ কলব্যাক প্যাটার্নটি কেবল নিম্নরূপে করে উন্নত করা যেতে পারে

after_initialize :some_method_goes_here, :if => :new_record?

আপনার থ্রিমি কোডটি সমিতিগুলির সাথে ডিল করার প্রয়োজন হলে এটির একটি অ-তুচ্ছ সুবিধা রয়েছে কারণ নিম্নলিখিত কোডটি সূক্ষ্ম এন + 1 ট্রিগার করে যদি আপনি সম্পর্কিতটি বাদ না দিয়ে প্রাথমিক রেকর্ডটি পড়েন।

class Account

  has_one :config
  after_initialize :init_config

  def init_config
    self.config ||= build_config
  end

end

16

ফিউশন বলছি এই জন্য কিছু দুর্দান্ত প্লাগইন আছে ।


দ্রষ্টব্য, এই প্লাগইনটি :defaultস্কিমা মাইগ্রেশনের মানগুলি 'স্রেফ কাজ' করতে দেয় Model.new
jchook

জেফ তার পোস্টে যা বলেছিল তার বিপরীতে আমি :default'স্রেফ কাজ' করতে মাইগ্রেশনের মানগুলি পেতে পারি Model.new। 4.1.16 কারাগারে কাজ করা যাচাই করা হয়েছে।
ম্যাগনে

8

প্রস্তাবিত উত্তরের চেয়ে আরও ভাল / ক্লিনার সম্ভাব্য উপায় হ'ল এক্সেসরটি ওভাররাইট করা, এর মতো:

def status
  self['status'] || ACTIVE
end

"মুছে যাওয়ার ডিফল্ট accessors" দেখুন ActiveRecord :: বেজ ডকুমেন্টেশন এবং স্ব ব্যবহার করে Stackoverflow থেকে আরো


অবস্থা থেকে এখনও ফিরে আসা হ্যাশ শূন্য থাকবে attributes। রেল পরীক্ষিত 5.2.0।
স্পাইল

8

আমি রত্ন ব্যবহার করিattribute-defaults

ডকুমেন্টেশন থেকে: চালান sudo gem install attribute-defaultsএবং require 'attribute_defaults'আপনার অ্যাপ্লিকেশন যোগ করুন।

class Foo < ActiveRecord::Base
  attr_default :age, 18
  attr_default :last_seen do
    Time.now
  end
end

Foo.new()           # => age: 18, last_seen => "2014-10-17 09:44:27"
Foo.new(:age => 25) # => age: 25, last_seen => "2014-10-17 09:44:28"

7

অনুরূপ প্রশ্ন, তবে সবার কিছুটা আলাদা প্রসঙ্গ রয়েছে: - আমি কীভাবে রেলস অ্যাক্টিভেকর্ডের মডেলটিতে বৈশিষ্ট্যের জন্য একটি ডিফল্ট মান তৈরি করব?

সেরা উত্তর: আপনি যা চান তার উপর নির্ভর করে!

আপনি যদি প্রতিটি বস্তুটি একটি মান দিয়ে শুরু করতে চান : ব্যবহার করুনafter_initialize :init

আপনি new.htmlপৃষ্ঠাটি খোলার পরে ফর্মটির একটি ডিফল্ট মান থাকতে চান ? https://stackoverflow.com/a/5127684/1536309 ব্যবহার করুন

class Person < ActiveRecord::Base
  has_one :address
  after_initialize :init

  def init
    self.number  ||= 0.0           #will set the default value only if it's nil
    self.address ||= build_address #let's you set a default association
  end
  ...
end 

আপনি যদি চান যে বস্তু একটি মান ব্যবহারকারীর ইনপুট থেকে গণনা করা হয়েছে: ব্যবহারbefore_save :default_values ব্যবহারকারী প্রবেশ করতে চানXএবং তারপরY = X+'foo'? ব্যবহার করুন:

class Task < ActiveRecord::Base
  before_save :default_values
  def default_values
    self.status ||= 'P'
  end
end

4

এটি কি কনস্ট্রাক্টরদের জন্য! মডেলের initializeপদ্ধতিটি ওভাররাইড করুন ।

after_initializeপদ্ধতিটি ব্যবহার করুন ।


2
সাধারণত আপনি সঠিক হতে চাইবেন তবে আপনাকে কখনও অ্যাক্টিভেকর্ড মডেলটিতে আরম্ভ করতে হবে না কারণ এটি সর্বদা বলা হয় না। after_initializeপরিবর্তে আপনার পদ্ধতিটি ব্যবহার করা উচিত ।
লূক রেডপথ

কেবলমাত্র একটি ডিফল্ট সেট করতে একটি ডিফল্ট_স্কোপ ব্যবহার করা নিখুঁতভাবে ভুল। after_initialize হ'ল সঠিক উত্তর।
joomilho

4

সুপার ছেলেরা, আমি নিম্নলিখিতগুলি শেষ করেছি:

def after_initialize 
 self.extras||={}
 self.other_stuff||="This stuff"
end

একটি যাদুমন্ত্র মত কাজ করে!


3

এটি দীর্ঘ সময়ের জন্য উত্তর দেওয়া হয়েছে, তবে আমার ঘন ঘন ডিফল্ট মানগুলি প্রয়োজন এবং সেগুলি ডাটাবেসে না রাখাই পছন্দ করি। আমি একটি DefaultValuesউদ্বেগ তৈরি :

module DefaultValues
  extend ActiveSupport::Concern

  class_methods do
    def defaults(attr, to: nil, on: :initialize)
      method_name = "set_default_#{attr}"
      send "after_#{on}", method_name.to_sym

      define_method(method_name) do
        if send(attr)
          send(attr)
        else
          value = to.is_a?(Proc) ? to.call : to
          send("#{attr}=", value)
        end
      end

      private method_name
    end
  end
end

এবং তারপরে এটি আমার মডেলগুলিতে পছন্দ করুন:

class Widget < ApplicationRecord
  include DefaultValues

  defaults :category, to: 'uncategorized'
  defaults :token, to: -> { SecureRandom.uuid }
end

3

আমি এটি লোকেরা তাদের স্থানান্তরিত করার ক্ষেত্রেও দেখেছি, তবে আমি এটি মডেল কোডে সংজ্ঞায়িত দেখতে চাই see

অ্যাক্টিভেকর্ড মডেলটিতে ক্ষেত্রগুলির জন্য ডিফল্ট মান নির্ধারণের কোনও আধ্যাত্মিক উপায় আছে?

ক্যানোনিকাল রেইলস ওয়েল, রেল 5 এর আগে এটি মাইগ্রেশনে সেট করা ছিল এবং db/schema.rbযখনই কোনও মডেলের জন্য ডিবি দ্বারা কোন ডিফল্ট মান নির্ধারণ করা হচ্ছে তা দেখার জন্য কেবল অনুসন্ধান করুন ।

@ জেফ পেরিন উত্তর যা বলেছে তার বিপরীতে (যা কিছুটা পুরানো), ব্যবহারের সময় মাইগ্রেশন পদ্ধতি এমনকি ডিফল্ট প্রয়োগ করবে Model.new কিছুটা রেলের ম্যাজিকের কারণে । 4.1.16 কারাগারে কাজ করা যাচাই করা হয়েছে।

সহজ জিনিসটি প্রায়শই সেরা। কম জ্ঞানের debtণ এবং কোডবেসে বিভ্রান্তির সম্ভাব্য পয়েন্ট। এবং এটি 'কেবল কাজ করে'।

class AddStatusToItem < ActiveRecord::Migration
  def change
    add_column :items, :scheduler_type, :string, { null: false, default: "hotseat" }
  end
end

বা, কলাম পরিবর্তন করার জন্য একটি নতুন তৈরি না করেই করুন, তবে হয় করুন:

class AddStatusToItem < ActiveRecord::Migration
  def change
    change_column_default :items, :scheduler_type, "hotseat"
  end
end

বা সম্ভবত আরও ভাল:

class AddStatusToItem < ActiveRecord::Migration
  def change
    change_column :items, :scheduler_type, :string, default: "hotseat"
  end
end

কলাম পরিবর্তন পদ্ধতিতে বিকল্পগুলির জন্য অফিসিয়াল আরআর গাইড পরীক্ষা করুন।

null: falseনামঞ্জুর করে ডিবি মান নাল, এবং, একটা অতিরিক্ত লাভ, এটি তাই আপডেট সব পূর্ব বিদ্যমান ডিবি রেকর্ড যা পূর্বে নাল ছিল পাশাপাশি এই ক্ষেত্রের জন্য ডিফল্ট মান সঙ্গে সেট করা হয় যে। আপনি যদি চান তবে এই প্যারামিটারটি মাইগ্রেশনে বাদ দিতে পারেন, তবে আমি এটি খুব সহজেই পেয়েছি!

রেল 5+ এ আধ্যাত্মিক উপায়টি হ'ল, যেমনটি লুকাস ক্যাটন বলেছেন:

class Item < ActiveRecord::Base
  attribute :scheduler_type, :string, default: 'hotseat'
end

1

আফটার_আইনাইটালাইজেশন সমাধানগুলির সাথে সমস্যাটি হ'ল আপনি এই বৈশিষ্ট্যটি অ্যাক্সেস করেছেন কিনা তা বিবেচনা না করেই আপনি ডিবি থেকে সন্ধান করা প্রতিটি একক অবজেক্টে একটি আফটার_ইনাইটালাইজড যুক্ত করতে হবে। আমি একটি অলস বোঝা পদ্ধতির পরামর্শ দিই।

অ্যাট্রিবিউট পদ্ধতিগুলি (গেটার্স) অবশ্যই তাদের নিজস্ব পদ্ধতি, যাতে আপনি সেগুলি ওভাররাইড করতে পারেন এবং একটি ডিফল্ট সরবরাহ করতে পারেন। কিছুটা এইরকম:

Class Foo < ActiveRecord::Base
  # has a DB column/field atttribute called 'status'
  def status
    (val = read_attribute(:status)).nil? ? 'ACTIVE' : val
  end
end

যদি না কারও কারও ইশারা করা থাকে তবে আপনার Foo.find_by_status ('ACTIVE') করা দরকার। সেক্ষেত্রে আমি মনে করি আপনি যদি সত্যিই ডিবি সমর্থন করেন তবে আপনার ডাটাবেসের সীমাবদ্ধতায় আপনার ডিফল্ট সেট করতে হবে।


এই সমাধান এবং প্রস্তাবিত বিকল্পটি আমার ক্ষেত্রে কাজ করে না: আমার কাছে একটি এসটিআই শ্রেণির শ্রেণিবিন্যাস রয়েছে যেখানে কেবলমাত্র একটি শ্রেণিরই সেই বৈশিষ্ট্য রয়েছে এবং সংশ্লিষ্ট কলামটি ডিবি ক্যোয়ারী শর্তে ব্যবহৃত হবে।
cmoran92

1

আমি সঙ্গে সমস্যা গাড়ীতে আঘাত after_initializeদান ActiveModel::MissingAttributeErrorত্রুটি যখন জটিল খুঁজে বের করে করছেন:

উদাহরণ:

@bottles = Bottle.includes(:supplier, :substance).where(search).order("suppliers.name ASC").paginate(:page => page_no)

"অনুসন্ধান" .whereহ'ল শর্তগুলির হ্যাশ

সুতরাং আমি এইভাবে আরম্ভকরণকে এইভাবে ওভাররাইড করে শেষ করেছিলাম:

def initialize
  super
  default_values
end

private
 def default_values
     self.date_received ||= Date.current
 end

superকল নিশ্চিত বস্তু থেকে সঠিকভাবে আরম্ভের করতে প্রয়োজনীয় ActiveRecord::Baseআমার কাস্টমাইজ কোড, অর্থাত কাজ করার আগে: default_values


আমি এটা পছন্দ করি. আমার def initialize(*); super; default_values; endকারাগুলিতে 5.2.0 এ করা দরকার। এছাড়াও, ডিফল্ট মানটি পাওয়া যায়, এমনকি .attributesহ্যাশেও।
স্পাইল

1
class Item < ActiveRecord::Base
  def status
    self[:status] or ACTIVE
  end

  before_save{ self.status ||= ACTIVE }
end

2
এমএমএমএইচ ... প্রথমে বুদ্ধিমান মনে হয় তবে কিছু চিন্তা করার পরে আমি কিছু সমস্যা দেখতে পাচ্ছি। প্রথমত, সমস্ত ডিফল্ট মান একক বিন্দুতে নয়, তবে ক্লাসের মধ্যে ছড়িয়ে ছিটিয়ে থাকে (তাদের সন্ধান বা তাদের পরিবর্তন করার কল্পনা করুন)। দ্বিতীয় এবং সবচেয়ে খারাপ, আপনি পরে একটি নাল মান (বা এমনকি একটি মিথ্যাও!) রাখতে পারবেন না।
প্যারাডোজা

আপনি কেন ডিফল্ট হিসাবে নাল মান সেট করতে হবে? আপনি এআর এর সাথে বাকীটি কিছু না করেই পেয়ে যাবেন। মিথ্যা হিসাবে যেমন বুলিয়ান কলাম ব্যবহার করা হয় তখন আপনি ঠিক বলেছেন, এটি সেরা পদ্ধতির নয়।
মাইক ব্রেন

আমি অন্যদের কোডিংয়ের অভ্যাসের জন্য কথা বলতে পারি না কারণ আমার কোনও সমস্যা হয়নি কারণ আমি কোনও ক্লাস ফাইলের মধ্যে আমার গেটার / সেটটারগুলিকে ছড়িয়ে দিই না। এছাড়াও, যে কোনও আধুনিক পাঠ্য সম্পাদককে কোনও পদ্ধতিতে নেভিগেট করা সহজ করে তুলতে হবে (টেক্সটমেটে shift-cmd-t)।
মাইক ব্রেন

@ পরিদোজা - আমি এটি ফিরিয়ে নিয়েছি, এখন দেখতে পাচ্ছি কোথায় নাল ব্যবহার করে এটি ভেঙে যায়। অবিচ্ছিন্নভাবে নালটিকে ডিফল্ট হিসাবে ব্যবহার করার প্রয়োজন নেই তবে আপনি যদি সত্যিই কোনও সময়ে মানটিকে নালিতে পরিবর্তন করতে চান। ধন্যবাদ @paradoja, ধন্যবাদ।
মাইক ব্রেন

আমি এই পদ্ধতিটি ব্যবহার করি কারণ এটি গতিশীলভাবে উত্পন্ন বৈশিষ্ট্যগুলির সাথে ভাল কাজ করে।
ডেল ক্যাম্পবেল

0

যদিও ডিফল্ট মান নির্ধারণের জন্য এটি করা বেশিরভাগ ক্ষেত্রে বিভ্রান্তিকর এবং বিশ্রীজনক হলেও আপনি এটি ব্যবহার করতে পারেন :default_scope। পরীক্ষা করে দেখুন এখানে squil এর মন্তব্য


0

after_initialize পদ্ধতি অবমূল্যায়ন করা হয়, পরিবর্তে কলব্যাক ব্যবহার করুন।

after_initialize :defaults

def defaults
  self.extras||={}
  self.other_stuff||="This stuff"
end

তবে, ব্যবহার করে : আপনার মাইগ্রেশনগুলিতে ডিফল্ট হওয়া এখনও সবচেয়ে পরিষ্কার উপায়।


4
3 কারাগারে: after_initializeপদ্ধতি হ্রাস করা হয় না । প্রকৃতপক্ষে, ম্যাক্রো-স্টাইলের কলব্যাক আপনি হ্রাসের IS এর একটি উদাহরণ দেন । বিশদ: গাইড.আরবিওনরইলস.আর.২
জাবাবা

0

আমি খুঁজে পেয়েছি যে একটি বৈধকরণ পদ্ধতি ব্যবহার করে ডিফল্ট নির্ধারণের জন্য প্রচুর নিয়ন্ত্রণ সরবরাহ করে। আপনি আপডেটের জন্য ডিফল্ট (বা বৈধতা ব্যর্থ) সেট করতে পারেন। এমনকি আপনি যদি সত্যিই চাইতেন তবে সন্নিবেশ বনাম আপডেটের জন্য আলাদা ডিফল্ট মান সেট করে রেখেছেন। নোট করুন যে ডিফল্টটি # বৈধ না হওয়া পর্যন্ত সেট করা হবে না? বলা হয়.

class MyModel
  validate :init_defaults

  private
  def init_defaults
    if new_record?
      self.some_int ||= 1
    elsif some_int.nil?
      errors.add(:some_int, "can't be blank on update")
    end
  end
end

আফটার_নিটায়ালাইজ পদ্ধতিটি সংজ্ঞায়িত করার ক্ষেত্রে, কার্য সম্পাদনের সমস্যা হতে পারে কারণ প্রত্যক্ষদর্শীকরণকে প্রতিটি বস্তু দ্বারা ফিরেও বলা হয়: সন্ধান করুন: http://guides.rubyonrails.org/active_record_ediaations_callbacks.html# after_initialize- এবং- after_find


বৈধতা সংরক্ষণের আগেই ঘটে না? আপনি যদি সংরক্ষণের আগে খেলাপি প্রদর্শন করতে চান?
নুরেটিন

@ নুরেটিন এটি একটি ভাল বিষয় এবং আমি দেখতে পাচ্ছি আপনি কেন কখনও কখনও এটি চান তবে ওপি প্রয়োজনীয়তা হিসাবে এটি উল্লেখ করেনি। আপনার নিজের জন্য সিদ্ধান্ত নিতে হবে যে আপনি প্রতি বারে ডিফল্ট সেট করার ওভারহেড চান কিনা তা সংরক্ষণ না করেও। বিকল্পটি newপুনরায় ব্যবহারের জন্য অবিরাম পদক্ষেপ রাখা d
কেলভিন

0

কলামটি যদি কোনও 'স্থিতি' টাইপ কলাম হয়ে থাকে এবং আপনার মডেল নিজেকে রাষ্ট্রীয় মেশিনগুলির ব্যবহারের জন্য ধার দেয়, তবে আসম রত্নটি ব্যবহার করার বিষয়টি বিবেচনা করুন , তারপরে আপনি সহজেই করতে পারেন

  aasm column: "status" do
    state :available, initial: true
    state :used
    # transitions
  end

এটি এখনও সংরক্ষিত রেকর্ডগুলির জন্য মানটিকে আরম্ভ করে না, তবে এটি আপনার নিজের initবা যা কিছু দিয়ে ঘূর্ণায়মানের চেয়ে কিছুটা পরিষ্কার এবং আপনি আপনার সমস্ত স্ট্যাটাসের জন্য স্কোপের মতো অ্যাসেমের অন্যান্য সুবিধাগুলি কাটাবেন।



0

আমি "ডিফল্ট_মূল্য_ত" রত্নটি দৃ strongly়তার সাথে পরামর্শ দিচ্ছি: https://github.com/FooBarWidget/default_value_for

কিছু জটিল পরিস্থিতি রয়েছে যার জন্য প্রারম্ভিক পদ্ধতিটি ওভাররাইডের প্রয়োজন হয় যা এই রত্নটি করে।

উদাহরণ:

আপনার ডিবি ডিফল্ট ন্যূনাল, আপনার মডেল / রুবি-সংজ্ঞায়িত ডিফল্ট "কিছু স্ট্রিং", তবে আপনি যে কোনও কারণেই প্রকৃতপক্ষে মানটি নির্ধারণ করতে চান :MyModel.new(my_attr: nil)

এখানে বেশিরভাগ সমাধানগুলি মানটিকে শূন্য করতে সেট করতে ব্যর্থ হবে এবং এর পরিবর্তে এটি ডিফল্ট হিসাবে সেট করবে।

ঠিক আছে, সুতরাং ||=পদ্ধতির পরিবর্তে পরিবর্তে আপনি my_attr_changed?...

তবে এখন কল্পনা করুন যে আপনার ডিবি ডিফল্টটি "কিছু স্ট্রিং", আপনার মডেল / রুবি-সংজ্ঞায়িত ডিফল্টটি "কিছু অন্য স্ট্রিং", তবে একটি নির্দিষ্ট দৃশ্যের অধীনে আপনি মানটি "কিছু স্ট্রিং" (ডিবি ডিফল্ট) এ সেট করতে চান :MyModel.new(my_attr: 'some_string')

এই পরিণাম ডেকে আনবে my_attr_changed?হচ্ছে মিথ্যা কারণ মান ডিবি ডিফল্ট, যেটা ঘুরে ফিরে আপনার রুবি-সংজ্ঞায়িত ডিফল্ট কোড ফায়ার এবং "কিছু অন্যান্য STRING" মান সেট হবে ম্যাচ - আবার, না কি ইচ্ছা।


এই কারণে আমি মনে করি না যে এটি সঠিকভাবে একটি উত্তরোত্তর হুক দিয়ে সঠিকভাবে সম্পন্ন করা যেতে পারে।

আবার, আমার কাছে মনে হয় "ডিফল্ট_মূল্য_সামগ্রী" রত্ন সঠিক পন্থা গ্রহণ করছে: https://github.com/FooBarWidget/default_value_for


0

এখানে আমি যে সমাধানটি ব্যবহার করেছি যে আমি কিছুটা অবাক হয়েছিলাম তা এখনও যোগ করা যায় নি।

এটির দুটি অংশ রয়েছে। প্রথম অংশটি প্রকৃত স্থানান্তরে ডিফল্ট সেট করছে এবং দ্বিতীয় অংশটি উপস্থিতি সত্য কিনা তা নিশ্চিত করে মডেলটিতে একটি বৈধতা যুক্ত করছে।

add_column :teams, :new_team_signature, :string, default: 'Welcome to the Team'

সুতরাং আপনি এখানে দেখতে পাবেন যে ডিফল্ট ইতিমধ্যে সেট করা আছে। এখন যাচাইকরণের মধ্যে আপনি নিশ্চিত করতে চান যে স্ট্রিংয়ের জন্য সর্বদা একটি মান রয়েছে, তাই ঠিক করুন

 validates :new_team_signature, presence: true

এটি যা করবে তা আপনার জন্য ডিফল্ট মান সেট করে। (আমার জন্য আমার কাছে "দলে স্বাগতম"), এবং তারপরে এটি আরও একধাপ এগিয়ে যাবে এবং নিশ্চিত হবে যে সেই বস্তুর জন্য সর্বদা একটি মান উপস্থিত রয়েছে।

আশা করি এইটি কাজ করবে!


0
# db/schema.rb
create_table :store_listings, force: true do |t|
  t.string :my_string, default: "original default"
end

StoreListing.new.my_string # => "original default"

# app/models/store_listing.rb
class StoreListing < ActiveRecord::Base
  attribute :my_string, :string, default: "new default"
end

StoreListing.new.my_string # => "new default"

class Product < ActiveRecord::Base
  attribute :my_default_proc, :datetime, default: -> { Time.now }
end

Product.new.my_default_proc # => 2015-05-30 11:04:48 -0600
sleep 1
Product.new.my_default_proc # => 2015-05-30 11:04:49 -0600

-2

রেল 3 এ ডিফল্ট_স্কোপ ব্যবহার করুন

এপিআই ডক

অ্যাক্টিভেকর্ড্ড ডেটাবেজে (স্কিমা) সংজ্ঞায়িত ডিফল্টিং এবং অ্যাপ্লিকেশন (মডেল) এ ডিফল্ট হওয়া মধ্যে পার্থক্যকে অস্পষ্ট করে। প্রারম্ভিককরণের সময় এটি ডাটাবেস স্কিমাটিকে বিশ্লেষণ করে এবং সেখানে নির্দিষ্ট করা কোনও ডিফল্ট মান নোট করে। পরে, অবজেক্ট তৈরি করার সময়, এটি ডাটাবেস স্পর্শ না করে স্কিমা-নির্দিষ্ট ডিফল্ট মানগুলি বরাদ্দ করে।

আলোচনা


আপনি যদি মেটা_ কোথাও ব্যবহার করেন, ত্রুটির কারণে ডিফল্ট_স্কোপ নতুন এআর অবজেক্টগুলিকে ডিফল্ট নির্ধারণের জন্য কাজ করতে পারে না।
ভিক্টর ট্রান

এই মেটা_ কোথাও ইস্যুটি এখন ঠিক করা হয়েছে [ metautonomous.lightthouseapp.com/projects/53011/tickets/…
ভিক্টর ট্রান

3
ব্যবহার করবেন না default_scope। এটি আপনার সমস্ত প্রশ্নের দ্বারা আপনার সেট করা ক্ষেত্রটিতে এই শর্তটি যুক্ত করবে। এটি আপনি যা চান তা প্রায় কখনও নয়।
ব্র্যাড

@ ব্র্যাড, মজার আপনি উল্লেখ করেছেন, আমি পুরোপুরি একমত, এটি খারাপ)। আমার মন্তব্যটি স্ট্যাকওভারফ্লো / প্রশ্নগুলি 10/600845/… দেখুন
ভিক্টর ট্রেন

-3

এপিআই ডক্স থেকে http://api.rubyonrails.org/classes/ActtiveRecord/Callbacks.htmlbefore_validation আপনার মডেলটিতে পদ্ধতিটি ব্যবহার করুন , এটি আপনাকে কলগুলি তৈরি এবং আপডেট করার জন্য নির্দিষ্ট সূচনা তৈরির বিকল্প দেয় যেমন এই উদাহরণে (আবার কোড নেওয়া হয়েছে) এপিআই ডক্স উদাহরণ থেকে) নম্বর ক্ষেত্রটি ক্রেডিট কার্ডের জন্য শুরু করা হয়। আপনি যে মানটি চান সেট করতে সহজেই এটিকে মানিয়ে নিতে পারেন

class CreditCard < ActiveRecord::Base
  # Strip everything but digits, so the user can specify "555 234 34" or
  # "5552-3434" or both will mean "55523434"
  before_validation(:on => :create) do
    self.number = number.gsub(%r[^0-9]/, "") if attribute_present?("number")
  end
end

class Subscription < ActiveRecord::Base
  before_create :record_signup

  private
    def record_signup
      self.signed_up_on = Date.today
    end
end

class Firm < ActiveRecord::Base
  # Destroys the associated clients and people when the firm is destroyed
  before_destroy { |record| Person.destroy_all "firm_id = #{record.id}"   }
  before_destroy { |record| Client.destroy_all "client_of = #{record.id}" }
end

অবাক হলেন যে তাঁর এখানে পরামর্শ দেওয়া হয়নি


অবিলম্বে অবৈধতা অব্যাহত রাখার জন্য প্রস্তুত না হওয়া অবধি ডিফল্ট সেট করবে না। যদি প্রক্রিয়াটি চালিয়ে যাওয়ার আগে ডিফল্টগুলি পড়তে হয় তবে মানগুলি প্রস্তুত হবে না be
মিমেল

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