LINUX.ORG.RU

Как правильно создавать асоциации для существующих данных

 


0

2

Есть следующий код (за правильность не ручаюсь, главное идея)

class Product < ActiveRecord::Base
  belongs to :category
..
end
<%= form_for(@product) do |f| %>
<%= f.text_field :name%>
<%= f.select :category, options_for_select 
... skipped

Как наиболее правильно «цеплять» (и валидировать) категорию к продукту (категории уже созданы и доступны в селекте)?

Буду благодарен за ссылку или пример а то здесть или все интересное упущено или у меня голова уже не варит

★★★★★

Последнее исправление: ZuBB (всего исправлений: 3)

Ответ на: комментарий от GreenBag

я правильно понимаю что Вы предлагаете добавить в attr_accessible city_id (category_id в моем примере)?

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от GreenBag

кхм. ну тогда еще нужно добавить category_attributes в attr_reader дабы иметь возможность делать @product.category.name, я прав?

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

Когда ты пишешь belongs_to, то создается ассоциация у продукта на категорию и все атрибуты категории (name и прочие) доступны через ассоциацию:

  @product.category.name

Кстати, category_id (foreign key) должен также быть добавлен миграцией в таблицу products.

GreenBag ★★
()
Последнее исправление: GreenBag (всего исправлений: 1)
Ответ на: комментарий от GreenBag

Кстати, category_id (foreign key) должен также быть добавлен миграцией в таблицу products.

я в курсе, кеп

Когда ты пишешь belongs_to, то создается ассоциация у продукта на категорию и все атрибуты категории (name и прочие) доступны через ассоциацию:

все атрибуты категории (name и прочие) доступны через ассоциацию

а что же тогда делает attr_reader? // вот сейчас отброшу лень и проверю прав ли ты

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от GreenBag

получается что еще нужно озаботится о том чтобы провалидировать category_id на принадлежность к категориям на сервере. каким методом это делается?

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

Когда ты пишешь belongs_to, то создается ассоциация у продукта на категорию и все атрибуты категории (name и прочие) доступны через ассоциацию:

все атрибуты категории (name и прочие) доступны через ассоциацию

вот сейчас отброшу лень и проверю прав ли ты

да, так и есть..

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

attr_reader

разобрался. это из руби

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от GreenBag

осталось узнать ответ только на этот вопрос

получается что еще нужно озаботится о том чтобы провалидировать category_id на принадлежность к категориям на сервере. каким методом это делается?

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

вот сейчас отброшу лень и...

Вот с этого стоит и начинать, прежде чем задавать вопросы о attr_reader и прочее.

получается что еще нужно озаботится о том чтобы провалидировать category_id на принадлежность к категориям на сервере

???

GreenBag ★★
()
Ответ на: комментарий от GreenBag

ничто не мешает юзеру пометять значение в селекте и в базу попадет как минимум невалидные данные

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

Транзакция сохранения не пройдет уже на уровне самой БД — т.к. при связи через внешний ключ произойдет ошибка, т.к. ключ будет ссылаться на несуществующую запись (с несуществующим id).

GreenBag ★★
()
Ответ на: комментарий от GreenBag

только теперь я понял что же на самом деле вы имели ввиду здесь

Кстати, category_id (foreign key) должен также быть добавлен миграцией в таблицу products.

так можна делать но это не руби вей и здесь сказано почему. поэтому оставим ваш вариант как запасной. хотел бы услышать мнение других спецов

ZuBB ★★★★★
() автор топика
Последнее исправление: ZuBB (всего исправлений: 1)
Ответ на: комментарий от ZuBB

1. То, что написано на «буффер-переполнен» — это создание поля целого типа с названием ключа, но не создающего сам внешний ключ.

2. В рельсах для этого есть:

a) gem foreigner

b)тыц

GreenBag ★★
()
Последнее исправление: GreenBag (всего исправлений: 1)
Ответ на: комментарий от GreenBag

1. То, что написано на «буффер-переполнен» — это создание поля целого типа с названием ключа, но не создающего сам внешний ключ.

янпп

2. В рельсах для этого есть:

a) gem foreigner

b)тыц

еще раз. в моей ссылке достаточно четко пишет почему создавать fk не рекомендуется. также там говорится что можна делать проверки на application level. Вот я и хотел бы увидеть пример тех проверок

ZuBB ★★★★★
() автор топика
Последнее исправление: ZuBB (всего исправлений: 1)
Ответ на: комментарий от GreenBag

fail. оно валидирует асоциированную модельзапись. а у нас ничего не асоциировано. мы же просто вкорячили category_id

ZuBB ★★★★★
() автор топика

Как наиболее правильно «цеплять» (и валидировать) категорию к продукту (категории уже созданы и доступны в селекте)?

Ну цеплять через belongs_to, это правильно и достаточно.

Валидировать ID категории вот так: http://stackoverflow.com/questions/12451288/how-to-validate-associated-model-id тоже вполне достаточно.

