এই অ্যাক্টিভেকর্ড :: রিডইনলিরেকর্ড ত্রুটিটি কী কারণে ঘটছে?


203

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

start_cards = DeckCard.find :all, :joins => [:card], :conditions => ["deck_cards.deck_id = ? and cards.start_card = ?", @game.deck.id, true]  

এটি কাজ করে বলে মনে হচ্ছে। যাইহোক, আমি যখন এই ডেককার্ডগুলি অন্য সংঘে স্থানান্তরিত করার চেষ্টা করি তখন আমি অ্যাক্টিভেকর্ড :: রিডইনলিরেকর্ড ত্রুটি পাই।

এখানে কোড

for player in @game.players 
  player.tableau = Tableau.new
  start_card = start_cards.pop 
  start_card.draw_pile = false
  player.tableau.deck_cards << start_card  # the error occurs on this line
end

এবং প্রাসঙ্গিক মডেলগুলি (টেবিলের প্লেয়ারগুলি কার্ডের ঝালরাই)

class Player < ActiveRecord::Base
  belongs_to :game
  belongs_to :user
  has_one :hand
  has_one :tableau
end

class Tableau < ActiveRecord::Base
  belongs_to :player
  has_many :deck_cards
end  

class DeckCard < ActiveRecord::Base
  belongs_to :card
  belongs_to :deck  
end

আমি এই কোডের ঠিক পরে DeckCardsখেলোয়াড়দের হাতে যোগ করার পরে একই ধরণের কাজ করছি এবং সেই কোডটি ঠিকঠাকভাবে কাজ করছে। belongs_to :tableauডেককার্ড মডেলটিতে আমার প্রয়োজন আছে কিনা তা নিয়ে আমি ভাবছিলাম , তবে প্লেয়ারের হাতে যোগ করার জন্য এটি ঠিক কাজ করে। ডেককার্ড টেবিলটিতে আমার একটি tableau_idএবং hand_idকলাম রয়েছে।

আমি রেল এপিআইতে রিডইনলিআরকার্ডটি সন্ধান করেছি এবং এটি বিবরণের বাইরে খুব বেশি কিছু বলে না।

উত্তর:


283

রেলগুলি ২.৩.৩ এবং তার চেয়ে কম

অ্যাক্টিভেকর্ডCHANGELOG থেকে (v1.12.0, অক্টোবর 16, 2005) :

কেবল পঠনযোগ্য রেকর্ডগুলি উপস্থাপন করুন। যদি আপনি অবজেক্ট.আরেডনালি কল করেন! তারপরে এটি অবজেক্টটিকে কেবল পঠনযোগ্য হিসাবে চিহ্নিত করবে এবং আপনি অবজেক্ট.সভে বললে ReadOnlyRecord বাড়িয়ে তুলবে। object.readonly? অবজেক্টটি কেবল পঠনযোগ্য কিনা তা রিপোর্ট করে। পাসিং: কেবলমাত্র পঠনযোগ্য => কোনও অনুসন্ধানকারী পদ্ধতির সাথে মান সত্যিকার অর্থে ফিরে পাওয়া রেকর্ডগুলি কেবল পঠনযোগ্য হিসাবে চিহ্নিত করবে। বিকল্পটি: এখন যোগ দেয় বিকল্পটি কেবলমাত্র পঠনযোগ্য, সুতরাং আপনি যদি এই বিকল্পটি ব্যবহার করেন তবে একই রেকর্ড সংরক্ষণ করা এখন ব্যর্থ হবে। চারপাশে কাজ করতে Find_by_sql ব্যবহার করুন।

ব্যবহার find_by_sqlকরা সত্যই কোনও বিকল্প নয় কারণ এটি কাঁচা সারি / কলামের ডেটা দেয়, না ActiveRecords। আপনার দুটি বিকল্প রয়েছে:

  1. উদাহরণটি ভেরিয়েবলটিকে @readonlyরেকর্ডে ভুয়াতে বাধ্য করুন (হ্যাক)
  2. :include => :cardপরিবর্তে ব্যবহার করুন:join => :card

2.3.4 এবং তারপুড়ে রেলগুলি

উপরের বেশিরভাগটি আর সেপ্টেম্বর 10 ২০১২ এর পরে আর সত্য নয়:

  • ব্যবহার Record.find_by_sql করা একটি কার্যকর বিকল্প
  • :readonly => trueস্বয়ংক্রিয়ভাবে অনুমিত হয় শুধুমাত্র যদি :joinsনির্দিষ্ট হয়েছিল ছাড়া একটি সুনির্দিষ্ট :select কিংবা একটি সুনির্দিষ্ট (অথবা আবিষ্কর্তা-স্কোপ-উত্তরাধিকারসূত্রে) :readonlyবিকল্প (বাস্তবায়ন দেখতে set_readonly_option!মধ্যে active_record/base.rbপাগল 2.3.4, অথবা বাস্তবায়ন to_aমধ্যে active_record/relation.rbএবং custom_join_sqlমধ্যে active_record/relation/query_methods.rbপাগল 3.0.0 জন্য)
  • তবে :readonly => trueসবসময় স্বয়ংক্রিয়ভাবে অনুমিত হয় has_and_belongs_to_manyযদি যোগ দিতে টেবিল আরো দুই বিদেশী কী কলাম এবং :joinsছাড়া একটি সুনির্দিষ্ট উল্লেখ করা :select(অর্থাত ব্যবহারকারী-সরবরাহকৃত :readonlyমান উপেক্ষা করা হয় - দেখুন finding_with_ambiguous_select?মধ্যে active_record/associations/has_and_belongs_to_many_association.rb।)
  • উপসংহারে, কোনও বিশেষ যোগদানের টেবিল না করে এবং has_and_belongs_to_manyতারপরে @aaronrustadউত্তরটি কেবল ২.৩.৪ এবং 3.0.০.০ এ জরিমানা প্রযোজ্য।
  • আপনি যদি অর্জন করতে চান তবে ব্যবহার করবেন না ( বোঝায় একটি , যা কম নির্বাচনী এবং এর চেয়ে কম দক্ষ )):includesINNER JOIN:includesLEFT OUTER JOININNER JOIN

