অ্যাক্টিভেকর্ড :: রিলেশন অবজেক্টের অ্যারে রূপান্তর করা


106

আমার কাছে একটি অ্যারে অবজেক্ট রয়েছে, আসুন এটির নাম দিন Indicator। আমি def self.subjectsএই অ্যারেতে সূচক শ্রেণির পদ্ধতিগুলি ( বিভিন্ন, স্কোপ ইত্যাদি) চালাতে চাই । গ্রুপের অবজেক্টগুলিতে ক্লাসের পদ্ধতিগুলি চালানোর জন্য আমি কেবল একটাই উপায় তাদের অ্যাক্টিভেকর্ড :: রিলেশন হতে পারি। সুতরাং আমি একটি to_indicatorsপদ্ধতি যোগ করার অবলম্বন শেষ Array

def to_indicators
  # TODO: Make this less terrible.
  Indicator.where id: self.pluck(:id)
end

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

all.to_indicators.applicable_for_bank(id).each do |indicator|
  total += indicator.residual_risk_for(id)
  indicator_count += 1 if indicator.completed_by?(id)
end

আমি অনুমান করি যে এই কনডেন্সগুলি দুটি প্রশ্নে নেমে এসেছে।

  1. কীভাবে আমি অবজেক্টের অ্যারেটিকে একটি অ্যাক্টিভেকর্ড :: রিলেশনে রূপান্তর করতে পারি? সাধারণত whereপ্রতিটি সময় না করে।
  2. def self.subjectsঅ্যাক্টিভেকর্ড :: সম্পর্কিত ক্ষেত্রে কোনও ধরণের পদ্ধতি চালানোর সময় , আমি কীভাবে সেই অ্যাক্টিভেকর্ড :: সম্পর্কিত অবজেক্টটি অ্যাক্সেস করব?

ধন্যবাদ আমার যদি কিছু পরিষ্কার করার দরকার হয় তবে আমাকে জানান।


4
যদি সেই অ্যারেটিকে কোনও সম্পর্কের কাছে ফিরিয়ে আনার চেষ্টা করার একমাত্র কারণ যদি আপনি এটি পেয়েছেন তবে অ্যান্ড্রু মার্শালের উত্তরটি ইঙ্গিত .allকরার .scopedমতো ব্যবহার করুন (যদিও রেল 4 এ এটি কাজ করবে .all)। নিজেকে যদি কোনও সম্পর্কের জন্য কোনও অ্যারে পরিণত করার প্রয়োজন মনে হয় আপনি কোথাও ভুল হয়ে গেছেন ...
nzifnab

উত্তর:


46

কীভাবে আমি অবজেক্টের অ্যারেটিকে একটি অ্যাক্টিভেকর্ড :: রিলেশনে রূপান্তর করতে পারি? সাধারণত প্রতিটি সময় যেখানেই না করা উচিত।

আপনি কোনও অ্যারেকে একটি অ্যাক্টিভেকর্ডে রূপান্তর করতে পারবেন না: সম্পর্কিত যেহেতু রিলেশন একটি এসকিউএল ক্যোয়ারির জন্য কেবল একজন নির্মাতা এবং এর পদ্ধতিগুলি প্রকৃত ডেটাতে কাজ করে না।

তবে, আপনি যা চান তা যদি সম্পর্ক হয় তবে:

  • অ্যাক্টিভেকর্ড 3.x এর জন্য, কল allএবং পরিবর্তে কল করবেন না scoped, যা রিলেশনটি ফিরিয়ে দেবে যা আপনাকে একই allঅ্যারে রেকর্ড উপস্থাপন করে যা একই রেকর্ড উপস্থাপন করে ।

  • অ্যাক্টিভেকর্ড 4.x এর জন্য, কেবল কল করুন all, যা রিলেশন দেয়।

def self.subjectsঅ্যাক্টিভেকর্ড :: সম্পর্কিত ক্ষেত্রে কোনও ধরণের পদ্ধতি চালানোর সময় , আমি কীভাবে সেই অ্যাক্টিভেকর্ড :: সম্পর্কিত অবজেক্টটি অ্যাক্সেস করব?

পদ্ধতিটি যখন কোনও রিলেশন অবজেক্টে ডাকা হয় তখন সেই selfসম্পর্ক (মডেল শ্রেণীর বিপরীতে এটি সংজ্ঞায়িত হয়)।


