ActiveRecord :: База без таблицы - PullRequest
21 голосов
/ 02 июня 2009

Это появилось немного назад ( атрибуты модели rails без соответствующего столбца в db ), но похоже, что упомянутый плагин Rails не поддерживается (http://agilewebdevelopment.com/plugins/activerecord_base_without_table). Нет ли способа сделать это с ActiveRecord как есть?

Если нет, есть ли способ получить правила проверки ActiveRecord без использования ActiveRecord?

ActiveRecord, конечно, хочет, чтобы таблица существовала.

Ответы [ 8 ]

39 голосов
/ 02 июня 2009

Это подход, который я использовал в прошлом:

В приложение / модели / 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

In app / models / 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>>
17 голосов
/ 02 июня 2009

Проверки - это просто модуль в ActiveRecord. Вы пытались смешать их с вашей моделью, отличной от ActiveRecord?

class MyModel
  include ActiveRecord::Validations

  # ...
end
9 голосов
/ 30 ноября 2011

Я полагаю, что чем больше ответов, тем лучше, так как это один из первых результатов в Google при поиске "моделей rails 3.1 без таблиц"

Я реализую то же самое, не используя ActiveRecord :: Base, включая ActiveRecord :: Validations

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

class Payment
  include ActiveModel::Validations
  attr_accessor :cc_number, :payment_type, :exp_mm, :exp_yy, :card_security, :first_name, :last_name, :address_1, :address_2, :city, :state, :zip_code, :home_telephone, :email, :new_record

  validates_presence_of :cc_number, :payment_type, :exp_mm, :exp_yy, :card_security, :first_name, :last_name, :address_1, :address_2, :city, :state

  def initialize(options = {})
    if options.blank?
      new_record = true
    else
      new_record = false
    end
    options.each do |key, value|
      method_object = self.method((key + "=").to_sym)
      method_object.call(value)
    end
  end

  def new_record?
    return new_record
  end

  def to_key
  end

  def persisted?
    return false
  end
end

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

6 голосов
/ 17 декабря 2009

ОБНОВЛЕНИЕ: Для Rails 3 это можно сделать очень просто. В Rails 3+ вы можете использовать новый модуль ActiveModel и его подмодули. Это должно работать сейчас:

class Tableless
  include ActiveModel::Validations

  attr_accessor :name

  validates_presence_of :name
end

Для получения дополнительной информации, вы можете проверить Railscast (или прочитать об этом на AsciiCasts ) по этой теме, а также это сообщение в блоге Иегуда Каца .

СТАРЫЙ ОТВЕТ СЛЕДУЕТ:

Возможно, вам понадобится добавить это к решению, предложенному Джоном Топли в предыдущем комментарии:

class Tableless

  class << self
    def table_name
      self.name.tableize
    end
  end

end

class Foo < Tableless; end
Foo.table_name # will return "foos"

Это дает вам «поддельное» имя таблицы, если оно вам нужно. Без этого метода Foo::table_name будет оцениваться как "tablelesses".

4 голосов
/ 14 июня 2009

Я нашел эту ссылку, которая работает КРАСИВО.

http://codetunes.com/2008/07/20/tableless-models-in-rails/

2 голосов
/ 14 августа 2013

Просто дополнение к принятому ответу:

Заставьте ваши подклассы наследовать родительские столбцы с помощью:

class FakeAR < ActiveRecord::Base
  def self.inherited(subclass)
    subclass.instance_variable_set("@columns", columns)
    super
  end

  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

  # Overrides save to prevent exceptions.
  def save(validate = true)
    validate ? valid? : true
  end
end
1 голос
/ 20 февраля 2013

Существует камень активных записей без таблиц . Это жемчужина для создания таблиц ActiveRecord моделей, поэтому он поддерживает проверки, ассоциации, типы. Поддерживает Active Record 2.3, 3.0, 3.2

Рекомендованный способ сделать это в Rails 3.x (с использованием ActiveModel) не поддерживает ни ассоциации, ни типы.

1 голос
/ 26 октября 2011

Это поисковая форма, которая представляет объект с именем критерий , который имеет вложенный период объект с началом и концом атрибутами.

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

Работает на Rails 3.1.

Модель:

class Criteria < ActiveRecord::Base
  class << self

    def column_defaults
      {}
    end

    def column_names
      []
    end
  end # of class methods

  attr_reader :period

  def initialize values
    values ||= {}
    @period = Period.new values[:period] || {}
    super values
  end

  def period_attributes
    @period
  end
  def period_attributes= new_values
    @period.attributes = new_values
  end
end

В контроллере:

def search
  @criteria = Criteria.new params[:criteria]
end

В помощнике:

def criteria_index_path ct, options = {}
  url_for :action => :search
end

На виде:

<%= form_for @criteria do |form| %>
  <%= form.fields_for :period do |prf| %>
    <%= prf.text_field :beginning_as_text %>
    <%= prf.text_field :end_as_text %>
  <% end %>
  <%= form.submit "Search" %>
<% end %>

Создает HTML:

<form action="/admin/search" id="new_criteria" method="post">
  <input id="criteria_period_attributes_beginning_as_text" name="criteria[period_attributes][beginning_as_text]" type="text"> 
  <input id="criteria_period_attributes_end_as_text" name="criteria[period_attributes][end_as_text]" type="text">

Примечание : атрибут действия, предоставляемый помощником, и формат именования вложенных атрибутов, упрощающий для контроллера загрузку всех значений одновременно

...