দ: অন্তর্ভুক্ত করা # টি প্রশ্নের কমিয়ে আনতে সহায়ক, আমি সে সম্পর্কে জানতাম না; তবে আমি টেবিল / ডেককার্ডস অ্যাসোসিয়েশনটিকে একটি has_many: এর মাধ্যমে পরিবর্তন করার চেষ্টা করেছি এবং এখন আমি একটি 'সন্ধান খুঁজে পেলাম না' '; আমাকে তার জন্য আরও একটি প্রশ্ন পোস্ট করতে হতে পারে
ব্যবহারকারীর 62270

হ্যাঁ @codeman,: প্রশ্নের সংখ্যা কমাতে হবে অন্তর্ভুক্ত এবং অন্তর্ভুক্ত সারণী (কেমন অন্তর্নিহিত এর পাগল যেমন শুধুমাত্র পাঠযোগ্য আপনার রেকর্ডের, যা এটি যত তাড়াতাড়ি এটা কিছু এসকিউএল sniffs করে উপলক্ষে ছাড়া যোগদানের আপনার অবস্থা সুযোগ ফিরিয়ে আনব
সন্ধানে

'Has_many: a, through =>: b' কাজ করার জন্য, বি সমিতিটি অবশ্যই ঘোষণা করতে হবে, যেমন 'has_many: b; has_many: a,: through =>: b ', আমি আশা করি এটি আপনার ক্ষেত্রে?
ভ্লাদার

6
এটি সাম্প্রতিক প্রকাশগুলিতে পরিবর্তিত হতে পারে তবে আপনি কেবল যুক্ত করতে পারেন: পদ্ধতির বৈশিষ্ট্যগুলির অংশ হিসাবে কেবল পঠনযোগ্য => মিথ্যা।
অ্যারন রুস্তাদ

1
এই উত্তরটি প্রযোজ্য যদি আপনার কাছে একটি কাস্টম: join_table নির্দিষ্ট করা আছে_আর_বেলং_স_মনি সংযোগ থাকে।
লি

172

বা 3 টি কক্ষে আপনি কেবলমাত্র পঠন পদ্ধতি ব্যবহার করতে পারেন (আপনার অবস্থার সাথে "..." প্রতিস্থাপন করুন):

( Deck.joins(:card) & Card.where('...') ).readonly(false)

1
হুম ... আমি দু'জনেই এসেলিক্যাস্টগুলিতে এই রেইলকাস্টগুলি দেখেছি এবং উভয়টিরই readonlyফাংশনটির উল্লেখ নেই ।
Purplejacket

45

এটি রেলের সাম্প্রতিক প্রকাশে পরিবর্তিত হতে পারে, তবে এই সমস্যাটি সমাধানের উপযুক্ত উপায়টি যুক্ত করা : পঠনযোগ্য => অনুসন্ধান বিকল্পগুলির সাথে মিথ্যা


3
আমি বিশ্বাস করি না এটি হ'ল কমপক্ষে ২.৩.৪
ওলি

2
এটি এখনও রেল 3.0.০.১০ নিয়ে কাজ করে, এখানে আমার নিজস্ব কোড থেকে একটি সুযোগ রয়েছে যা এখানে রয়েছে এমন একটি সুযোগ পেয়েছে:
ফান্ড্রেইজার.ডোন্যাটেবল.ড্রেডনলি

16

('*') সিলেক্ট করুন 3..২ এ এটি ঠিক করেছে বলে মনে হচ্ছে:

> Contact.select('*').joins(:slugs).where('slugs.slug' => 'the-slug').first.readonly?
=> false

কেবল যাচাই করতে, বাদ দেওয়া নির্বাচন ('*') কেবল পঠনযোগ্য রেকর্ড তৈরি করে:

> Contact.joins(:slugs).where('slugs.slug' => 'the-slug').first.readonly?
=> true

আমি যুক্তি বুঝতে পারি না বলতে পারি তবে কমপক্ষে এটি একটি দ্রুত এবং পরিষ্কার কাজ clean


4
select(quoted_table_name + '.*')
কারাগারে

1
সে ছিল উজ্জ্বল ব্রাউনসন। ধন্যবাদ.
ট্রিপ

এটি কাজ করতে পারে তবে ব্যবহারের চেয়ে জটিলreadonly(false)
কেলভিন

5

Find_by_sql এর পরিবর্তে, আপনি একটি নির্দিষ্ট করতে পারেন: সন্ধানকারীকে নির্বাচন করুন এবং সবকিছু আবার খুশি ...

start_cards = DeckCard.find :all, :select => 'deck_cards.*', :joins => [:card], :conditions => ["deck_cards.deck_id = ? and cards.start_card = ?", @game.deck.id, true]


3

এটি নিষ্ক্রিয় করতে ...

module DeactivateImplicitReadonly
  def custom_join_sql(*args)
    result = super
    @implicit_readonly = false
    result
  end
end
ActiveRecord::Relation.send :include, DeactivateImplicitReadonly

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