Как стать автором
Обновить

Комментарии 41

Изменения в attr_accessible нужны, чтобы можно было сохранять данные «пачками», а не по одной.


Без объявления attr_accessible вообще невозможно сохранить данные кроме тех, что Devise определяет по-умолчанию.

А чем Вас не устраивает вариант 2-х отдельных «ролей» в Devise?
Потому, что полиморфизм позволяет ассоциировать одну модель, например Comment, с несколькими моделями сразу через одну единственную полиморфную связь, что обеспечивает простоту и краткость кода, ну и вообще принцип DRY уж очень подкупает выгодами его применения.
Принцип «Polymorphism» я понимаю, но по обстоятельству, может быть целесообразным использовать два типа Юзеров. Я понимаю если это разные уровни «Редактоpа» в какой-то блоговой системе, но если это Админ и Юзер, или, Читатель и Публикатор, то тут сама идея полиморфизма как-то ни к месту.
ну почему же, например редактор, читатель и публицист могут оставлять комментарии к чему-либо, при этом они все будут :commenter, либо переписываться в ЛС, при этом они будут :author_letter.
Спасибо за поправку.
Две роли меня не устроили потому, что 2 роли — это 2 формы регистрации и 2 формы входа (насколько я понял). То есть типа «Войти как пользователь» и «Войти как администратор».

Тут же предполагается, что у них таки есть общие поля, но есть и различные.
+ я не очень понял, если делать 2 разных модели, то у меня будет user_signed_in?, admin_signed_in?, authenticate_user! и authenticate_admin!, что меня не устраивает, потому что контроллеры они пользуются одними и теми же, просто с разными правами.
Да все просто на самом деле, роли — это не то чем должен заведовать devise. В вашем случае это ответственность cancan — github.com/ryanb/cancan/wiki/Role-Based-Authorization

Мне больше понравился github.com/stffn/declarative_authorization, рекомендую ознакомиться
Да, особенно хорош declarative_authorization при наличии неймспейсов в контроллерах :) Поэтому я больше в d_a ни ногой:)
не понял про неймспейсы… чем они помогают/мешают при использовании d_a?
Счастливый человек:) d_a очень плохо работает с ними, а мне с ними нужно было работать постоянно. Не столько неймспейсы даже, сколько вложенные ресурсы.
А по поводу ролей — если бы поля были одинаковые у обоих типов юзеров — нет проблем. Но они, с одной стороны, совсем разные сущности (и надо бы создать 2 разных девайсовы модели), с другой стороны — очень похожие и имеют много общего.
У типов как «обычный пользователь» и «администратор» больше разных аттрибутов чем одинаковых. Поэтому, будет правильным сделать две разные модели для них. Чего вы добились полиморфизмом? 3 таблицы в BD vs 2-х.
Про админа речи не идет вообще, речь о том, что нужны Заказчик и Исполнитель.
Извиняюсь за БД, имелось ввиду DB. Пусть будет «заказчик» и «потребитель», но всё равно, у них разные атрибуты. Всё таки я сторонник де-нормализации БД. Пускай будет больше таблиц, чем больше программного вычисления.
И как в таком случае будут вести себя контроллеры и представления? «Войти как заказчик», «Войти как исполнитель», «Зарегистрироваться как заказчик», «Зарегистрироваться как исполнитель»?

Что тогда делать в контроллерах, везде писать «authenticate_customer!», «authenticate_executive!» в before_filter'ах?

