একটি অ্যাক্টিভেকর্ড রেকর্ড নকল করার সহজতম উপায় কী?


411

প্রক্রিয়াটির একটি একক ক্ষেত্র পরিবর্তন করে ( আইডি ছাড়াও ) আমি একটি অ্যাক্টিভেকর্ড রেকর্ডের একটি অনুলিপি তৈরি করতে চাই । এটি সম্পাদন করার সহজ উপায় কী?

আমি বুঝতে পেরেছি যে আমি একটি নতুন রেকর্ড তৈরি করতে পারি এবং তারপরে ক্ষেত্রের প্রতিটি ক্ষেত্রের ডেটা ফিল্ড-বাই-ফিল্ড অনুলিপি করতে পারি - তবে আমি বুঝতে পেরেছিলাম এটি করার একটি সহজ উপায় থাকতে হবে ...

যেমন:

 @newrecord=Record.copy(:id)  *perhaps?*

উত্তর:


622

অনুলিপি পেতে, ক্লোনটি (বা রেল 3.1+ এর জন্য ডুপ) ব্যবহার করুন:

# rails < 3.1
new_record = old_record.clone

#rails >= 3.1
new_record = old_record.dup

তারপরে আপনি যে কোনও ক্ষেত্রটি পরিবর্তন করতে পারেন।

অ্যাক্টিভেকর্ড আপনাকে একটি স্বাক্ষরিত আইডি সহ একটি নতুন (ডিবিতে সংরক্ষণ করা হয়নি) রেকর্ড দেওয়ার জন্য বিল্ট-ইন অবজেক্ট # ক্লোনটিকে ওভাররাইড করে
মনে রাখবেন এটি সংঘগুলি অনুলিপি করে না, সুতরাং আপনার প্রয়োজন হলে আপনাকে এটি ম্যানুয়ালি করতে হবে।

রেল 3.1 ক্লোনটি একটি অগভীর অনুলিপি, পরিবর্তে ডুপ ব্যবহার করুন ...


6
এটি এখনও কি 3.3.0.beta কারাগারে কাজ করে? আমি যখন q = p.clone, এবং তারপর p == q, আমি trueফিরে পেতে । অন্যদিকে q = p.dup, আমি যদি ব্যবহার করি তবে falseতাদের তুলনা করার সময় আমি ফিরে আসি।
অটোমল্টস

1
ক্লোনটিতে থাকা রেল ৩.১ ডক্সটি বলে যে এটি এখনও কাজ করে, তবে আমি রেলগুলি ৩.১.০. আরসি 4 ব্যবহার করছি এবং এমনকি new?পদ্ধতিটিও কাজ করছে না।
তুরাদগ

12
দেখে মনে হচ্ছে এই কার্যকারিতাটি ডুপের
skattyadz

74
অবশ্যই ক্লোন ব্যবহার করবেন না। যেহেতু অন্যান্য পোস্টারগুলি ক্লোন পদ্ধতিটি উল্লিখিত হয়েছে এখন কার্নেল # ক্লোন ব্যবহার করার জন্য প্রতিনিধিত্ব করে যা আইডিটি অনুলিপি করবে। অ্যাক্টিভেকর্ড :: বেস # এখন থেকে ডুপ ব্যবহার করুন
ব্র্যাডগোনসার্ফিং

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

74

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

old_task = Task.find (Task_id)
new_task = Task.new (old_task.attributes. विस (scheduled: তফসিল_অন => কিছু_ নতুন_সামান্য}))

সঙ্গে একটি নতুন টাস্ক তৈরি করবে :id => nil, :scheduled_on => some_new_dateএবং অন্যান্য সব গুণাবলীর মূল কাজটি হিসাবে একই। Task.new ব্যবহার করে আপনাকে স্পষ্টভাবে সেভ কল করতে হবে, তাই আপনি যদি এটি স্বয়ংক্রিয়ভাবে সংরক্ষণ করতে চান তবে Task.new কে Task.create এ পরিবর্তন করুন।

শান্তি বর্ষিত হোক।


5
বি / সি আপনি WARNING: Can't mass-assign protected attributes: id, due_date, created_at, updated_at
কীভাবে

যখন আমি এটি করি, আমি একটি কলামের সাথে একটি কলামের সাথে একটি অজানা বৈশিষ্ট্য ত্রুটি পেয়েছি কারণ সেখানে has_many সম্পর্কের কারণে রয়েছে column এই কাছাকাছি কোন উপায় আছে?
রুবেন মার্টিনেজ জুনিয়র

