क्या किसी मॉडल की आईडी वैल्यू को ओवरराइड करने का कोई तरीका है? कुछ इस तरह:
Post.create(:id => 10, :title => 'Test')
आदर्श होगा, लेकिन स्पष्ट रूप से काम नहीं करेगा।
क्या किसी मॉडल की आईडी वैल्यू को ओवरराइड करने का कोई तरीका है? कुछ इस तरह:
Post.create(:id => 10, :title => 'Test')
आदर्श होगा, लेकिन स्पष्ट रूप से काम नहीं करेगा।
जवाबों:
आईडी सिर्फ attr_protected है, यही वजह है कि आप इसे सेट करने के लिए बड़े पैमाने पर असाइनमेंट का उपयोग नहीं कर सकते हैं। हालाँकि, इसे मैन्युअल रूप से सेट करते समय, यह सिर्फ काम करता है:
o = SomeObject.new
o.id = 8888
o.save!
o.reload.id # => 8888
मुझे यकीन नहीं है कि मूल प्रेरणा क्या थी, लेकिन मैं यह तब करता हूं जब ActiveHash मॉडल को ActiveRecord में परिवर्तित कर रहा हूं। ActiveHash आपको ActiveRecord में समान ही__ शब्दार्थ का उपयोग करने की अनुमति देता है, लेकिन माइग्रेशन होने और तालिका बनाने के बजाय, और हर कॉल पर डेटाबेस के ओवरहेड को लाइक करने के बाद, आप बस अपना डेटा yml फ़ाइलों में संग्रहीत करते हैं। डेटाबेस में विदेशी कुंजियाँ yml में इन-मेमोरी आईडी का संदर्भ देती हैं।
ActiveHash पिकलिस्ट्स और छोटे तालिकाओं के लिए बहुत अच्छा है जो अक्सर बदलते रहते हैं और केवल डेवलपर्स द्वारा बदलते हैं। इसलिए जब ActiveHash से ActiveRecord में जा रहे हैं, तो बस सभी विदेशी कुंजी संदर्भों को समान रखना आसान है।
ActiveRecord::VERSION::STRING == "3.2.11"
यहाँ (sqlite3 एडेप्टर के साथ) और मेरे लिए उपरोक्त काम करता है।
प्रयत्न
a_post = Post.new do |p|
p.id = 10
p.title = 'Test'
p.save
end
आपको वह देना चाहिए जो आप खोज रहे हैं।
आप भी कुछ इस तरह का उपयोग कर सकते हैं:
Post.create({:id => 10, :title => 'Test'}, :without_protection => true)
यद्यपि डॉक्स में कहा गया है , यह बड़े पैमाने पर असाइनमेंट सुरक्षा को बायपास करेगा।
रेल के लिए 4:
Post.create(:title => 'Test').update_column(:id, 10)
अन्य रेल 4 उत्तर मेरे काम नहीं आए । उनमें से कई दिखाई दिएरेल कंसोल का उपयोग करते समय परिवर्तन करने के लिए , लेकिन जब मैंने MySQL डेटाबेस में मूल्यों की जांच की, तो वे अपरिवर्तित रहे। अन्य उत्तर केवल कभी-कभी काम करते थे।
MySQL के लिए कम से कम, id
ऑटो इंक्रीमेंट आईडी नंबर से नीचे असाइन करना तब तक काम नहीं करता है जब तक आप उपयोग नहीं करते हैं update_column
। उदाहरण के लिए,
p = Post.create(:title => 'Test')
p.id
=> 20 # 20 was the id the auto increment gave it
p2 = Post.create(:id => 40, :title => 'Test')
p2.id
=> 40 # 40 > the next auto increment id (21) so allow it
p3 = Post.create(:id => 10, :title => 'Test')
p3.id
=> 10 # Go check your database, it may say 41.
# Assigning an id to a number below the next auto generated id will not update the db
यदि आप create
उपयोग करने के लिए बदलते हैं new
+ save
तो भी आपको यह समस्या होगी। मैन्युअल रूप से id
जैसे बदल रहा हैp.id = 10
भी इस समस्या पैदा करता है।
सामान्य तौर पर, मैं एक अतिरिक्त डेटाबेस क्वेरी की लागत के बावजूद भी इसे update_column
बदलने के लिए उपयोग करूंगा id
क्योंकि यह हर समय काम करेगा। यह एक त्रुटि है जो आपके विकास के माहौल में दिखाई नहीं दे सकती है, लेकिन काम करते हुए यह कहकर चुपचाप अपने उत्पादन डेटाबेस को भ्रष्ट कर सकती है।
Post.new.update(id: 10, title: 'Test')
वास्तव में, यह पता चला है कि निम्नलिखित कार्य करना:
p = Post.new(:id => 10, :title => 'Test')
p.save(false)
validate: false
बस के बजाय पास करते हैं false
। हालाँकि, आप अभी भी संरक्षित विशेषता के मुद्दे पर चलते हैं - वहाँ एक अलग तरीका है जो मैंने अपने उत्तर में उल्लिखित किया है।
जैसा कि जेफ़ बताते हैं, आईडी ऐसा व्यवहार करता है मानो attr_protected है। इसे रोकने के लिए, आपको डिफ़ॉल्ट संरक्षित विशेषताओं की सूची को ओवरराइड करना होगा। कहीं भी ऐसा करने में सावधानी बरतें कि विशेषता जानकारी बाहर से आ सकती है। आईडी फ़ील्ड डिफ़ॉल्ट रूप से किसी कारण से सुरक्षित है।
class Post < ActiveRecord::Base
private
def attributes_protected_by_default
[]
end
end
(ActiveRecord 2.3.5 के साथ परीक्षण किया गया)
हम विशेषताएँ_प्रकारित_बाह्य_ ओवरफ़ॉल्ट को ओवरराइड कर सकते हैं
class Example < ActiveRecord::Base
def self.attributes_protected_by_default
# default is ["id", "type"]
["type"]
end
end
e = Example.new(:id => 10000)
Post.create!(:title => "Test") { |t| t.id = 10 }
यह मुझे उस तरह की चीज के रूप में नहीं मारता है, जिसे आप सामान्य रूप से करना चाहते हैं, लेकिन यह बहुत अच्छी तरह से काम करता है यदि आपको आईडी के एक निश्चित सेट के साथ तालिका को पॉप्युलेट करने की आवश्यकता है (उदाहरण के लिए जब एक रेक कार्य का उपयोग करके चूक बनाते हैं) और आप ऑटो-इन्क्रिमेंटिंग को ओवरराइड करना चाहते हैं (ताकि हर बार जब आप कार्य को चलाएं तो टेबल एक ही आईडी से आबाद हो):
post_types.each_with_index do |post_type|
PostType.create!(:name => post_type) { |t| t.id = i + 1 }
end
इस create_with_id फ़ंक्शन को अपने seeds.rb के शीर्ष पर रखें और फिर इसका उपयोग अपने ऑब्जेक्ट निर्माण के लिए करें जहाँ स्पष्ट आईडी वांछित हैं।
def create_with_id(clazz, params)
obj = clazz.send(:new, params)
obj.id = params[:id]
obj.save!
obj
end
और इसे इस तरह से उपयोग करें
create_with_id( Foo, {id:1,name:"My Foo",prop:"My other property"})
के बजाय का उपयोग करने का
Foo.create({id:1,name:"My Foo",prop:"My other property"})
यह मामला एक ऐसा ही मुद्दा है जो id
एक तरह की कस्टम तिथि के साथ आवश्यक था :
# in app/models/calendar_block_group.rb
class CalendarBlockGroup < ActiveRecord::Base
...
before_validation :parse_id
def parse_id
self.id = self.date.strftime('%d%m%Y')
end
...
end
और तब :
CalendarBlockGroup.create!(:date => Date.today)
# => #<CalendarBlockGroup id: 27072014, date: "2014-07-27", created_at: "2014-07-27 20:41:49", updated_at: "2014-07-27 20:41:49">
कॉलबैक ठीक काम करता है।
शुभ लाभ!।
id
यूनिक्स टाइम स्टैम्प पर आधारित बनाने की जरूरत थी । मैंने वह अंदर कर लिया है before_create
। ठीक काम करता है।
रेल 3 के लिए, इसे करने का सबसे सरल तरीका शोधन के new
साथ उपयोग करना है without_protection
, और फिर save
:
Post.new({:id => 10, :title => 'Test'}, :without_protection => true).save
बीज डेटा के लिए, यह सत्यापन को बायपास करने के लिए समझ में आता है जो आप इस तरह कर सकते हैं:
Post.new({:id => 10, :title => 'Test'}, :without_protection => true).save(validate: false)
हमने वास्तव में ActiveRecord :: सहायता के लिए एक सहायक विधि जोड़ी है, जो बीज फ़ाइलों को निष्पादित करने से तुरंत पहले घोषित किया जाता है:
class ActiveRecord::Base
def self.seed_create(attributes)
new(attributes, without_protection: true).save(validate: false)
end
end
और अब:
Post.seed_create(:id => 10, :title => 'Test')
रेल 4 के लिए, आपको संरक्षित विशेषताओं के बजाय स्ट्रांगपराम का उपयोग करना चाहिए। यदि यह मामला है, तो आप किसी भी झंडे को पारित किए बिना बस असाइन करने और सहेजने में सक्षम होंगे new
:
Post.new(id: 10, title: 'Test').save # optionally pass `{validate: false}`
{}
ऊपर शमूएल के जवाब (Rails3) के रूप में विशेषताओं को डाले बिना मेरे लिए काम नहीं करता है ।
id
अभी भी 10. है
id
10 के रूप में पारित किया गया था - इसलिए यह वास्तव में यही होना चाहिए। यदि वह नहीं है जो आप उम्मीद कर रहे थे, तो क्या आप एक उदाहरण के साथ स्पष्ट कर सकते हैं?