উত্তর:
সম্পাদনা: মন্তব্য এবং অন্যান্য উত্তর দেখুন। এই এক চেয়ে স্মার্ট উত্তর আছে! অথবা সম্প্রদায় উইকি হিসাবে এটিকে উন্নত করার চেষ্টা করুন।
মডেলগুলি কোনও মাস্টার অবজেক্টে নিজেকে নিবন্ধন করে না, সুতরাং না, মডেলগুলির তালিকায় নেই রেয়েলগুলি।
তবে আপনি এখনও আপনার অ্যাপ্লিকেশনটির মডেল ডিরেক্টরিগুলির বিষয়বস্তুটিতে সন্ধান করতে পারেন ...
Dir.foreach("#{RAILS_ROOT}/app/models") do |model_path|
# ...
end
সম্পাদনা: আরেকটি (বন্য) ধারণাটি হ'ল অ্যাক্টিভেকর্ড :: বেস প্রসারিত প্রতিটি শ্রেণীর সন্ধানের জন্য রুবি প্রতিবিম্ব ব্যবহার করা। আপনি কীভাবে সমস্ত ক্লাস তালিকাভুক্ত করতে পারেন তা জানেন না ...
সম্পাদনা: কেবল মজা করার জন্য, আমি সমস্ত ক্লাসের তালিকা করার একটি উপায় খুঁজে পেয়েছি
Module.constants.select { |c| (eval c).is_a? Class }
সম্পাদনা: পরিশেষে ডিরেক্টরিগুলি না দেখে সমস্ত মডেলের তালিকাতে সাফল্য পেয়েছে
Module.constants.select do |constant_name|
constant = eval constant_name
if not constant.nil? and constant.is_a? Class and constant.superclass == ActiveRecord::Base
constant
end
end
আপনি যদি উদ্ভূত শ্রেণিটিও পরিচালনা করতে চান তবে আপনাকে পুরো সুপারক্লাস চেইনটি পরীক্ষা করতে হবে। আমি ক্লাস ক্লাসে একটি পদ্ধতি যুক্ত করে এটি করেছি:
class Class
def extend?(klass)
not superclass.nil? and ( superclass == klass or superclass.extend? klass )
end
end
def models
Module.constants.select do |constant_name|
constant = eval constant_name
if not constant.nil? and constant.is_a? Class and constant.extend? ActiveRecord::Base
constant
end
end
end
RAILS_ROOT
3 টি আর Dir.glob(Rails.root.join('app/models/*'))
ActiveRecord::Base
এখনকার বংশধর হিসাবে নিজেকে নিবন্ধিত করে , তাই আপনি যদি সমস্ত মডেলকে আগ্রহী করেন তবে আপনি সেগুলি সহজেই পুনরাবৃত্তি করতে পারেন - নীচে আমার উত্তর দেখুন।
3, 4 এবং 5 রেলের পুরো উত্তরটি হ'ল:
যদি cache_classes
বন্ধ থাকে (ডিফল্টরূপে এটি বিকাশে বন্ধ থাকে তবে উত্পাদনে থাকে):
Rails.application.eager_load!
তারপর:
ActiveRecord::Base.descendants
এটি নিশ্চিত করে তোলে যে আপনার অ্যাপ্লিকেশনের সমস্ত মডেল তারা যেখানেই থাকুক না কেন, বোঝাই হয়েছে এবং মডেল সরবরাহকারী কোনও রত্নও লোড হয়েছে।
এটি ক্লাসগুলিতেও কাজ করবে যা উত্তরাধিকার সূত্রে প্রাপ্ত হয় ActiveRecord::Base
, যেমন ApplicationRecord
5 রেলের মতো , এবং কেবলমাত্র বংশধরদের সেই সাবট্রিকেই ফিরে আসতে পারে:
ApplicationRecord.descendants
এটি কীভাবে করা হয় সে সম্পর্কে আপনি যদি আরও জানতে চান তবে অ্যাক্টিভসপোর্ট :: ডেসেন্ডেন্টস ট্র্যাকার পরীক্ষা করে দেখুন ।
:environment
জন্য আপনার টাস্ককে নির্ভর করুন eager_load!
।
Rails.application.eager_load!
আপনি কেবলমাত্র মডেলগুলি লোড করতে পারেন:Dir.glob(Rails.root.join('app/models/*')).each do |x| require x end
Rails.paths["app/models"].existent
ডিরেক্টরি গ্লোব করুন । ইচ্ছুক পুরো অ্যাপ্লিকেশনটি লোড করা আরও সম্পূর্ণ উত্তর এবং এটি নিশ্চিত করবে যে মডেলগুলি সংজ্ঞায়িত করার মতো কোনও জায়গা নেই।
Rails.application.paths["app/models"].eager_load!
যে কেউ যদি এটিকে হোঁচট খায় তবে আমি আরও একটি সমাধান পেয়েছি, দির পড়ার উপর নির্ভর করে না ক্লাস ক্লাস বাড়িয়ে ...
ActiveRecord::Base.send :subclasses
এটি ক্লাসগুলির একটি অ্যারে ফিরিয়ে দেবে। সুতরাং আপনি তারপর করতে পারেন
ActiveRecord::Base.send(:subclasses).map(&:name)
ActiveRecord::Base.subclasses
তবে ব্যবহার করতে হবে send
? এছাড়াও, মনে হচ্ছে মডেলটি প্রদর্শিত হওয়ার আগে আপনাকে "স্পর্শ" করতে হবে, উদাহরণস্বরূপ c = Category.new
এবং এটি প্রদর্শিত হবে। অন্যথায়, এটি না।
ActiveRecord::Base.descendants
ActiveRecord::Base.descendants
তালিকাভুক্ত করার আগে তাদের "স্পর্শ" করতে হবে।
ActiveRecord::Base.connection.tables.map do |model|
model.capitalize.singularize.camelize
end
ফিরে আসবে
["Article", "MenuItem", "Post", "ZebraStripePerson"]
অতিরিক্ত তথ্য আপনি যদি মডেল ছাড়াই অবজেক্টের নামে কোনও পদ্ধতিতে কল করতে চান: স্ট্রিং অজানা পদ্ধতি বা পরিবর্তনশীল ত্রুটি এটি ব্যবহার করে
model.classify.constantize.attribute_names
ActiveRecord::Base.send :subclasses
- সারণীর নামগুলি অনুসন্ধান করা ভাল ধারণা। মডেল নামগুলি স্বয়ংক্রিয়ভাবে উত্পন্ন করা লোরেফন উল্লিখিত হিসাবে সমস্যা হতে পারে।
.capitalize.singularize.camelize
প্রতিস্থাপন করা যেতে পারে .classify
।
আমি এটি করার উপায়গুলি খুঁজছিলাম এবং এই উপায়টি পছন্দ করে শেষ করেছি:
in the controller:
@data_tables = ActiveRecord::Base.connection.tables
in the view:
<% @data_tables.each do |dt| %>
<br>
<%= dt %>
<% end %>
<br>
উত্স: http://portfo.li/rails/348561-how-can-one-list-all-database-tables-from-one-project
ActiveRecord::Base.connection.tables.each{|t| begin puts "%s: %d" % [t.humanize, t.classify.constantize.count] rescue nil end}
কিছু মডেল সক্রিয় হতে পারে না তাই আপনার এটি উদ্ধার করা দরকার।
model_classes = ActiveRecord::Base.connection.tables.collect{|t| t.classify.constantize rescue nil }.compact
জন্য Rails5 মডেল এখন উপশ্রেণী এর ApplicationRecord
তাই আপনার অ্যাপে সমস্ত মডেলের আপনাকে যা তালিকাটি পেতে:
ApplicationRecord.descendants.collect { |type| type.name }
বা সংক্ষিপ্ত:
ApplicationRecord.descendants.collect(&:name)
আপনি যদি ডেভ মোডে থাকেন তবে আপনাকে আগে উত্সাহী লোড মডেলগুলি প্রয়োজন:
Rails.application.eager_load!
আপনার কাছে টেবিল-কম মডেল না থাকলে @ হ্নোভিকের সমাধানটি দুর্দান্ত is এই সমাধানটি পাশাপাশি উন্নয়ন মোডেও কাজ করবে
আমার পন্থা যদিও সম্পূর্ণ ভিন্ন -
ActiveRecord::Base.connection.tables.map{|x|x.classify.safe_constantize}.compact
শ্রেণিবদ্ধকরণ আপনাকে স্ট্রিং থেকে ক্লাসের নামটি সঠিকভাবে দেবে বলে মনে করা হচ্ছে । সেফ_ কনটেনটিজ নিশ্চিত করে যে আপনি কোনও ব্যাতিক্রম ছাড়াই নিরাপদে শ্রেণিতে পরিণত করতে পারবেন। আপনার যদি ডাটাবেস টেবিলগুলি মডেল নয় তবে ক্ষেত্রে এটি প্রয়োজন। সংক্ষিপ্ত করুন যাতে অঙ্কের যে কোনও শূন্যস্থান সরানো হয়।
safe_constantize
।
আপনি যদি কেবল শ্রেণীর নাম চান:
ActiveRecord::Base.descendants.map {|f| puts f}
এটি কেবল রিয়েল কনসোলে চালান, আরও কিছু নয়। শুভকামনা!
সম্পাদনা: @ sj26 ঠিক আছে, বংশধরদের ডাকার আগে আপনাকে প্রথমে এটি চালানো দরকার:
Rails.application.eager_load!
map
সঙ্গে puts
? আমি পয়েন্টটি হওয়া উচিত নাActiveRecord::Base.descendants.map(&:model_name)
এটি আমার পক্ষে কাজ করে বলে মনে হচ্ছে:
Dir.glob(RAILS_ROOT + '/app/models/*.rb').each { |file| require file }
@models = Object.subclasses_of(ActiveRecord::Base)
রেলগুলি কেবল যখন মডেলগুলি ব্যবহৃত হয় তখন লোড করে, তাই Dir.glob লাইনে মডেল ডিরেক্টরিতে সমস্ত ফাইল "প্রয়োজন" হয়।
একবার আপনার অ্যারেতে মডেলগুলি পরে, আপনি যা ভাবছিলেন তা করতে পারেন (যেমন দেখুন কোড দেখুন):
<% @models.each do |v| %>
<li><%= h v.to_s %></li>
<% end %>
...'/app/models/**/*.rb'
এক লাইনে: Dir['app/models/\*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
Dir['**/models/**/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
ActiveRecord::Base.connection.tables
মাত্র একটি লাইনে:
ActiveRecord::Base.subclasses.map(&:name)
Rails.application.eager_load!
উন্নয়ন মোডে কার্যকর করার আগে প্রয়োজন needs
আমি এখনও মন্তব্য করতে পারি না, তবে আমার ধারণা sj26 উত্তরটি শীর্ষ উত্তর হওয়া উচিত। কেবল একটি ইঙ্গিত:
Rails.application.eager_load! unless Rails.configuration.cache_classes
ActiveRecord::Base.descendants
রেল R সহ , জেটিওয়ার্ক ডিফল্ট কোড লোডার হয়ে ওঠে।
আগ্রহী লোড করার জন্য, চেষ্টা করুন:
Zeitwerk::Loader.eager_load_all
তারপর
ApplicationRecord.descendants
হ্যাঁ এমন অনেকগুলি উপায় রয়েছে যা আপনি সমস্ত মডেলের নামগুলি সন্ধান করতে পারেন তবে আমি আমার রত্ন মডেল_ইনফোতে যা করেছি তা এটি রত্নগুলিতে অন্তর্ভুক্ত সমস্ত মডেল আপনাকে দেবে give
array=[], @model_array=[]
Rails.application.eager_load!
array=ActiveRecord::Base.descendants.collect{|x| x.to_s if x.table_exists?}.compact
array.each do |x|
if x.split('::').last.split('_').first != "HABTM"
@model_array.push(x)
end
@model_array.delete('ActiveRecord::SchemaMigration')
end
তারপর কেবল এটি মুদ্রণ করুন
@model_array
সমস্ত রেল প্রাক লোড এড়ানোর জন্য, আপনি এটি করতে পারেন:
Dir.glob("#{Rails.root}/app/models/**/*.rb").each {|f| require_dependency(f) }
আবশ্যক_নির্ভরতা (চ) একই Rails.application.eager_load!
ব্যবহার করে। এটি ইতিমধ্যে প্রয়োজনীয় ফাইল ত্রুটিগুলি এড়ানো উচিত।
তারপরে আপনি এআর মডেলগুলির তালিকা তৈরি করতে সমস্ত ধরণের সমাধান ব্যবহার করতে পারেন ActiveRecord::Base.descendants
একটি জটিল রেল অ্যাপ (যা একটি বিদ্যুতের স্কোয়ার) দ্বারা পরীক্ষা করা হয়েছে তার একটি সমাধান এখানে দেওয়া হয়েছে
def all_models
# must eager load all the classes...
Dir.glob("#{RAILS_ROOT}/app/models/**/*.rb") do |model_path|
begin
require model_path
rescue
# ignore
end
end
# simply return them
ActiveRecord::Base.send(:subclasses)
end
এটি এই থ্রেডের উত্তরের সেরা অংশ নেয় এবং এটিকে সহজতম এবং সবচেয়ে পুঙ্খানুপুঙ্খ সমাধানে একত্রিত করে। আপনার মডেলগুলি সাব-ডাইরেক্টরিগুলিতে রয়েছে এমন সেটগুলি হ্যান্ডেল করে, সেট_ টেবিল_নাম ব্যবহার করুন ইত্যাদি handle
আমি কেবল এই মডেলটিই দেখতে পেলাম, যেহেতু আমার সমস্ত মডেলগুলি তাদের গুণাবলী সহ মুদ্রণ করতে হবে (@ আদিত্য সঙ্ঘির মন্তব্যে নির্মিত):
ActiveRecord::Base.connection.tables.map{|x|x.classify.safe_constantize}.compact.each{ |model| print "\n\n"+model.name; model.new.attributes.each{|a,b| print "\n#{a}"}}
এটি আমার পক্ষে কাজ করেছে। উপরের সমস্ত পোস্টের জন্য বিশেষ ধন্যবাদ। এটি আপনার সমস্ত মডেলের একটি সংগ্রহ ফিরিয়ে আনবে।
models = []
Dir.glob("#{Rails.root}/app/models/**/*.rb") do |model_path|
temp = model_path.split(/\/models\//)
models.push temp.last.gsub(/\.rb$/, '').camelize.constantize rescue nil
end
Rails
কার্যকরী পদ্ধতি descendants
, কিন্তু মডেলের না অগত্যা কি কখনো থেকে উত্তরাধিকারী ActiveRecord::Base
, উদাহরণস্বরূপ, বর্গ যে মডিউল অন্তর্ভুক্তActiveModel::Model
একটি মডেল হিসাবে একই আচরণ করতে হবে, শুধু একটি টেবিল থেকে লিঙ্ক করা হবে না।
সুতরাং উপরের সহকর্মীদের যা বলে পরিপূরক, সামান্যতম প্রচেষ্টা এটি করবে:
Class
রুবির শ্রেণির বানর প্যাচ :
class Class
def extends? constant
ancestors.include?(constant) if constant != self
end
end
এবং পদ্ধতি models
পূর্বপুরুষ সহ :
পদ্ধতিটি ধীরে ধীরে পরিবর্তে Module.constants
(অতিমাত্রায়) একটি সংকলন দেয় symbols
, সুতরাং পদ্ধতিটি Array#select
এই বানরের প্যাচের মতো প্রতিস্থাপন করা যেতে পারে Module
:
class Module
def demodulize
splitted_trail = self.to_s.split("::")
constant = splitted_trail.last
const_get(constant) if defines?(constant)
end
private :demodulize
def defines? constant, verbose=false
splitted_trail = constant.split("::")
trail_name = splitted_trail.first
begin
trail = const_get(trail_name) if Object.send(:const_defined?, trail_name)
splitted_trail.slice(1, splitted_trail.length - 1).each do |constant_name|
trail = trail.send(:const_defined?, constant_name) ? trail.const_get(constant_name) : nil
end
true if trail
rescue Exception => e
$stderr.puts "Exception recovered when trying to check if the constant \"#{constant}\" is defined: #{e}" if verbose
end unless constant.empty?
end
def has_constants?
true if constants.any?
end
def nestings counted=[], &block
trail = self.to_s
collected = []
recursivityQueue = []
constants.each do |const_name|
const_name = const_name.to_s
const_for_try = "#{trail}::#{const_name}"
constant = const_for_try.constantize
begin
constant_sym = constant.to_s.to_sym
if constant && !counted.include?(constant_sym)
counted << constant_sym
if (constant.is_a?(Module) || constant.is_a?(Class))
value = block_given? ? block.call(constant) : constant
collected << value if value
recursivityQueue.push({
constant: constant,
counted: counted,
block: block
}) if constant.has_constants?
end
end
rescue Exception
end
end
recursivityQueue.each do |data|
collected.concat data[:constant].nestings(data[:counted], &data[:block])
end
collected
end
end
এর বানর প্যাচ String
।
class String
def constantize
if Module.defines?(self)
Module.const_get self
else
demodulized = self.split("::").last
Module.const_get(demodulized) if Module.defines?(demodulized)
end
end
end
এবং, অবশেষে, মডেল পদ্ধতি
def models
# preload only models
application.config.eager_load_paths = model_eager_load_paths
application.eager_load!
models = Module.nestings do |const|
const if const.is_a?(Class) && const != ActiveRecord::SchemaMigration && (const.extends?(ActiveRecord::Base) || const.include?(ActiveModel::Model))
end
end
private
def application
::Rails.application
end
def model_eager_load_paths
eager_load_paths = application.config.eager_load_paths.collect do |eager_load_path|
model_paths = application.config.paths["app/models"].collect do |model_path|
eager_load_path if Regexp.new("(#{model_path})$").match(eager_load_path)
end
end.flatten.compact
end
def load_models_in_development
if Rails.env == "development"
load_models_for(Rails.root)
Rails.application.railties.engines.each do |r|
load_models_for(r.root)
end
end
end
def load_models_for(root)
Dir.glob("#{root}/app/models/**/*.rb") do |model_path|
begin
require model_path
rescue
# ignore
end
end
end
আমি এই উত্তরগুলিতে অনেকগুলি ব্যর্থ হয়ে পরীক্ষা করেছি 4 রেলগুলিতে (বাহ godশ্বরের উদ্দেশ্যে তারা দুটি বা দুটি জিনিস বদলেছিল) আমি নিজের নিজের যুক্ত করার সিদ্ধান্ত নিয়েছি। যেগুলি অ্যাক্টিভেকর্ড :: বেসকোনেকশন নামে পরিচিত এবং টেবিলের নামগুলি টানা কাজ করেছে কিন্তু ফলাফলটি আমি পাইনি কারণ আমি কিছু মডেল (অ্যাপ / মডেলগুলির অভ্যন্তরের ফোল্ডারে) লুকিয়ে রেখেছি যা আমি চাইনি মুছে ফেলা:
def list_models
Dir.glob("#{Rails.root}/app/models/*.rb").map{|x| x.split("/").last.split(".").first.camelize}
end
আমি এটিকে একটি প্রারম্ভকালে রেখেছি এবং এটিকে যে কোনও জায়গা থেকে কল করতে পারি। অপ্রয়োজনীয় মাউস-ব্যবহার প্রতিরোধ করে।
ধরে নিই যে সমস্ত মডেল অ্যাপ্লিকেশন / মডেলগুলিতে রয়েছে এবং আপনার সার্ভারে আপনার গ্রেপ ও অ্যাডক রয়েছে (বেশিরভাগ ক্ষেত্রেই),
# extract lines that match specific string, and print 2nd word of each line
results = `grep -r "< ActiveRecord::Base" app/models/ | awk '{print $2}'`
model_names = results.split("\n")
এটি Rails.application.eager_load!
প্রতিটি ফাইলের চেয়ে দ্রুত বা লুপ করে Dir
।
সম্পাদনা করুন:
এই পদ্ধতির অসুবিধা হ'ল এটি এমন মডেলগুলিকে মিস করে যা অপ্রত্যক্ষভাবে অ্যাক্টিভেকর্ডের (যেমন FictionalBook < Book
) থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয় । সবচেয়ে নিশ্চিত উপায় হ'ল Rails.application.eager_load!; ActiveRecord::Base.descendants.map(&:name)
যদিও এটি ধীরে ধীরে ধীরে ধীরে।
কেউ যদি এটি দরকারী মনে করে তবে আমি এই উদাহরণটি এখানে ফেলছি। সমাধান এই উত্তরটির উপর ভিত্তি করে https://stackoverflow.com/a/10712838/473040 ।
ধরা যাক আপনি একটি কলাম আছে public_uid
যে বহির্বিশ্বের করার জন্য একটি প্রাথমিক আইডি হিসেবে ব্যবহার করা হয় (আপনি findjreasons কেন আপনি যে কাজ করতে চাইবেন পারেন এখানে )
এখন ধরা যাক আপনি বিদ্যমান ক্ষেত্রগুলির মডেলগুলির গোছায় এই ক্ষেত্রটি প্রবর্তন করেছেন এবং এখন আপনি সেট করা সমস্ত রেকর্ডগুলি পুনরায় তৈরি করতে চান। আপনি এই মত করতে পারেন
# lib/tasks/data_integirity.rake
namespace :di do
namespace :public_uids do
desc "Data Integrity: genereate public_uid for any model record that doesn't have value of public_uid"
task generate: :environment do
Rails.application.eager_load!
ActiveRecord::Base
.descendants
.select {|f| f.attribute_names.include?("public_uid") }
.each do |m|
m.where(public_uid: nil).each { |mi| puts "Generating public_uid for #{m}#id #{mi.id}"; mi.generate_public_uid; mi.save }
end
end
end
end
আপনি এখন চালাতে পারেন rake di:public_uids:generate