কীভাবে রেলগুলিতে ডিফল্ট মান সেট করবেন?


108

আমি রেলগুলিতে অবজেক্টের জন্য ডিফল্ট মান নির্ধারণ করার সর্বোত্তম উপায়টি সন্ধান করার চেষ্টা করছি।

আমি যেটি সবচেয়ে ভাল ভাবতে পারি তা হ'ল newনিয়ামকটিতে পদ্ধতির ডিফল্ট মান সেট করা ।

যদি এটি গ্রহণযোগ্য হয় বা এটির আরও ভাল উপায় আছে তবে কারও কাছে কি কোনও ইনপুট রয়েছে?


1
এই জিনিসগুলি কি কি; তারা কিভাবে গ্রাস / ব্যবহার করা হয়? তারা দর্শন দেওয়ার সময় বা নিয়ন্ত্রণকারী যুক্তির জন্য ব্যবহৃত হয়?
গিশু

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

যেহেতু গৃহীত এবং সর্বাধিক উত্তরগুলি অ্যাক্টিভেকর্ডগুলিতে ফোকাস করে, আমরা ধরে নিই যে আসল প্রশ্নটি অ্যাকিটভেকর্ডস সম্পর্কে ছিল। এর ফলে সম্ভাব্য প্রতিলিপির stackoverflow.com/questions/328525/...
সিরো Santilli郝海东冠状病六四事件法轮功

উত্তর:


98

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

class SetDefault < ActiveRecord::Migration
  def self.up
    change_column :people, :last_name, :type, :default => "Doe"
  end

  def self.down
    # You can't currently remove default values in Rails
    raise ActiveRecord::IrreversibleMigration, "Can't remove the default"
  end
end

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

তবে, যদি আপনি নির্দিষ্ট ক্ষেত্রে কেবল ডিফল্ট মানগুলি সেট করতে চান - বলুন, এটি উত্তরাধিকার সূত্রে প্রাপ্ত মডেল যা অন্য কারও সাথে একটি টেবিল ভাগ করে - অন্য একটি মার্জিত উপায় হ'ল মডেল অবজেক্টটি তৈরি হওয়ার সময় এটি সরাসরি আপনার রেল কোডে করা:

class GenericPerson < Person
  def initialize(attributes=nil)
    attr_with_defaults = {:last_name => "Doe"}.merge(attributes)
    super(attr_with_defaults)
  end
end

তারপরে, যখন আপনি একটি করেন GenericPerson.new(), এটি সর্বদা "ডো" বৈশিষ্ট্যটিকে ট্র্যাক করবে Person.new()যতক্ষণ না আপনি এটিকে অন্য কোনও কিছু দিয়ে ওভাররাইড করে।