2
@RubenMartineJr। আমি জানি এটি একটি পুরানো পোস্ট, তবে হ্যাশ বৈশিষ্ট্যগুলিতে '। ছাড়া' ব্যবহার করে আপনি এটিকে পেতে পারেন: new_task = Task.new (old_task.attributes.except (: গুণমান_ইউ_ডন্ট_ওয়ান্ট: অন্য_এইডিডব্লু)। নিমজ্জিত (scheduled: সময়সূচী_আন) => some_new_date}))
Ninigi

@ ফিলিপকোবি আপনাকে ধন্যবাদ - তবে আমি যদি আইডিটি ফাঁকা না করতে চাই তবে কী হবে? আমি চাই যখন আমি সদৃশ তৈরি করি তখন রেলগুলি স্বয়ংক্রিয়ভাবে একটি নতুন আইডি বরাদ্দ করে - এটি কি সম্ভব?
বিকেএসপুরগাঁও

1
old_task.attribtes দুর্ভাগ্যক্রমে আইডি ক্ষেত্রটি বরাদ্দ করে। এটি আমার পক্ষে কাজ করছে না
বিকেএসপুরজিওন

32

আপনি অ্যাক্টিভেকর্ড 3.2 এর জন্য অ্যামিবা রত্নটিও পছন্দ করতে পারেন ।

আপনার যদি, আপনি সম্ভবত ব্যবহার করতে চাই nullify, regexবা prefixকনফিগারেশন ডিএসএল পাওয়া অপশন।

এটা সহজ এবং স্বয়ংক্রিয় রিকার্সিভ অনুলিপি সমর্থন has_one, has_manyএবং has_and_belongs_to_manyসমিতি, ক্ষেত্র প্রাক-প্রক্রিয়াকরণ ও একটি অত্যন্ত নমনীয় ও শক্তিশালী কনফিগারেশন ডিএসএল উভয় মডেল প্রয়োজন এবং মাছি উপর প্রয়োগ করা যেতে পারে।

অ্যামিবা ডকুমেন্টেশন যাচাই করে নেওয়ার বিষয়টি নিশ্চিত হন তবে ব্যবহার বেশ সহজ ...

মাত্র

gem install amoeba

বা যোগ করুন

gem 'amoeba'

আপনার গেমফিল

তারপরে আপনার মডেলটিতে অ্যামিবা ব্লক যুক্ত করুন এবং dupযথারীতি পদ্ধতিটি চালান

class Post < ActiveRecord::Base
  has_many :comments
  has_and_belongs_to_many :tags

  amoeba do
    enable
  end
end

class Comment < ActiveRecord::Base
  belongs_to :post
end

class Tag < ActiveRecord::Base
  has_and_belongs_to_many :posts
end

class PostsController < ActionController
  def some_method
    my_post = Post.find(params[:id])
    new_post = my_post.dup
    new_post.save
  end
end

আপনি কোন ক্ষেত্রটি বিভিন্ন উপায়ে অনুলিপি করতে পারেন তা নিয়ন্ত্রণ করতে পারেন তবে উদাহরণস্বরূপ, আপনি যদি মন্তব্যগুলি নকল হতে বাধা দিতে চান তবে আপনি একই ট্যাগগুলি বজায় রাখতে চান তবে আপনি এরকম কিছু করতে পারেন:

class Post < ActiveRecord::Base
  has_many :comments
  has_and_belongs_to_many :tags

  amoeba do
    exclude_field :comments
  end
end

আপনি উভয় উপসর্গ এবং প্রত্যয় পাশাপাশি regexes সঙ্গে স্বতন্ত্রতা নির্দেশ করতে সহায়তা করতে ক্ষেত্রগুলি প্রিপ্রসেস করতে পারেন। এছাড়াও, এখানে আরও অনেকগুলি বিকল্প রয়েছে যাতে আপনি আপনার উদ্দেশ্যটির জন্য সর্বাধিক পঠনযোগ্য স্টাইলে লিখতে পারেন:

class Post < ActiveRecord::Base
  has_many :comments
  has_and_belongs_to_many :tags

  amoeba do
    include_field :tags
    prepend :title => "Copy of "
    append :contents => " (copied version)"
    regex :contents => {:replace => /dog/, :with => "cat"}
  end
end

সমিতির পুনরাবৃত্তি অনুলিপি সহজ, কেবল শিশু মডেলগুলিতে অ্যামিবা সক্ষম করুন

class Post < ActiveRecord::Base
  has_many :comments

  amoeba do
    enable
  end
end

class Comment < ActiveRecord::Base
  belongs_to :post
  has_many :ratings

  amoeba do
    enable
  end
