2009-06-02 8 views
21

Ceci est arrivé il y a un peu (rails model attributes without corresponding column in db) mais il semble que le plugin Rails mentionné ne soit pas maintenu (http://agilewebdevelopment.com/plugins/activerecord_base_without_table). Est-ce qu'il n'y a aucun moyen de le faire avec ActiveRecord tel quel? Si ce n'est pas le cas, y a-t-il un moyen d'obtenir des règles de validation ActiveRecord sans utiliser ActiveRecord?ActiveRecord :: Base sans table

ActiveRecord souhaite que la table existe bien sûr.

+0

double possible de [modèle Rails sans base de données] (http://stackoverflow.com/questions/315850/rails modèle sans base de données) –

+0

dans rails 3, vous pouvez inclure ActiveModel :: Validations, comme beaucoup d'autres modules dans ce même espace de noms qui apportera des fonctionnalités ActiveRecord comme à vos modèles. Dans les rails 4, il y a aussi ActiveModel :: Model, qui inclut beaucoup d'entre eux pour vous faire sentir votre modèle (non-persistant ou personnalisé-persistant) comme un modèle ActiveRecord. – nandinga

+1

La solution en 2016 http://stackoverflow.com/a/34354961/5310342 –

Répondre

39

C'est une approche que je l'ai utilisé dans le passé:

Dans 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 

Dans app/modèles/foo.rb

class Foo < Tableless 
    column :bar, :string 
    validates_presence_of :bar 
end 

Dans 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>> 
+0

Belle. Je vais essayer bientôt. Merci! –

+0

Je suis complètement hors de la boucle sur Rails en ce moment, mais si vous pensez que l'un des nouveaux arrivants a de meilleures réponses que le vôtre, s'il vous plaît faites le moi savoir, merci! –

+0

Faites en sorte que les sous-classes héritent des colonnes parentes: http://stackoverflow.com/a/18237894/217956 – jpemberthy

17

Les 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 
+0

n'ai pas essayé, très intéressant ... Je genre de voulait obtenir la méthode initialize libre et ainsi, mais avec juste des validations je serai heureux ... –

6

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:

class Tableless 
    include ActiveModel::Validations 

    attr_accessor :name 

    validates_presence_of :name 
end 

Pour plus d'informations, vous pouvez consulter la Railscast (ou read about it on AsciiCasts) sur le sujet, ainsi que ce blog post by Yehuda Katz.

VIEUX RÉPONSE 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".

+0

Intéressant J'ai utilisé ce http://codetunes.com/2008/07/20/tableless-models-in-rails/ depuis un certain temps sans problèmes Merci –

+0

Oui, cette solution fonctionne et a besoin du patch table_name, car dans ce cas la classe hérite directement de 'ActiveRecord :: Base' – Dimitar

1

C'est un formulaire de recherche qui présente un objet appelé critères qui a une période imbriqué objet avec commençant et fin attributs.

L'action dans le contrôleur est vraiment simple mais il charge les valeurs à partir d'objets imbriqués sur la forme et un nouveau rendu les mêmes valeurs avec des messages d'erreur si nécessaire.

Fonctionne sur les 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 

De l'avis:

<%= 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 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 pour charger toutes les valeurs à la fois

+0

Salut @Neil Stockbridge, je ne suis pas sûr que ça répond à la question l. –

+0

Il s'agit d'un exemple pratique d'utilisation de Base sans table (qui était la question d'origine), y compris le code pour faire fonctionner Base sans table. Cet exemple fonctionne pour moi avec Rails 3.1.0. Les autres ne l'ont pas fait. J'ai pensé que cela pourrait être utile aux autres. –

+0

Qu'en est-il de la validation? –

9

I figure le plus de réponses le mieux car c'est l'un des premiers résultats de google lors de la recherche de "rails 3.1 modèles sans tables"

J'ai implémenté la même chose sans utiliser ActiveRecord :: Base tout en incluant l'ActiveRecord :: Validations

L'objectif 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é, mais nulle part a encore la capacité d'être validée en utilisant les validations que nous connaissons et aimons tous. J'espère que cela aidera quelqu'un car j'ai passé quelques heures à essayer de comprendre cela aujourd'hui.

+0

Merci, souhait qui avait été disponible dans ROR 2 :) –

+0

Vous devriez inclure 'ActiveModel :: Validations', cependant. Pour plus d'informations, vous pouvez consulter le [Railscast] (http://railscasts.com/episodes/219-active-model) sur le sujet, ainsi que ce [blog de Yehuda Katz] (http://yehudakatz.com/2010/01/10/activemodel-make-any-ruby-object-feel-like-activerecord/). – Dimitar

+0

Merci pour les liens @Dimitar J'ai mis à jour mon commentaire – bloveless

1

Il est the activerecord-tableless gem. C'est une gemme de créer des modèles ActiveRecord sans tableur, donc il a un support pour les validations, les associations, 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 support pour les associations ni les types.

+0

J'ai sorti un bijou, activerecord-tablefree, https://github.com/boltthreads/activerecord-tablefree qui est compatible avec Rails 5, et implémente ce modèle (le les colonnes override utilisées par activeecord-tablefree ont cessé de fonctionner, ont dû passer à une nouvelle approche) –

2

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 
Questions connexes