4
সমাধান সম্পর্কে নীচে @ মার্কো প্রিনস দেখুন।
জাস্টিন

রেলপথে 5 পুশ অবজ্ঞাত পদ্ধতি সম্পর্কে কি
জস্বিন্দর

@ GstjiSaini আপনি যে সঠিক পদ্ধতিটি উল্লেখ করছেন তা সম্পর্কে আমি অনিশ্চিত, দয়া করে ডক বা উত্সের লিঙ্ক সরবরাহ করুন। যদিও, যদি এটি অবহেলা করা হয় তবে খুব কার্যকর সমাধান নয় কারণ এটি সম্ভবত খুব শীঘ্রই চলে যাবে।
অ্যান্ড্রু মার্শাল

এবং সে কারণেই আপনি এটি করতে পারেন class User; def self.somewhere; where(location: "somewhere"); end; end, তবেUser.limit(5).somewhere
ডরিয়ান

এটিই কেবলমাত্র উত্তর যা সত্যিকার অর্থেই ওপিকে আলোকিত করে। অ্যাক্টিভেকর্ড কীভাবে কাজ করে সে সম্পর্কে প্রশ্নটি ত্রুটিযুক্ত জ্ঞান প্রকাশ করে। @ জাস্টিন কেবলমাত্র তাদের উপরের মানচিত্র তৈরি করতে এবং অন্য অপ্রয়োজনীয় ক্যোয়ারী তৈরির জন্য কেন চারপাশের বস্তুর অ্যারে পাস করা খারাপ তা সম্পর্কে বোঝার অভাবকে কেবলই জোরদার করছেন।
james2m

162

আপনি অবজেক্টের একটি অ্যারেকে arrএকটি অ্যাক্টিভেকর্ডে রূপান্তর করতে পারেন :: এই জাতীয় সম্পর্ক (ধরে নিচ্ছেন যে আপনি জানেন যে কোন শ্রেণীর অবজেক্টগুলি, সম্ভবত আপনি যা করছেন)

MyModel.where(id: arr.map(&:id))

আপনাকে whereযদিও ব্যবহার করতে হবে , এটি একটি দরকারী সরঞ্জাম যা আপনাকে ব্যবহার করতে অনিচ্ছুক হওয়া উচিত নয়। এবং এখন আপনার কাছে একটি ওলাইনার রয়েছে যাতে একটি অ্যারেটিকে সম্পর্কের সাথে রূপান্তরিত করে।

map(&:id)আপনার আইটেমের অ্যারেগুলিকে কেবল তাদের আইডি রয়েছে এমন একটি অ্যারেতে পরিণত করবে। এবং যেখানে অ্যারে পাস করার ফলে ক্লজটি একটি এসকিউএল স্টেটমেন্ট জেনারেট করে INএমন কিছু দেখায়:

