2012-06-23 6 views
0

Я читал и перечитывая рельсам ассоциации гид:Рельсы Active Record ассоциации

http://guides.rubyonrails.org/association_basics.html

Это были близки, но не совсем то же самое:

Ruby on rails active record associations

Я m не уверен, как настроить следующий сценарий.

События имеют статус ожидающего, открытого или закрытого.

Я думал, что это будет достаточно просто просто:

event has_one status 
status belongs_to event 

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

Тогда я думал, что я хотел бы сделать что-то вроде:

status has_many events 
event belongs_to status 

Но это кажется забавным, потому что статус не принадлежит событие. Событие имеет статус, не так ли?

Я пробовал использовать перечисления и не имел статус-модели. Но это стало сложно, поскольку ActiveRecord действительно не поддерживает перечисления. Я также подумал, что иметь отдельную модель может быть хорошей, если кто-то хочет расширить количество параметров статуса, например добавить «ожидание утверждения» или что-то еще.

Это сообщение говорит о том, что моя последняя установка в порядке, даже если он читает смешно:

Really easy Rails Active-Record Associations question

Но мне просто интересно, если я не знаю лучшего Руби/Rails способ обработки этот простой сценарий.

Заранее благодарен!

ответ

2

Игнорируйте этот голос в своей голове: вы все хорошо. Реальная важная из которых имеет belongs_to, где хранится внешний ключ. В этом примере ясно, что внешний ключ должен храниться в модели Event, что означает, что он должен belongs_to :status.

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

Почему бы не добавить status столбец Event (как целое), и есть что-то вроде этого:

class Event < ActiveRecord::Base 
    STATUS_TYPES = {1 => "active", 2 => "inactive", 3 => "closed"} 

    def status 
    STATUS_TYPES[self[:status]] 
    end 

    def status=(new_status) 
    new_status = STATUS_TYPES.invert[new_status] if new_status.class == "String" 
    self[:status] = new_status 
    end 
end 
+0

Спасибо за заверение. Вероятно, это то, что я буду делать в следующий раз, когда я столкнусь с этой проблемой. Благодаря! –

0

Вы ошибаетесь.

Если вы

Event 
has_one :status 

Status 
belongs_to :event 

Rails будет убедиться, что это объединение один-к-одному, поэтому статус будет принадлежать только к одному событию

Я уверен, что это то, что произойдет, если вы пытаетесь присвоить статус события другому событию

e1 = Event.first 
status = e1.status 

e2 = Event.new 
e2.status = status 
e2.save 

Event.first.status #=> nil 
+0

Да, я согласен с вами. Вот почему я рассматриваю второй вариант из-за этой проблемы. Но второй вариант кажется, что я заставляю ActiveRecord делать то, что он не собирался делать. В руководстве говорится следующее: «Например, имеет смысл сказать, что поставщик владеет учетной записью, чем тот, у кого есть поставщик.» Таким образом, с моим вторым вариантом, я буду говорить: «Статус принадлежит событию». Что читает смешно для меня. Может, я просто подумал об этом? –

3

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

Что вам действительно нужно, это перечисление. Но, конечно, рубин не имеет перечисления.

К счастью, вы можете подделать его.

module StatusCodes 
    pending = 0 
    open = 1 
    closed = 2 
end 

Затем вы можете сделать что-то вроде этого

if @event.status == StatusCodes::open 
    # do something 
end 

Это гораздо более простое решение, и ваш код остается очень читаемым.

+0

Да, согласен. Спасибо, что выбрали эту альтернативу! Береги себя! –

1

Вы могли бы хотеть рассмотреть вопрос об использовании state_machine и простой строковый столбец для реализации состояния, а используя ассоциацию или ручную перемотку.

+0

Wow ... государственные машины. Хорошо знать. Я сохраню это в заднем кармане. –