Олардың арасында рубюмен байланыстыру үшін ең жақсы тәжірибе

Мен навигациялық рельстердің нағыз сюжеттік сценарийде орналасқан рельстердің мінез-құлқын жүзеге асырудың жақсы әдісін таба алмаймын.

Сыныптағы ата-ана объектілерінің массивіне қатынаушы сынып ата-ана объектісіне ие болсын десеңіз, мен Балалар объектісін басқарғанда, мен сияқты Ата-ана оңай алайық:

class Parent
  attr_accessor :children

  def initialize
    @children = Array.new
  end
end

class Child
end

parent = Parent.new
first_child = Child.new
second_child = Child.new
parent.children << [ first_child, second_child ]

a_child = parent.children.first

get_parent_from_child = a.child.parent

Маған қызықтыратын бөлік, әрине, «ата-аналық» объектіні өз балаларының бірінен алуға тырысатын соңғы жол.

Оны қалай оңай және таза түрде қолдануға болады?

Мен еншілес объектке енуді ойластырдым, бірақ мен бұл мәннің ата-аналық объектіге еншілес объектіні тіркеген сайын, қалайша тексерілетініне сенімді емеспін.

Рубинде мұны оңай және таза тәсіл бар ма?

Алдын-ала рақмет.

2

3 жауаптар

Өздеріңіз білетін kids туралы толығымен ашып көрсетудің қажеті жоқ, сіздің деректеріңізге толық қолжетімділікті толық басқара алмайтын ештеңе жоқ.

class Parent
  def initialize
    @children = [ ]
  end

  # You get a shallow copy of the children, you can
  # change the individual children but not the tree
  # structure.
  def children
    @children.dup
  end

  # We take ownership of the children when you add them.
  def add_children(*kids)
    kids.each { |k| k.parent = self }
    @children += kids
  end

  def remove_children(&block)
    @children.delete_if(&block)
  end
end

# This would probably have some sort of payload and
# a sensible "==" implementation.
class Child
  attr_reader :parent
  def parent=(p)
    raise StandardError => 'Not allowed to change parents!' if @parent
    @parent = p
  end
end

Содан кейін child.parent жұмыс істейді және сіз балаларды алып тастағыңыз келсе, сіз оларды жоюға болатын ата-анаңызды айтыңыз:

# Remove the children with even payloads.
parent.remove_children { |c| c.payload % 2 == 0 }

# Remove the children with odd payloads and copy them.
odds = [ ]
parent.remove_children do |c|
  kill_it = c.payload % 2 != 0
  odds << Child.new(c.payload) if(kill_it)
  kill_it
end
2
қосылды
@Барамин: Ешқандай қобалжу емес, бірнеше нұсқасы бар, сіз үшін жұмыс істеп жатқандай жақсы нәрсе.
қосылды автор mu is too short, көзі
Ckruse-дің жауабын жақсы жаңартуға болады, бірақ мен іздейтін нәрсеге қарағанда, Иенді жақсы көремін. Сіздің көмегіңіз үшін көп рахмет, Му (тым қысқа), hehe, мен сіздің есіміңізді ұнатамын.
қосылды автор Baramin, көзі

Массивке қосылған әрбір бала үшін ата-ана атрибуты тағайындаған ата-анадағы балалардың жеке аксессуарын жазыңыз. Балаларды алаптан алып тастағанда керісінше орындаңыз. Мен мұны осылай жасайтын едім.

1
қосылды
Мұны сіз де істей аласыз. Жиымнан класс жасаңыз және new_child() әдісін орындаңыз, ол parent сипатын орнатады және одан кейін self деп аталады.
қосылды автор ckruse, көзі
Жарайды ма. Мен бұны шынымен жасай аламын, ата-аналық объектке add_child және delete_child қосыңыз. Мен оны қазір іске асыра бастайтын боламын, ал егер ешкімде жақсы шешім болмаса, сіздің жауапыңызды дәлелдейді. Мысалы, new_child = parent.children.new() сияқты нәрселерге мүмкіндік беретін әдісті қалайтын болар еді.
қосылды автор Baramin, көзі

Rails-ті сияқты, теңшелетін контейнер класын пайдалану арқылы Rails-ден has_many мінез-құлқына қол жеткізуге болады.

class Parent
  attr_reader :children

  def initialize
    @children = ChildCollection.new(self)
  end
end

class Child
  attr_accessor :parent
end

class ChildCollection
  def initialize parent
    @children = []
    @parent = parent
  end

  def new
    child = Child.new
    child.parent = @parent
    @children << child
    child
  end

  def << child
    child.parent = @parent
    @children << child
    self
  end
end

Ата-аналарға балаларды қосу үшін кейбір мысал код:

parent = Parent.new
child1 = parent.children.new
child2 = Child.new
child3 = Child.new
parent.children << child2 << child3

puts "Parent is: #{parent.object_id}"
puts "Child1's parent is: #{child1.parent.object_id}"
puts "Child2's parent is: #{child2.parent.object_id}"
puts "Child3's parent is: #{child3.parent.object_id}"

remove және each сияқты басқа да пайдалы әдістерді лақтырғыңыз келуі мүмкін (сондықтан ChildCollection болуы мүмкін Enumerable Модульді алыңыз және онымен бірге келген барлық салқын заттарды алыңыз), бірақ бұл сізге бастау үшін жеткілікті болуы керек.

1
қосылды
Parent сыныбында attr_accessor орнына attr_reader: children қолдандым, себебі бізде контейнерде тиісті ата-аналық объектіге . Біз балаларды коллекциядан қосып, алып тастай аламыз.
қосылды автор Ian Eccles, көзі
Иә, бұл мен іздегендей көрінеді. Мен оны жобада дүйсенбіде іске асыруға тырысамын. Рахмет, Ян.
қосылды автор Baramin, көзі