Всегда проверять на customer_signed_in? и executive_signed_in? мне как-то тоже не очень улыбается. Я выбрал лучшее решение для меня (как мне кажется), в некоторых ситуациях да, лучше сделать 2 модели вместо трех, а полиморфизм оставить до лучших времен, но, имхо, это не тот случай.
Меня уже ничего не спасет, я уже со всем справился :)
ognevsky, а можете вьюхи показать. У меня аналогичная задача, но вот получаю ошибку при сабмите формы «undefined method `primary_key' for String:Class»

Моя вью регистрации:

<div class="center"> <h2>Регистрация</h2><br/> <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %> <%= devise_error_messages! %> <div><%= f.select :character, options_for_select([["Физлицо", "Individual"], ["Компания", "Company"]]) %></div> <div><%= f.email_field :email, :placeholder => 'Адрес электронной почты' %></div> <div><%= f.password_field :password, :placeholder => 'Пароль' %></div> <div><%= f.password_field :password_confirmation, :placeholder => 'Подтверждение пароля' %></div> <div><%= f.submit "Зарегистрироваться", :class => 'btn btn-danger' %></div> <% end %> <%= render "devise/shared/links" %> </div>
Как я люблю подсветку кода…

Залил на pastebin.com/yAvstYzE
pastie.org/4399931
У меня вот такое, я использовал formtastic, с встроенным форм-билдером не пробовал, если честно.
Ага, разобрался еще до ответа, спасибо.

Андрей, такой еще вопрос: вот выбирает юзер в форме регистрации тип пользователя, как динамически перестроить форму?

Я сделал два partial, в которые поместил обязательные для заполнения поля. По умолчанию у меня выбран 1й тип юзера в селекте и отображается 1й partial. Но когда выбрал в селекте 2й тип юзера, должен отобразиться 2й partial вместо 1го.
Тут javascript в помощь, я не забый большой его знаток, поэтому и советовать особенно ничего не буду. Лучший вариант — Ajax'ом подгружать вторую форму.
Ок, этот вариант мне сразу в голову пришел, думал просто есть другой вариант. А у Вас в приложении заполнение данных юзера было на втором шаге после ввода общих полей или ajax-ом тоже форму меняли?
У меня там, по–моему, потом в профиле добавлялось. То есть, по сути, как будто на втором шаге.
Попробовал указать по умолчанию 1й тип юзера. В его модели есть обязательные к заполнению при регистрации поля, которые я влючаю в форму: pastebin.com/aY74NtDe
Но когда рендериться страница с формой полей этих нет, только поля модели User.
В чем может быть причина, я не правильно описываю форму? Или т.к. запись еще не сохранена (т.е.) в базе фактически нет записи user (и заполненных полей character_id, character_type), то мы не можем и заполнить данные модели Individual? (хотя я больше расчитываю на то, что я ошибся где-то).
Полезным будет почитать про вложенные ресурсы, про accepts_nested_attributes_for тоже. Возможно, в этом проблема.
Решил проблему с отображением: gist.github.com/3288189, gist.github.com/3288198

Но при регистрации теперь получаю ошибку «ArgumentError in RegistrationController#create»
Cannot build association character. Are you trying to build a polymorphic one-to-one association?

Request

Parameters:
{«utf8»=>"✓",
«authenticity_token»=>«62bE9GNDQ1QFn5UDP34EmxLlHSRiKzCSPwJO8BiNuYU=»,
«user»=>{«character_type»=>«Company»,
«email»=>"",
«password»=>"[FILTERED]",
«password_confirmation»=>"[FILTERED]",
«character_attributes»=>{«name»=>""}},
«commit»=>«Зарегистрироваться»}
ognevsky, спасибо за хорошую, подробную статью!
Пожалуйста:)
Статья конечно интересная, но подробностей как раз таки не хватает. Вы так и не написали зачем вам потребовался полиморфизм в этой ситуации.

> После этого создадим 2 модели: Customer и Executive. В миграциях можно прописать любые уникальные для каждого типа пользователя данные

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

И еще не ясно откуда взялся метод «admin?». Cancan его сам как-то определяет?
Прошу прощения, admin? пролез случайно, недосмотрел :(
По поводу уникальных полей — у исполнителя эти поля icq, skype, email (публичный),
а у заказчика — ИНН, название фирмы, адрес фирмы, город проживания и что-то еще.

+ такая модель позволяет прописывать ассоциации непосредственно в моделях. То есть в executive.rb мы напишем:
has_many :participations, :dependent => :destroy
has_many :documents, :through => :participations
А в customer.rb:

has_many :documents, :dependent => :destroy

Таким образом, и заказчики, и исполнители связаны с документами. У обоих типов пользователей мы можем написать user.documents, но вот выбираться они будут по-разному. То есть для заказчика «свои документы» — это те, которые он написал, а для исполнителя — те, к которым он подключился (или же его подключили).
Я подозревал что у вас все же есть дополнительная логика, ради которой имеет смысл использовать полиморфизм. Просто из самой статьи это не понятно. А ведь статья именно о полиморфных ассоциациях ;)
Чукча не писатель, чукча рассказыватель :)
По моему вместо
validates_presence_of :name, :character_type
в третьих рельсах надо писать
validates :name, :character_type, :presence => true

Спасибо за интересную статью.
Ну, это уже дело вкуса, хотя я предпочитаю вариант с параметром-типом валидации, который был введен в 3 версии.
не учите плохому, лучше исправьте, т.к. в 3.1 эти методы уже будут удалены.
сорри, не туда ответил.
Ничего страшного, тут не так много комментариев, чтобы в них заблудиться. Ок, сейчас исправлю.
Блин, там такая вермишель с подсветкой синтаксиса, что мне страшно даже заходить в редактирование статьи o_O Будем надеяться, что никто от этой неточности не умрет:)
так я же и написал, что предпочитаю новый синтаксис:

validates :name, :character_type, :presence => true

Просто некоторым людям удобнее или привычнее использовать старый. Кстати, в одной из книг по Rails 3, если не ошибаюсь, авторства Оби Фернандеса, используется как раз-таки старый синтаксис.
Это он мне отвечал, но промахнулся. Я согласен, что в статье нужно было с самого начала писать «по-новому», раз уж это новые рельсы, но я что-то не о том задумался)
Да, уже отметили, что можно и так, и так. Я пока что себя на новый лад не переучил (и сниппеты текстмейта тоже =).
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации