ActiveRecord: фильтрация детей без попадания в базу данных - PullRequest
0 голосов
/ 15 декабря 2009

Я ищу чистый способ отфильтровать дочерние элементы родителя в отношении has_many, не затрагивая базу данных и, таким образом, перезагружать представление объектов базы данных обратно в приложение.

Например:

class Parent < ActiveRecord::Base
  has_many :children, ...
  ...
end

Мое понимание (поправьте меня, если я ошибаюсь) заключается в том, что

parent.children.find_all_by_attr('foo')

возвращает всех потомков родителя, которые имеют значение attr 'foo' в БД, но поскольку он снова попадает в базу данных, все дочерние элементы, для которых перед сохранением были установлены значения атрибута attr, будут восстановлены, поэтому их значения БД будут восстановлены любые изменения.

Я взломал это с

parent.children.reject { |child| child.attr != 'foo' }

но это кажется очень неаккуратным и более трудным для чтения. У кого-нибудь есть более ясное предложение о том, как это сделать?

Ответы [ 2 ]

3 голосов
/ 15 декабря 2009

После некоторого возни, похоже, что это немного сложнее, чем это. Мое возни было так:

  • Я создал пару моделей, Родитель и ребенок с has_many отношения в одноразовых рельсах приложение.
  • Я открыл script/console и тыкал вокруг.

Я создал нового родителя с ребенком и сохранил их

>> p = Parent.new;p.children << Child.new(:foo=>'bar');p.save
=> true

Смотри, ребенок в БД и его можно найти by_foo

>> p.children.find_by_foo('bar')
=> #<Child id: 1, foo: "bar", parent_id: 1, created_at: "2009-12-14 22:08:05", updated_at: "2009-12-14 22:08:05">

Я добавил еще одного ребенка в коллекцию, он отображается в p.children, но не в методах коллекции, которые попадают в базу данных.

>> p.children << Child.new(:foo=>'bar')
=> [#<Child id: 1, foo: "bar", parent_id: 1, created_at: "2009-12-14 22:08:05", updated_at: "2009-12-14 22:08:05">, #<Child id: 2, foo: "bar", parent_id: 1, created_at: "2009-12-14 22:08:25", updated_at: "2009-12-14 22:08:25">]
>> p.children.find_by_foo('bar')
=> #<Child id: 1, foo: "bar", parent_id: 1, created_at: "2009-12-14 22:08:05", updated_at: "2009-12-14 22:08:05">

Я меняю ребенка, который находится в БД.

>> p.children[0].foo = 'baz'
=> "baz"

Когда я ищу его, он дает мне версию БД.

>> p.children.find_by_foo('bar')
=> #<Child id: 1, foo: "bar", parent_id: 1, created_at: "2009-12-14 22:08:05", updated_at: "2009-12-14 22:08:05">

Но местная коллекция не изменилась.

>> p.children
=> [#<Child id: 1, foo: "baz", parent_id: 1, created_at: "2009-12-14 22:08:05", updated_at: "2009-12-14 22:08:05">, #<Child id: 2, foo: "bar", parent_id: 1, created_at: "2009-12-14 22:08:25", updated_at: "2009-12-14 22:08:25">]

Так что, если вы снова сохраните p, изменения будут переданы.

Если вы хотите получить все локальные объекты ассоциации, включая те, которые были изменены, вы не можете использовать искатели ActiveRecord, потому что они попадают в базу данных, вместо этого используйте методы массива, как вы делали выше. Тем не менее, использование find_all или select будет проще для понимания

parent.children.select{|c| c.attr == 'foo'}
0 голосов
/ 15 декабря 2009

Вы можете сделать противоположное reject, то есть find_all:

parent.children.find_all {|child| child.attr == 'foo' }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...