Если Вы использовали Сервер. MapPath, тогда у Вас должен уже быть относительный веб-путь. Согласно документация MSDN , этот метод берет одну переменную, путь , который является виртуальным трактом веб-сервера. Таким образом, если бы Вы смогли назвать метод, у Вас должен уже быть относительный веб-путь, сразу доступный.
Вы можете заморозить весь объект AR :: B, установив для @readonly значение true (в методе), но это заблокирует все атрибуты.
Я бы порекомендовал определить методы установки атрибутов, которые проверяют текущее состояние перед переходом в super:
class Post < ActiveRecord::Base
def author=(author)
super unless self.published?
end
def content=(content)
super unless self.published?
end
end
[EDIT] Или для большого количества атрибутов:
class Post < ActiveRecord::Base
%w(author content comments others).each do |method|
class_eval <<-"end_eval", binding, __FILE__, __LINE__
def #{method}=(val)
super unless self.published?
end
end_eval
end
end
Который, конечно, я бы поддержал, добавив плагин, чтобы поделиться с другими, и добавить хороший DSL для доступа, например: disable_attributes: author,: content ,: comments,: when =>: published?
Редактирование атрибутов, которые не следует редактировать, является ошибкой проверки:
class Post < ActiveRecord::Base
validate :lock_down_attributes_when_published
private
def lock_down_attributes_when_published
return unless published?
message = "must not change when published"
errors.add(:title, message) if title_changed?
errors.add(:published_at, message) if published_at_changed?
end
end
Здесь используются расширения ActiveRecord :: Dirty , представленные в версии 2.2 или около того.
Вы можете добавить настраиваемую проверку, чтобы блокировать изменения атрибутов, если вы находитесь в определенном состоянии. Вы можете жестко кодировать вещи прямо в валидацию. Но я предпочитаю немного более надежный подход с использованием констант, определяющих белый список (список атрибутов, которым разрешено изменять в состоянии) или черный список (список атрибутов, которые не могут изменяться в состоянии).
Вот пример того и другого. подходы. Каждый подход предполагает, что в вашей модели есть метод состояния, который возвращает текущее / новое состояние в виде строки.
Подход с использованием белого списка
WhiteListStateLockMap = {
"state_1" => [
"first_attribute_allowed_to_change_in_state_1",
"second_attribute_allowed_to_change_in_state_1",
...
],
"state_2" => [
"first_attribute_allowed_to_change_in_state_2",
"second_attribute_allowed_to_change_in_state_2",
...
],
...
}
validates :state_lock
def state_lock
# ensure that all changed elements are on the white list for this state.
unless changed & WhiteListStateLockMap[state] == changed
# add an error for each changed attribute absent from the white list for this state.
(changed - WhiteListStateLockMap[state]).each do |attr|
errors.add attr, "Locked while #{state}"
end
end
end
Подход с использованием черного списка
BlackListStateLockMap = {
"state_1" => [
"first_attribute_not_allowed_to_change_in_state_1,
"second_attribute_not_allowed_to_change_in_state_1,
...
],
"state_2" => [
"first_attribute_not_allowed_to_change_in_state_2",
"second_attribute_not_allowed_to_change_in_state_2",
...
],
...
}
validates :state_lock
def state_lock
# ensure that no changed attributes are on the black list for this state.
unless (changed & BlackListStateLockMap[state]).empty?
# add an error for all changed attributes on the black list for this state.
(BlackListStateLockMap[state] & changed).each do |attr|
errors.add attr, "Locked while #{state}"
end
end
end