2
চেষ্টা করে দেখুন এটি .newক্লাস পদ্ধতিতে ডাকা নতুন মডেল অবজেক্টগুলিতে কাজ করবে । অ্যাক্টিভেকর্ড সরাসরি কলিং সম্পর্কে সেই ব্লগ পোস্টের আলোচনাটি .allocateছিল ডেটাবেস থেকে বিদ্যমান ডেটা সহ লোড হওয়া মডেল অবজেক্ট সম্পর্কে। ( এবং আইটিএমও অ্যাক্টিভেকর্ডের পক্ষে এটি কাজ করা একটি ভয়ানক ধারণা But তবে এটি বিন্দুর পাশে
beside

2
আপনি যদি মূল পোস্টারের প্রশ্নটি আবার নিকিতা এবং তারপরে আমার মন্তব্যগুলি যথাযথভাবে পড়তে পিছনে সরে যান তবে তা আপনার কাছে আরও বোধগম্য হতে পারে। যদি না ... ঠিক আছে, প্রশ্নের উত্তর দেওয়া হয়েছে। আপনার দিনটি শুভ হোক.
এসএফলে

8
ডাউন মাইগ্রেশনের জন্য আরও ভাল: change_column_default :people, :last_name, nil স্ট্যাকওভারফ্লো.com
নোলান অ্যামি

9
দয়া করে নোট করুন যে নতুন রেল সংস্করণগুলির জন্য আপনার ডিফল্ট প্যারামিটারের আগে অতিরিক্ত ধরণের পরামিতি প্রয়োজন। অনুসন্ধান করুন: এই পৃষ্ঠায় টাইপ করুন।
বেন হুইলার

3
@ জোয়েলব্রেওয়ার আজ আমি এটিতে ছুটে এসেছি - 4 রেলগুলির জন্য, আপনাকে কলামের change_column :people, :last_name, :string, default: "Doe"
ধরণও

56

এসএফএলির উত্তরের ভিত্তিতে, নতুন রেল সংস্করণগুলির জন্য এখানে একটি আপডেট / স্থির একটি রয়েছে:

class SetDefault < ActiveRecord::Migration
  def change
    change_column :table_name, :column_name, :type, default: "Your value"
  end
end

2
সাবধান থাকুন এটি ails.২.x রেলগুলিতে কাজ করে না (পরবর্তী সংস্করণগুলিতে পরীক্ষা করা হয়নি)। যেমনটি change_columnবেশ "স্ট্রাকচারিং" হতে পারে, বিপরীত অপারেশনটি হ্রাস করা যায় না। আপনি যদি নিশ্চিত না হন, তাহলে শুধু চলমান দ্বারা এটি পরীক্ষা db:migrateএবং db:rollbackঅধিকার পরে। উত্তরটি একই ফলাফল হিসাবে স্বীকৃত তবে কমপক্ষে এটি ধরে নেওয়া হয়েছে!
gfd

1
এটি আমার জন্য সঠিক উত্তর .. এটি রেল 5.1 এর সাথে কাজ করে তবে আপনাকে যা করতে হবে upএবং downউপরের বর্ণিত @ গুবস্টো
ফ্যাব্রিজিও

22

সবার আগে আপনি ওভারলোড করতে পারবেন না initialize(*args) কারণ এটি সমস্ত ক্ষেত্রে বলা হয় না।

আপনার সেরা বিকল্পটি হ'ল আপনার মাইগ্রেশনে আপনার ডিফল্ট স্থাপন করা:

add_column :accounts, :max_users, :integer, :default => 10

দ্বিতীয়টি হ'ল আপনার মডেলটিতে ডিফল্ট স্থাপন করা তবে এটি কেবল প্রাথমিক বৈশিষ্ট্যগুলির সাথেই কাজ করবে। আমি যেমন booleanকলামগুলি দিয়েছিলাম তেমন সমস্যা হতে পারে :

def after_initialize
  if new_record?
    max_users ||= 10
  end
end

তোমার দরকার new_record?আপনার এটির তাই ডিফল্টগুলি ডেটাবেস থেকে লোড হওয়া মানগুলিকে ওভাররাইড না করে।

আপনি প্রয়োজন ||=আরম্ভ পদ্ধতি মধ্যে পাস পরামিতি অগ্রাহ্য থেকে পাগল থামাতে।


12
সামান্য নোট - আপনি দুটি জিনিস করতে চান: .... 1) আপনার পদ্ধতিটি_পরে নামকরণ করুন না। আপনি চান after_initiation :your_method_name.... 2 টি ব্যবহারself.max_users ||= 10
জেসি ওলগ্যামট

5
বুলিয়ানদের জন্য, কেবল এটি করুন: প্রোপ = সত্য যদি প্রোপ.নিল?
ফ্রান্সিস পটার

2
বা এর after_initialize doপরিবর্তেdef after_initialize
ফোটানাস

self.max_users নিরাপদ থাকতে।
কেন রতানাচাই এস।

15

আপনি change_column_defaultনিজের স্থানান্তরগুলিতেও চেষ্টা করতে পারেন (ails.২.৮ রেলগুলিতে পরীক্ষিত):

class SetDefault < ActiveRecord::Migration
  def up
    # Set default value
    change_column_default :people, :last_name, "Smith"
  end

  def down
    # Remove default
    change_column_default :people, :last_name, nil
  end
end

change_column_default রেলগুলি API ডক্স


1
গৃহীত উত্তরটি আরও সম্পূর্ণ তবে আমি এই পরিষ্কার এবং ডকুমেন্টেড একটি পছন্দ করি ... ধন্যবাদ!
gfd

7