Alve ★★★★★
()
Ответ на: комментарий от Alve

special-k, и Alve

вашы ответы по сути идентичны, если я правильно понял. да, вполне рабочий вариант. но.. мое внутренное руби-фу говорит что скорее всего есть еще более короткий и действенный метод. рельсы точно писались людьми которые и лишней клавишы не нажмут :)

ZuBB ★★★★★
() автор топика
Последнее исправление: ZuBB (всего исправлений: 4)
Ответ на: комментарий от ZuBB

еще раз. в моей ссылке достаточно четко пишет почему создавать fk не рекомендуется. также там говорится что можна делать проверки на application level. Вот я и хотел бы увидеть пример тех проверок

Ерунда какая. Там написано, что рельсы поддерживают СУБД, не умеющие внешних ключей, это основная причина. И написано это в 2009 году. Для мира рельс это вечность. Создавать констрейнты на уровне СУБД или нет - надо думать собственной головой. Если целостность данных критична - создавать однозначно, это не вопрос стиля или соглашений, это вопрос жизненно важный для приложения. Если же это какой-нибудь бложик с комментариями, то вполне достаточно проверки на уровне приложения.

anonymous
()
Ответ на: комментарий от ZuBB

Я бы сделал так

model:

attr_accessible :category
validates :category, presence: true

view:

f.select :category_id, option_for_select

controller:

category = Category.find_by_id(params[:category_id])
product.update_attributes(:category => category)

Drugnir
()
Ответ на: комментарий от trashymichael

Что угодно.
Ошибка транзакции - это как минимум лишнее обращение к бд. Одно дело вызов метода объекта, другое обработка исключения БД. Валидация должна быть на клиенте, затем на сервере, и уже затем, может быть в бд.

special-k ★★★
()
Ответ на: комментарий от special-k

это все понятно, но что кроется за простотой вызова метода, эти данные значит надо в памяти держать, при рестарте восстанавливать, как-то сбрасывать кеши, контролировать целостность, етц етц, с одной стороны это просто метод, с другой лучше просто воспользоваться трудами десятков лет и тысяч людей, давно прошедших этот путь

trashymichael ★★★
()
Ответ на: комментарий от special-k

капитальных систем вообще лучше избегать, валидация на клиенте это совсем отдельная история

trashymichael ★★★
()
Ответ на: комментарий от trashymichael

значит надо в памяти держать

Вообще это может быть такой же запрос, только валидный (как здесь, в частности). Как было сказано, бд - это гребанное хранилище, не думаю, что на него стоит возлагать тьму важных функций.

special-k ★★★
()
Последнее исправление: special-k (всего исправлений: 1)
Ответ на: комментарий от special-k

скажем так, я пишу исходя из данных топика, оп явно излишне фантазирует, буксуя висячие сады на простой задаче, я не прав?

trashymichael ★★★
()
Ответ на: комментарий от special-k

так ты и говоришь, транзакции это мол лишнее обращение (котенок умер), а метод может быть запросом, в итоге мы сошлись на том с чего начали, как не крути это будет одно и тоже, либо данные валидируются и запрос неизбежен либо нет, детали реализации запроса могут быть разные, самый простой путь — послать запрос не вникая в детали.

trashymichael ★★★
()
Ответ на: комментарий от trashymichael

Во-первых, оно и не хуже (и даже лучше, т.к. создание сложного объекта, со множеством сопутствующих запросов, может быть прервано, а в противном случае фейловый объект будет всегда создаваться до конца); во-вторых ты и сам иногда захочешь знать валидный у тебя объект или нет; в-третьих, в рамках рельс это неприменимо при т.н. полиморфизме; в-четвертых ошибка в транзакции будет вызывать исключение и ты будешь обрабатывать исключения.

Короче говоря, в рельсах уж точно так делать не надо, а вообще можно и так, но наступит разрозненность в хранении правил создания записей, осложнения при смене платформы. Хоть полной абстракции от БД все равно не выйдет, но лучше к этому стремиться, чем сознательно размазывать логику, тем более, было бы зачем.

special-k ★★★
()
Ответ на: комментарий от trashymichael

буксуя висячие сады на простой задаче, я не прав?

Нет, написать правила для валидации объекта несоизмеримо проще (как уже было сказано, в т.ч. мной, это одна или две строки кода). Обработать исключения и запихнуть это в стандартный механизм оповещения рельс таки сложнее.

special-k ★★★
()
Ответ на: комментарий от special-k

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

алсо, я не из рельс, но я вижу это так

trashymichael ★★★
()
Ответ на: комментарий от trashymichael

платформу никогда не меняют

Ее могут частично менять, подключая какое-нибудь key-value storage, для ускорения чего-нибудь, например.

чем писать тыщи проверок

Чем тыщи, наверно, но здесь одна, надо действовать по ситуации.

special-k ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.