La base de ActiveRecord Sans tableau
-
06-09-2019 - |
Question
Cela est arrivé il y a un peu (modèle attributs sans colonne correspondante db ) mais il semble que le plugin Rails est mentionné pas maintenu ( http://agilewebdevelopment.com/plugins/activerecord_base_without_table ). Yat-il pas possible de le faire avec ActiveRecord comme il est?
Dans le cas contraire, il est possible d'obtenir des règles de validation ActiveRecord sans utiliser ActiveRecord?
ActiveRecord veut la table existe, bien sûr.
La solution
Ceci est une approche que je l'ai utilisé dans le passé:
app / modèles / 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
app / modèles / foo.rb
class Foo < Tableless
column :bar, :string
validates_presence_of :bar
end
script / console
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>>
Autres conseils
Validations sont simplement un module dans ActiveRecord. Avez-vous essayé de les mélanger dans votre modèle non-ActiveRecord?
class MyModel
include ActiveRecord::Validations
# ...
end
Je figure les plus de réponses mieux puisque c'est l'un des premiers résultats dans Google lors de la recherche « rails 3.1 modèles sans tables »
J'ai implémente la même chose sans utiliser ActiveRecord :: Base tout en incluant ActiveRecord :: Validations
Le but principal était d'obtenir tout ce travail dans formtastic, et au-dessous j'ai inclus un paiement de l'échantillon qui ne sera pas sauvé partout mais a encore la capacité d'être validée en utilisant les validations que nous connaissons et aimons tous.
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
J'espère que cela aide quelqu'un comme je l'ai passé quelques heures à essayer de comprendre cela aujourd'hui.
Mise à jour: Pour Rails 3, cela peut être fait très facile. Dans Rails 3+, vous pouvez utiliser le nouveau module ActiveModel
et ses sous-modules. Cela devrait fonctionner maintenant:
class Tableless
include ActiveModel::Validations
attr_accessor :name
validates_presence_of :name
end
Pour plus d'informations, vous pouvez consulter la Railscast (ou lire sur AsciiCasts ) sur le sujet, ainsi que ce blog par Yehuda Katz .
RÉPONSE VIEUX suit:
Vous devrez peut-être ajouter à la solution, proposée par John Topley dans le commentaire précédent:
class Tableless
class << self
def table_name
self.name.tableize
end
end
end
class Foo < Tableless; end
Foo.table_name # will return "foos"
Cela vous donne un nom de table « faux », si vous en avez besoin. Sans cette méthode, Foo::table_name
évaluera à "tablelesses".
J'ai trouvé ce lien qui fonctionne à merveille.
http://codetunes.com/2008/07/ 20 / tableless-modèles en rails /
Juste un ajout à la réponse acceptée:
Faites vos sous-classes héritent des colonnes parent avec:
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
Ceci est un formulaire de recherche qui présente un objet appelé critères qui a une imbriqué période objet avec commençant et end attributs.
L'action du contrôleur est très simple mais il charge les valeurs à partir d'objets imbriqués sur la forme et re-rend les mêmes valeurs avec des messages d'erreur si nécessaire.
Travaux sur Rails 3.1.
Le modèle:
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
Dans le contrôleur:
def search
@criteria = Criteria.new params[:criteria]
end
Dans l'assistant:
def criteria_index_path ct, options = {}
url_for :action => :search
end
Dans la vue:
<%= 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 %>
Produit le code 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">
Remarque : L'attribut d'action fourni par l'assistant et les attributs imbriqués format de nommage qui le rend si simple pour le contrôleur de charger toutes les valeurs à la fois
Il est le joyau activerecord-tableless . Il est un petit bijou pour créer des modèles tableless ActiveRecord, donc il a un support pour les associations, les validations, les types. Il prend en charge Active record de 2,3, 3,0, 3,2
La méthode recommandée pour le faire dans 3.x Rails (à l'aide ActiveModel) n'a pas de soutien pour les associations ni les types.