আপনি যদি অ্যাক্টিভেকর্ড অবজেক্টের উল্লেখ করছেন তবে আপনার এটি করার দুটি উপায় (আরও বেশি) রয়েছে:

1. একটি: ডিবিতে ডিফল্ট প্যারামিটার ব্যবহার করুন

ই জি

class AddSsl < ActiveRecord::Migration
  def self.up
    add_column :accounts, :ssl_enabled, :boolean, :default => true
  end

  def self.down
    remove_column :accounts, :ssl_enabled
  end
end

এখানে আরও তথ্য: http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

2. একটি কলব্যাক ব্যবহার করুন

ই জি before_validation_on_create

এখানে আরও তথ্য: http://api.rubyonrails.org/class/ActtiveRecord/Callbacks.html#M002147


2
ডাটাবেসটিতে ডিফল্ট ব্যবহার করে সমস্যাটি সেভাবে সংরক্ষণ না করেও সেট আপ হয় না? যদি আমি জনগণের ডিফল্টগুলির সাথে একটি নতুন অবজেক্ট তৈরি করতে চাই তবে আমার সেগুলি আরম্ভকারীতে সেট করা দরকার।
রাফ

বুলিয়ান 1 বা 0 তে ডিফল্ট হতে পারে না - সেগুলি অবশ্যই সত্য বা মিথ্যাতে সেট করা আবশ্যক (সিলাসজের উত্তর দেখুন)।
জ্যামন হলমগ্রেন

@ জ্যামনহোলমগ্রেন এই মন্তব্যের জন্য ধন্যবাদ, আমি উত্তরটি সংশোধন করেছি :)
ভ্লাদ জ্লোোটানু

সমস্যা নেই @ ভ্ল্যাডজলোটানু
জ্যামন হল্মগ্রেন

7

after_initializeঅ্যাক্টিভেকর্ড কলব্যাক ব্যবহার করে রুবে অন ​​রেলস v3.2.8 এ, আপনি আপনার মডেলটিতে এমন একটি পদ্ধতি কল করতে পারেন যা কোনও নতুন অবজেক্টের জন্য ডিফল্ট মান নির্ধারণ করবে।

after_initialize কলব্যাক প্রতিটি বস্তুর জন্য ট্রিগার করা হয় যা সন্ধানকারী দ্বারা খুঁজে পাওয়া যায় এবং তা ইনস্ট্যান্ট করা হয়, সাথে সাথে ইনটাইটেলাইজ করা নতুন অবজেক্টগুলি ইনস্ট্যান্ট করার পরে ট্রিগার করা হয় ( অ্যাক্টিভেকর্ড কলব্যাকস দেখুন )।

সুতরাং, আইএমও এটির মতো দেখতে হবে:

class Foo < ActiveRecord::Base
  after_initialize :assign_defaults_on_new_Foo
  ...
  attr_accessible :bar
  ...
  private
  def assign_defaults_on_new_Foo
    # required to check an attribute for existence to weed out existing records
    self.bar = default_value unless self.attribute_whose_presence_has_been_validated
  end
end

Foo.bar = default_valueএই উদাহরণটির জন্য উদাহরণটি যদি না থাকে তবে attribute_whose_presence_has_been_validatedসেভ / আপডেটে কোনও পূর্ববর্তী থাকে । default_valueতারপর ব্যবহার ফর্ম রেন্ডার করতে আপনার ভিউ সাথে ব্যবহার করা হবে default_valueজন্যbar অ্যাট্রিবিউট।

সর্বোপরি এটি হ্যাকি ...

সম্পাদনা - 'new_record?' কোনও নতুন কল থেকে ইনস্ট্যান্ট করছে কিনা তা পরীক্ষা করতে

কোনও অ্যাট্রিবিউট মানটি পরীক্ষা করার পরিবর্তে new_record?রেলগুলি সহ অন্তর্নির্মিত পদ্ধতিটি ব্যবহার করুন । সুতরাং, উপরের উদাহরণটি দেখতে হবে:

class Foo < ActiveRecord::Base
  after_initialize :assign_defaults_on_new_Foo, if: 'new_record?'
  ...
  attr_accessible :bar
  ...
  private
  def assign_defaults_on_new_Foo
    self.bar = default_value
  end
