Я хочу создать модель Rails (2.1 и 2.2) с проверками ActiveRecord, но без таблицы базы данных. Какой подход наиболее широко используется? Я нашел несколько плагинов, которые заявляют, что предлагают эту функциональность, но многие из них, похоже, не широко используются или поддерживаются. Что мне рекомендует сделать сообщество? Прямо сейчас я склоняюсь к тому, чтобы придумать собственное решение на основе это сообщение в блоге.
Это похоже на дубликат stackoverflow.com/questions/937429/…, который на самом деле предлагает лучшее решение.





просто создайте новый файл, заканчивающийся на «.rb», следуя принятым вами соглашениям (единственное число для имени файла и имени класса, подчеркнутое для имени файла, верблюжий регистр для имени класса) в вашем каталоге «models /». Ключевым моментом здесь является не наследовать вашу модель от ActiveRecord (потому что именно AR дает вам функциональность базы данных). например: для новой модели автомобилей создайте файл с именем "car.rb" в каталоге models / и внутри вашей модели:
class Car
# here goes all your model's stuff
end
edit: кстати, если вам нужны атрибуты в своем классе, вы можете использовать здесь все, что используете на ruby, просто добавьте пару строк с помощью attr_accessor:
class Car
attr_accessor :wheels # this will create for you the reader and writer for this attribute
attr_accessor :doors # ya, this will do the same
# here goes all your model's stuff
end
edit # 2: после прочтения комментария Майка я бы посоветовал вам пойти его путем, если вам нужна вся функциональность ActiveRecord, но без таблицы в базе данных. Если вам просто нужен обычный класс Ruby, возможно, вы найдете это решение лучше;)
но это не дает ему подтверждения AR.
хорошая точка зрения. Бьюсь об заклад, есть много вариантов использования обоих решений :)
Как насчет того, чтобы пометить класс как абстрактный?
class Car < ActiveRecord::Base
self.abstract = true
end
это скажет rails, что у класса Car нет соответствующей таблицы.
[редактировать]
это вам не поможет, если вам нужно будет сделать что-то вроде:
my_car = Car.new
Я думаю, что публикация в блоге, на которую вы ссылаетесь, - лучший способ. Я бы только посоветовал перенести заглушенные методы в модуль, чтобы не загрязнять ваш код.
Я с Хонзой, и я думаю, что этот пост - ваш единственный вариант, если вам нужны проверки AR в ваших POCO. Удачи.
Сообщение отсутствует, когда я был здесь, не могли бы вы разместить его здесь?
Rails представил ActiveModel как способ решения этой проблемы - ответ на этот вопрос ниже stackoverflow.com/a/34354961/1511504
Есть скринкаст о модели неактивной записи, составленной Райаном Бейтсом. Хорошее место для начала.
На всякий случай вы его еще не смотрели.
опять же, это не решает проблему плакатов с использованием проверок AR.
Я выполнил эти инструкции в своем приложении, и оно отлично сработало.
Делайте так, как сказал Тьяго Пинто, и просто не наследуйте вашу модель от ActiveRecord :: Base. Это будет обычный класс Ruby, который вы вставите в файл в каталоге app / models /. Если ни в одной из ваших моделей нет таблиц, и вы вообще не используете базу данных или ActiveRecord в своем приложении, обязательно измените файл environment.rb, добавив в него следующую строку:
config.frameworks -= [:active_record]
Это должно быть в блоке Rails::Initializer.run do |config|.
так же, как ответ Тьяго Пинто, это не поможет нашему другу использовать проверки AR в своем классе.
Это подход, который я использовал в прошлом:
В приложение / модели / tableless.rb
class Tableless < ActiveRecord::Base
def self.columns
@columns ||= [];
end
def self.column(name, sql_type = nil, default = nil, null = true)
columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default,
sql_type.to_s, null)
end
# Override the save method to prevent exceptions.
def save(validate = true)
validate ? valid? : true
end
end
В приложение / модели / foo.rb
class Foo < Tableless
column :bar, :string
validates_presence_of :bar
end
В скрипт / консоль
Loading development environment (Rails 2.2.2)
>> foo = Foo.new
=> #<Foo bar: nil>
>> foo.valid?
=> false
>> foo.errors
=> #<ActiveRecord::Errors:0x235b270 @errors = {"bar"=>["can't be blank"]}, @base=#<Foo bar: nil>>
Хорошо работает и очень легкий. Rails 2.3 будет немного жаловаться на отсутствие таблицы в скрипте / консоли, но добавление self.abstract_class = true решает эту проблему (без предотвращения создания экземпляров).
Мне это кажется ужасным. Зачем наследовать от ActiveRecord :: Base, если вам не нужна серверная часть базы данных? Существуют и другие библиотеки, которые предоставляют функциональные возможности проверки, которые не предполагают наличия серверной части базы данных.
@Rekin См. stackoverflow.com/questions/3416484/…
@Дэйвид. Хорошо, это одно. Любые другие?
Для записи: первый вариант (stackoverflow.com/questions/3416484/…) предназначен только для Rails 3.
Кто-нибудь когда-либо пытался включить ActiveRecord::Validations и ActiveRecord::Validations::ClassMethods в класс, не являющийся Active Record, и посмотреть, что происходит при попытке настроить валидаторы?
Я уверен, что между средой проверки и самим ActiveRecord существует множество зависимостей. Но вам может удастся избавиться от этих зависимостей, создав свою собственную структуру валидации из инфраструктуры валидации AR.
Просто идея.
Обновлять: oopps, это более или менее то, что предлагается в сообщении, связанном с вашим вопросом. Извините за беспокойство.
Ваш ответ теперь полезен, потому что сообщение в блоге больше не существует.
Используйте Validatable gem. Как вы говорите, есть решения на основе AR, но они, как правило, хрупкие.
Вам следует проверить плагин PassiveRecord. Он дает вам интерфейс, подобный ActiveRecord, для моделей, не относящихся к базе данных. Это просто и меньше хлопот, чем борьба с ActiveRecord.
Мы используем PassiveRecord в сочетании с гемом Валидный, чтобы получить желаемое поведение OP.
В наши дни я, вероятно, включил бы ActiveModel и все, что мне нужно.
Я создал быстрый миксин, чтобы справиться с этим, согласно предложению Джона Топли.
В Rails 3 есть лучший способ сделать это: http://railscasts.com/episodes/219-active-model
Я проголосовал за вас, потому что согласен, что это более чистый и лучший способ сделать это, особенно если вы начинаете новый проект. Однако я обнаружил, что решение Джона Топли лучше подходит для проекта, где большому количеству кода все еще нужно думать, что ваша модель является подклассом ActiveRecord :: Base. Одним из конкретных примеров нелегко работающего этого метода является то, что ваш код использует сторонний плагин, который полагается на ActiveRecord.
В Rails 4 также есть ActiveModel :: Model, который включает в себя многие модули ActiveModel и некоторую другую магию, чтобы вы почувствовали свою (непостоянную или настраиваемую) модель как модель ActiveRecord.
Теперь есть более простой способ:
class Model
include ActiveModel::Model
attr_accessor :var
validates :var, presence: true
end
Код ActiveModel::Model:
module ActiveModel
module Model
def self.included(base)
base.class_eval do
extend ActiveModel::Naming
extend ActiveModel::Translation
include ActiveModel::Validations
include ActiveModel::Conversion
end
end
def initialize(params = {})
params.each do |attr, value|
self.public_send("#{attr} = ", value)
end if params
end
def persisted?
false
end
end
end
http://api.rubyonrails.org/classes/ActiveModel/Model.html
Это путь сейчас
Для полноты:
Rails теперь (в V5) имеет удобный модуль, который вы можете включить:
include ActiveModel::Model
Это позволяет вам инициализировать с помощью хэша и, помимо прочего, использовать проверки.
Полная документация - здесь.
Связанная запись в блоге теперь мертва.