end

class Rating < ActiveRecord::Base
  belongs_to :comment
end

কনফিগারেশন ডিএসএলে আরও আরও বিকল্প রয়েছে, তাই ডকুমেন্টেশন পরীক্ষা করে দেখতে ভুলবেন না।

উপভোগ করুন! :)


দুর্দান্ত উত্তর। বিস্তারিত জানার জন্য ধন্যবাদ!
ডেরেক প্রিয়ার

ধন্যবাদ এটি কাজ করে !! তবে আমার একটি প্রশ্ন আছে যে ক্লোন করা বস্তুটি সংরক্ষণ করার আগে আমি কীভাবে ক্লোনিংয়ের সাথে নতুন এন্ট্রি যুক্ত করব?
মোহাম্মদ আনাস

1
এখানে একটি ঠিক। সঠিক পদ্ধতি .amoeba_dup, শুধু না .dup। আমি এই কোডটি কার্যকর করার চেষ্টা করছিলাম তবে এটি এখানে কাজ করছে না।
ভিক্টর

31

অ্যাক্টিভেকর্ড :: বেস # ডুপ ব্যবহার করুন যদি আপনি আইডিটি অনুলিপি করতে চান না


1
উপরের স্বীকৃত উত্তর অনুসারে @ থোরিন, দেখেছেন এটি রেলগুলির সঠিক পদ্ধতির মতো দেখাচ্ছে <3.1 হল.clone
ড্যান ওয়েভার

24

আমি সাধারণত বৈশিষ্ট্যগুলি অনুলিপি করি, আমার যা কিছু পরিবর্তন করতে হবে তা পরিবর্তন করে:

new_user = User.new(old_user.attributes.merge(:login => "newlogin"))

যখন আমি এটি করি, unknown attributeএকটি কলামের সাথে একটি ত্রুটি পেয়েছি কারণ সেখানে একটি কলাম রয়েছে যা একটি has_many সম্পর্কের কারণে। এই কাছাকাছি কোন উপায় আছে?
রুবেন মার্টিনেজ জুনিয়র

Rails4 সহ, এটি রেকর্ডটির জন্য একটি অনন্য আইডি তৈরি করে না
বেন

4
রেল 4 দিয়ে একটি নতুন রেকর্ড তৈরি করতে, করুন User.create(old_user.attributes.merge({ login: "newlogin", id: nil }))। এটি সঠিক ইউনিক আইডি সহ একটি নতুন ব্যবহারকারীর সংরক্ষণ করবে।
রাজেশএম

কারাগুলিতে হ্যাশ # বাদে এবং হ্যাশ # স্লাইস রয়েছে , সম্ভাব্যভাবে প্রস্তাবিত পদ্ধতিটিকে সবচেয়ে শক্তিশালী এবং কম ত্রুটি-প্রবণ করে তোলে। অতিরিক্ত লিবস যুক্ত করার দরকার নেই, প্রসারিত করা সহজ।
কুচাহাবে

10

আপনার যদি সমিতিগুলির সাথে একটি গভীর অনুলিপি প্রয়োজন হয় তবে আমি গভীর_ক্লোনযোগ্য রত্নের প্রস্তাব দিই


আমিও. আমি এই রত্নটি চেষ্টা করেছিলাম এবং এটি প্রথমবার ব্যবহার হয়েছিল, ব্যবহার করা খুব সহজ।
রব

4

5 রেলগুলিতে আপনি কেবল এটির মতো সদৃশ অবজেক্ট বা রেকর্ড তৈরি করতে পারেন।

new_user = old_user.dup

2

সহজে উপায়:

#your rails >= 3.1 (i was done it with Rails 5.0.0.1)
  o = Model.find(id)
 # (Range).each do |item|
 (1..109).each do |item|
   new_record = o.dup
   new_record.save
 end

অথবা

# if your rails < 3.1
 o = Model.find(id)
 (1..109).each do |item|
   new_record = o.clone
   new_record.save
 end     

2

#dupউদাহরণের সদৃশটি কাস্টমাইজ করতে এবং সম্পর্কের সদৃশকে অন্তর্ভুক্ত করার জন্য এখানে অ্যাক্টিভেকর্ড পদ্ধতির ওভাররাইডের একটি নমুনা রয়েছে:

class Offer < ApplicationRecord
  has_many :offer_items

  def dup
    super.tap do |new_offer|

      # change title of the new instance
      new_offer.title = "Copy of #{@offer.title}"

      # duplicate offer_items as well
      self.offer_items.each { |offer_item| new_offer.offer_items << offer_item.dup }
    end
  end
end

দ্রষ্টব্য: এই পদ্ধতিতে কোনও বাহ্যিক রত্নের প্রয়োজন হয় না তবে এর জন্য #dupপ্রয়োগ করা পদ্ধতি সহ নতুন অ্যাক্টিভেকর্ড সংস্করণ প্রয়োজন


0

আপনি ক্রিয়াকলাপ_ও_হায়ারযোগ্য রত্ন পরীক্ষা করতে পারেন ।

"প্রেরিত হিসেবে উত্তরাধিকারসূত্রে একটি রুবি জহর বিশেষভাবে পাগল / ActiveRecord মডেলের জন্য লিখিত হয়। এটা সঙ্গে ব্যবহার করা বোঝানো হয় স্ব-উল্লেখ এসোসিয়েশন , অথবা একটি মডেল যা ভাগ উত্তরাধিকারসূত্রে বৈশিষ্ট্যাবলী একটি পিতা বা মাতা থাকার সঙ্গে। এই যদি আপনার কোন অ্যাট্রিবিউট উত্তরাধিকারী বা দেব অভিভাবক মডেল থেকে সম্পর্ক। "

acts_as_inheritableআপনার মডেলগুলিতে যুক্ত করে আপনার এই পদ্ধতিগুলিতে অ্যাক্সেস পাবেন:

inherit_attributes

class Person < ActiveRecord::Base

  acts_as_inheritable attributes: %w(favorite_color last_name soccer_team)

  # Associations
  belongs_to  :parent, class_name: 'Person'
  has_many    :children, class_name: 'Person', foreign_key: :parent_id
end

parent = Person.create(last_name: 'Arango', soccer_team: 'Verdolaga', favorite_color:'Green')

son = Person.create(parent: parent)
son.inherit_attributes
son.last_name # => Arango
son.soccer_team # => Verdolaga
son.favorite_color # => Green

inherit_relations

class Person < ActiveRecord::Base

  acts_as_inheritable associations: %w(pet)

  # Associations
  has_one     :pet
end

parent = Person.create(last_name: 'Arango')
parent_pet = Pet.create(person: parent, name: 'Mango', breed:'Golden Retriver')
parent_pet.inspect #=> #<Pet id: 1, person_id: 1, name: "Mango", breed: "Golden Retriver">

son = Person.create(parent: parent)
son.inherit_relations
son.pet.inspect # => #<Pet id: 2, person_id: 2, name: "Mango", breed: "Golden Retriver">

আশা করি এটি আপনাকে সহায়তা করতে পারে।


0

যেহেতু আরও যুক্তি থাকতে পারে, কোনও মডেলের নকল করার সময়, আমি একটি নতুন ক্লাস তৈরি করার পরামর্শ দেব, যেখানে আপনি প্রয়োজনীয় সমস্ত যুক্তি পরিচালনা করেন। এটিকে সহজ করতে, এমন এক রত্ন রয়েছে যা সাহায্য করতে পারে: ক্লাউন

তাদের নথিপত্রের উদাহরণ অনুসারে, কোনও ব্যবহারকারী মডেলের জন্য:

class User < ActiveRecord::Base
  # create_table :users do |t|
  #  t.string :login
  #  t.string :email
  #  t.timestamps null: false
  # end

  has_one :profile
  has_many :posts
end

আপনি আপনার ক্লোনার ক্লাস তৈরি করেছেন:

class UserCloner < Clowne::Cloner
  adapter :active_record

  include_association :profile, clone_with: SpecialProfileCloner
  include_association :posts

  nullify :login

  # params here is an arbitrary Hash passed into cloner
  finalize do |_source, record, params|
    record.email = params[:email]
  end
end

class SpecialProfileCloner < Clowne::Cloner
  adapter :active_record

  nullify :name
end

এবং তারপরে এটি ব্যবহার করুন:

user = User.last
#=> <#User(login: 'clown', email: 'clown@circus.example.com')>

cloned = UserCloner.call(user, email: 'fake@example.com')
cloned.persisted?
# => false

cloned.save!
cloned.login
# => nil
cloned.email
# => "fake@example.com"

# associations:
cloned.posts.count == user.posts.count
# => true
cloned.profile.name
# => nil

প্রকল্প থেকে অনুলিপি করা উদাহরণ, তবে এটি আপনি কী অর্জন করতে পারবেন তার একটি পরিষ্কার দৃষ্টি দেবে।

দ্রুত এবং সাধারণ রেকর্ডের জন্য আমি এখানে যাব:

Model.new(Model.last.attributes.reject {|k,_v| k.to_s == 'id'}

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