end

এটি অনেক পরিষ্কার। আহ, রেলগুলির যাদু - এটি আমার চেয়ে স্মার্ট।


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

1
আপনি after_initializeএখানে কলব্যাকের প্রস্তাব দিচ্ছেন কেন ? কলব্যাকগুলিতে রেল ডকুমেন্টেশনের before_createঅতিরিক্ত শর্ত পরীক্ষা ছাড়াই ডিফল্ট মান নির্ধারণের উদাহরণ রয়েছে
Dfr

@ ডিএফআর - আমি অবশ্যই এটি মিস করেছি, আপনি কি আমাকে পর্যালোচনা করার জন্য একটি লিঙ্ক ফেলে দিতে পারেন এবং আমি উত্তরটি আপডেট করব ...
ত্রুটিযুক্ত

হ্যাঁ, এখানে api.rubyonrails.org/classes/ActtiveRecord/Callbacks.html প্রথম উদাহরণ, বর্গSubscription
ডিফার

5
@ ডিএফআর - কলব্যাকের after_initializeপরিবর্তে আমরা যে কারণটি ব্যবহার before_createকরছি তা হ'ল আমরা যখন নতুন বস্তু তৈরি করছি তখন ব্যবহারকারীর জন্য (একটি দৃশ্যে ব্যবহারের জন্য) একটি ডিফল্ট মান সেট করতে চাই । before_createকলব্যাক বলা হয় পরে ব্যবহারকারী একটি নতুন অবজেক্ট পরিবেশিত হয়েছে, তাদের ইনপুট প্রদান করা, এবং কন্ট্রোলার সৃষ্টির জন্য বস্তু জমা দেওয়া হয়েছে। কন্ট্রোলার তারপরে যেকোন before_createকলব্যাকের জন্য পরীক্ষা করে । এটি পাল্টা স্বজ্ঞাত বলে মনে হচ্ছে তবে এটি একটি নামকরণ বিষয় - ক্রিয়াকে before_createবোঝায় create। কোনও নতুন অবজেক্ট ইনস্ট্যান্ট করা আপত্তি করে না create
ত্রুটিপূর্ণ

5

কমপক্ষে ails.২..6 বেলার বুলিয়ান ক্ষেত্রগুলির জন্য, এটি আপনার মাইগ্রেশনে কাজ করবে।

def change
  add_column :users, :eula_accepted, :boolean, default: false
end

একটি 1বা 0ডিফল্ট রেখে দেওয়া এখানে কাজ করবে না, কারণ এটি একটি বুলিয়ান ক্ষেত্র। এটি অবশ্যই একটি trueবা falseমান হওয়া উচিত ।


4

আপনি যদি কোনও মডেলটির সাথে লেনদেন করছেন তবে আপনি রেল 5+ এ অ্যাট্রিবিউটস এপিআই ব্যবহার করতে পারেন http://api.rubyonrails.org/class/ActtiveRecord/Atributes/ClassMethods.html#method-i-attribute

একটি উপযুক্ত কলামের নাম সহ একটি স্থানান্তর যুক্ত করুন এবং তারপরে মডেলটিতে এটি সেট করুন:

class StoreListing < ActiveRecord::Base
  attribute :country, :string, default: 'PT'
end

2

একটি স্থানান্তর এবং ব্যবহার উত্পন্ন change_column_default, সংক্ষিপ্ত এবং বিপরীত হয়:

class SetDefaultAgeInPeople < ActiveRecord::Migration[5.2]
  def change
    change_column_default :people, :age, { from: nil, to: 0 }
  end
end

1

আপনি যদি ডেটাবেস ব্যাক মডেলটির নির্দিষ্ট বৈশিষ্ট্যের জন্য কেবলমাত্র ডিফল্ট সেট করে থাকেন তবে আমি এসকিএল ডিফল্ট কলাম মানগুলি ব্যবহার করব - আপনি কি ধরণের ডিফল্ট ব্যবহার করছেন তা স্পষ্ট করে বলতে পারেন?

এটি পরিচালনা করার জন্য অনেকগুলি পন্থা রয়েছে, এই প্লাগইনটি একটি আকর্ষণীয় বিকল্পের মতো দেখায়।


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

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

