У меня есть два класса, которые я хотел бы указать следующим образом:
class Club < ActiveRecord::Base
belongs_to :president, :class_name => "Person", :foreign_key => "president_id"
belongs_to :vice_president,
:class_name => "Person",
:foreign_key => "vice_president_id"
end
class Person < ActiveRecord::Base
has_one :club, :conditions =>
['president_id = ? OR vice_president_id = ?', '#{self.id}', '#{self.id}']
end
Это не работает и дает мне ошибку при попытке получить ассоциацию клуба от объекта человека. Ошибка состоит в том, потому что ищет person_id в таблице клуба, когда я посмотрел на SQL. Я могу обойти его путем объявления нескольких has_one ассоциаций, но чувствовать, что это - неподходящий способ сделать его.
Человек может только быть президентом или вице-президентом одного клуба.
Любой, который в состоянии дать определенный совет относительно этой проблемы, я был бы очень благодарен.
Насколько я знаю, ваше условие has_one
никогда не будет работать в Rails.
Вам нужен один явный has_one
или own_to
или has_many для каждой «ссылки» в обеих таблицах. Итак, если у вас есть две «ссылки», вам понадобятся две has_one
и две own_to
. Вот как это работает.
Во-вторых, я думаю, вам следует пересмотреть свои модели. Как вы это делаете, один человек не может быть президентом клуба и сотрудником одновременно. Или быть президентом двух клубов. Даже если у вас их нет прямо сейчас, они могут появиться в будущем - сейчас проще оставаться гибким.
Гибкий способ сделать это - использовать has_many: через
с промежуточной таблицей, определяющей роль. Другими словами:
# The memberships table has a person_id, club_id and role_id, all integers
class Membership < ActiveRecord::Base
belongs_to :club
belongs_to :person
validates_presence_of :role_id
validates_numericality_of :role_id
end
class Club < ActiveRecord::Base
has_many :memberships, :dependent => :delete_all
has_many :people, :through => :memberships
end
class Person < ActiveRecord::Base
has_many :memberships, :dependent => :delete_all
has_many :clubs, :through => :memberships
end
Теперь, предполагая, что role_id = 0 означает сотрудника, role_id = 1 означает президента, а role_id = 2 означает Vice_president, вы можете использовать это так:
tyler = Person.find(1) # person_id is 1
other = Person.find(2) # person_id is 2
c = Club.find(1) # club_id is 1
tyler.clubs # returns all the clubs this person is "member" of
c.people # returns all the "members" of this club, no matter their role
#make tyler the president of c
tyler.memberships.create(:club_id => 1, :role_id => 1)
#make other the vicepresident of c
#but using c.memberships instead of other.memberships (works both ways)
c.memberships.create(:person_id => 2, :role_id => 1)
#find the (first) president of c
c.memberships.find_by_role_id(1).person
#find the (first) vicepresident of c
c.memberships.find_by_role_id(2).person
#find all the employees of c
c.memberships.find_all_by_role_id(0).collect { |m| m.person }
#find all the clubs of which tyler is president
tyler.memberships.find_all_by_role_id(1).collect { |m| m.club }
Дополнительные примечания:
have_many
, а членство - роль own_to
.Или вы можете определить методы в членстве для получения имени роли (если 0, возвращается «сотрудник», если 1, «президент» и т. Д. Рекомендуется использовать Boost.Regex .
Пример (с веб-сайта):
bool validate_card_format(const std::string& s)
{
static const boost::regex e("(\\d{4}[- ]){3}\\d{4}");
return regex_match(s, e);
}
Другой пример:
// match any format with the regular expression:
const boost::regex e("\\A(\\d{3,4})[- ]?(\\d{4})[- ]?(\\d{4})[- ]?(\\d{4})\\z");
const std::string machine_format("\\1\\2\\3\\4");
const std::string human_format("\\1-\\2-\\3-\\4");
std::string machine_readable_card_number(const std::string s)
{
return regex_replace(s, e, machine_format, boost::match_default | boost::format_sed);
}
std::string human_readable_card_number(const std::string s)
{
return regex_replace(s, e, human_format, boost::match_default | boost::format_sed);
}
-121--3090652- Для хранения изображений я всегда хранил их на жестком диске, но используя очень жесткий сценарий проверки изображений, чтобы убедиться, что изображения не содержат вредоносного кода. Я также используется для применения перезаписи URL, чтобы пользователи не могли найти реальный путь к изображениям.
Разве у вас нет странного ощущения, что вы храните изображения в базах данных? База данных mysql может расти очень быстро, и вам всегда нужен PHP скрипт для отображения изображений, что означает, что это делает ваш сервер медленнее.
Что касается места хранения пароля, используйте соление, как ответили другие.
Наконец, для документации, я очень люблю видеть, как Wordpress структурирован. Я часами смотрел исходный код и читал документы. Это просто ужасно хороший пример того, как организовать любой сайт.
-121--4903885-Это классический пример использования полиморфных ассоциаций. Вот ссылка: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
Что-то вроде..
class Club < ActiveRecord::Base
belongs_to :person, :polymorphic => true
class Person < ActiveRecord::Base
has_one :club, :as => :position
Я думаю, что ваши ассоциации неверны . По-вашему, сложно назначить президента или вице-президента.
Я бы сделал это так:
class Club < ActiveRecord::Base
has_one :president,
:class_name => "Person",
:foreign_key => 'president_club_id'
has_one :vice_president,
:class_name => "Person",
:foreign_key => 'vice_president_club_id'
end
class Person < ActiveRecord::Base
belongs_to :club
end
Теперь вы можете назначать роли так:
club.president = Person.create(:name => 'Tom')
club.vice_president = Person.create(:name => 'Andrew')
Предлагаю вам представить новую модель, которая называется ролью. Затем получите следующее:
class Club
has_many :roles
def president
end
def vice_president
end
end
class Person
belongs_to :role
end
class Role
has_one :person
belongs_to :club
end