SELECT .... WHERE `my_models`.id IN (2, 3, 4, 6, ....

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


4
ঠিক আছে, ঠিক আমার যা দরকার ছিল। আপনি এটি মডেলটির কোনও বৈশিষ্ট্যের জন্য ব্যবহার করতে পারেন। আমার জন্য পুরোপুরি কাজ করে।
nfriend21

7
আপনি যখন করতে পারেন তখন কেন আক্ষরিক এসকিউএল তৈরি করবেন where(id: arr.map(&:id))? এবং কঠোরভাবে বলতে গেলে, এটি অ্যারেটিকে কোনও সম্পর্কের সাথে রূপান্তরিত করে না, পরিবর্তে সেই আইডিগুলির সাথে বস্তুর নতুন দৃষ্টান্ত পাওয়া যায় (একবার সম্পর্কটি উপলব্ধি হয়ে যায়) যা ইতিমধ্যে অ্যারেতে থাকা মেমরির উদাহরণগুলির চেয়ে আলাদা বৈশিষ্ট্যযুক্ত মান থাকতে পারে।
অ্যান্ড্রু মার্শাল

8
যদিও এটি ক্রম হারায়।
ভেলিজার হরিস্টভ

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

9
খুব অদক্ষ! আপনি অ্যাক্সেসের জন্য একটি ডাটাবেস ক্যোয়ারী করতে যাচ্ছেন এমন মেমরির মধ্যে ইতিমধ্যে থাকা অবজেক্টগুলির একটি সংকলন আপনি পরিণত করেছেন। আপনি যে শ্রেণীর পদ্ধতিগুলি অ্যারেতে পুনরাবৃত্তি করতে চান তা আমি পুনর্বিবেচনার দিকে নজর দেব।
james2m 15

4

ওয়েল, আমার ক্ষেত্রে, আমাকে অবজেক্টগুলির একটি অ্যারেটি অ্যাক্টিভেকর্ড :: রিলেশন- তে রূপান্তর করার পাশাপাশি একটি নির্দিষ্ট কলামের সাথে বাছাই করতে হবে (উদাহরণস্বরূপ আইডি)। যেহেতু আমি মাইএসকিউএল ব্যবহার করছি তাই ক্ষেত্রের কাজটি সহায়ক হতে পারে।

MyModel.where('id in (?)',ids).order("field(id,#{ids.join(",")})") 

এসকিউএল দেখতে:

SELECT ... FROM ... WHERE (id in (11,5,6,7,8,9,10))  
ORDER BY field(id,11,5,6,7,8,9,10)

মাইএসকিউএল ফিল্ড ফাংশন


পোস্টগ্র্রেএসকিউএল এর সাথে কাজ করে এমন একটি সংস্করণের জন্য, এই থ্রেডের চেয়ে আর কোনও দিকে তাকান না: stackoverflow.com/questions/1309624/…
আর্মচেয়ারডজ

অ্যাক্টিভেকর্ড :: স্টেটমেন্টআইনওয়েড (পিজি :: টুম্যানিআরগমেন্টস: এআরআরআর: কোনও ফাংশনে 100 টির বেশি আর্গুমেন্ট পাস করতে পারে না) এই কর্মফলটি 100 টিরও বেশি আর্গুমেন্টের সাথে দাঁড়াতে পারে না, সুতরাং এটি 100, আইডির মতো মোট দৈর্ঘ্যের সম্পর্কের সাথে কাজ করে এবং 12 একে অপরের থেকে পৃথক করা হবে না।
আন্তন সেমিনিচেনকো

তাহলে MyModel.where(id: ids)?
coisnepe

1

ActiveRecord::Relation ডাটাবেস ক্যোয়ারিকে বাঁধায় যা ডাটাবেস থেকে ডেটা পুনরুদ্ধার করে।

ধরা যাক বোঝার জন্য, আমাদের একই শ্রেণীর অবজেক্টের সাথে অ্যারে রয়েছে, তবে আমরা কোন কোয়েরিতে তাদের বেঁধে রাখি বলে মনে করি?

আমি যখন দৌড়ে যাই,

users = User.where(id: [1,3,4,5])
  User Load (0.6ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` IN (1, 3, 4, 5)  ORDER BY created_at desc

এখানে উপরের দিকে, usersপ্রত্যাবর্তন Relationবস্তু কিন্তু এর পিছনে ডাটাবেস ক্যোয়ারী আবদ্ধ করে আপনি এটি দেখতে পারেন,

users.to_sql
 => "SELECT `users`.* FROM `users` WHERE `users`.`id` IN (1, 3, 4, 5)  ORDER BY created_at desc"

সুতরাং ActiveRecord::Relationsql ক্যোয়ারী থেকে পৃথক থাকা বস্তুর অ্যারে থেকে ফিরে আসা সম্ভব নয় ।


0

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

এখানে বলা হচ্ছে আমার সমাধান, আমি Arrayক্লাস বাড়িয়েছি

# lib/core_ext/array.rb

class Array

  def to_activerecord_relation
    return ApplicationRecord.none if self.empty?

    clazzes = self.collect(&:class).uniq
    raise 'Array cannot be converted to ActiveRecord::Relation since it does not have same elements' if clazzes.size > 1

    clazz = clazzes.first
    raise 'Element class is not ApplicationRecord and as such cannot be converted' unless clazz.ancestors.include? ApplicationRecord

    clazz.where(id: self.collect(&:id))
  end
end

একটি ব্যবহার উদাহরণ হবে array.to_activerecord_relation.update_all(status: 'finished')। এখন আমি কোথায় এটি ব্যবহার করব?

কখনও কখনও আপনি ফিল্টার আউট প্রয়োজন ActiveRecord::Relationউদাহরণস্বরূপ সম্পূর্ণ না উপাদানগুলি গ্রহণ। এই ক্ষেত্রে সুযোগটি ব্যবহার করা সবচেয়ে ভাল elements.not_finishedএবং আপনি এখনও তা চালিয়ে যাবেন ActiveRecord::Relation

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

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