1

নতুন / আরম্ভ করার উদ্দেশ্যে ওভাররাইড করার পরামর্শ সম্ভবত অসম্পূর্ণ। রেলগুলি (ঘন ঘন) অ্যাক্টিভেকর্ড অবজেক্টের জন্য কল বরাদ্দ করবে এবং বরাদ্দের কলগুলি আরম্ভের কলগুলির ফলাফল করবে না।

আপনি যদি অ্যাক্টিভেকর্ড অবজেক্টের কথা বলছেন, পরে_অনিটায়ালাইজ ওভাররাইডে একবার দেখুন।

এই ব্লগ পোস্টগুলি (আমার নয়) দরকারী:

ডিফল্ট মানগুলি ডিফল্ট কনস্ট্রাক্টরদের ডাকা হয় না

[সম্পাদনা করুন: এসএফলে উল্লেখ করেছেন যে মেমরিতে কোনও নতুন অবজেক্টটি ইনস্ট্যান্ট করে দিলে রেলগুলি আসলে ডেটাবেজে ডিফল্টটিকে দেখে - আমি তা বুঝতে পারি নি]]


1

আমার যেমন ডিবিতে ডিফল্ট কলাম মান হিসাবে নির্দিষ্ট করা হয়েছিল ঠিক তেমন একটি ডিফল্ট সেট করা দরকার। সুতরাং এটি এরকম আচরণ করে

a = Item.new
a.published_at # => my default value

a = Item.new(:published_at => nil)
a.published_at # => nil

কারণ যুক্তি থেকে বৈশিষ্ট্য নির্ধারণের পরে কল্পনাটিকে কল্পনা করার পরে কল করা হয়, বৈশিষ্ট্যটি কখনই সেট করা হয়নি বা এটি ইচ্ছাকৃতভাবে শূন্য হিসাবে সেট করা হয়নি বলে শোধ করার কোনও উপায় ছিল না। সুতরাং আমি কিছুটা ভিতরে ঝুঁকতে হয়েছিল এবং এই সহজ সমাধানটি নিয়ে এসেছি।

class Item < ActiveRecord::Base
  def self.column_defaults
    super.merge('published_at' => Time.now)
  end
end

আমার জন্য দুর্দান্ত কাজ করে (রেল ৩.২.x)


1

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

def status
  self['name_of_var'] || 'desired_default_value'
end

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


0

আমি এখানে একটি অনুরূপ প্রশ্নের উত্তর দিয়েছি .. এটির জন্য একটি পরিষ্কার উপায় হল রেলগুলি ব্যবহার করা হচ্ছে_অ্যাক্সেসর_ওয়াইথ_ডিফল্ট

class SOF
  attr_accessor_with_default :is_awesome,true
end

sof = SOF.new
sof.is_awesome

=> true

হালনাগাদ

Attr_accessor_with_default কে ৩.২ টি কারাগারে ছাড় দেওয়া হয়েছে .. আপনি খাঁটি রুবির পরিবর্তে এটি করতে পারেন

class SOF
  attr_writer :is_awesome

  def is_awesome
    @is_awesome ||= true
  end
end

sof = SOF.new
sof.is_awesome

#=> true

attr_accessor_with_defaultরেল> 3.1.0 হিসাবে অবহিত করা হয়েছে
ফ্লাইন ফিশ

আপনার উদাহরণে, @ আইসোভাল == মিথ্যা থাকা সত্ত্বেও is_awesome সর্বদা সত্য হবে।
রিচি

0

আপনি যদি অ্যাক্টিভেকর্ড অবজেক্টের কথা বলছেন তবে আমি 'অ্যাট্রিবিউট-ডিফল্ট' রত্ন ব্যবহার করি।

ডকুমেন্টেশন এবং ডাউনলোড: https://github.com/bsm/attribute-deafults



-3

আপনি অ্যাক্টিভেকর্ড মডেলটির জন্য কনস্ট্রাক্টরকে ওভাররাইড করতে পারেন।

এটার মত:

def initialize(*args)
  super(*args)
  self.attribute_that_needs_default_value ||= default_value
  self.attribute_that_needs_another_default_value ||= another_default_value
  #ad nauseum
end

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