Rails Model without a table
Asked Answered
K

7

41

I want to create a select list for lets say colors, but dont want to create a table for the colors. I have seen it anywhere, but can't find it on google.

My question is: How can I put the colors in a model without a database table?

Or is there a better rails way for doing that?

I have seen someone putting an array or a hash directly in the model, but now I couldn't find it.

Kreager answered 17/1, 2013 at 22:14 Comment(2)
possible duplicate of Rails model without databaseFumed
I want to use this for a complex search filter form to save the form values but which will not be saved to the DB.Oleson
C
66
class Model

  include ActiveModel::Validations
  include ActiveModel::Conversion
  extend ActiveModel::Naming

  attr_accessor :whatever

  validates :whatever, :presence => true

  def initialize(attributes = {})
    attributes.each do |name, value|
      send("#{name}=", value)
    end
  end

  def persisted?
    false
  end

end

attr_accessor will create your attributes and you will create the object with initialize() and set attributes.

The method persisted will tell there is no link with the database. You can find examples like this one: http://railscasts.com/episodes/219-active-model?language=en&view=asciicast

Which will explain you the logic.

Carbineer answered 17/1, 2013 at 22:21 Comment(0)
F
28

The answers are fine for 2013 but since Rails 4 all the database independent features of ActiveRecord are extracted into ActiveModel. Also, there's an awesome official guide for it.

You can include as many of the modules as you want, or as little.

As an example, you just need to include ActiveModel::Model and you can forgo such an initialize method:

def initialize(attributes = {})
  attributes.each do |name, value|
    send("#{name}=", value)
  end
end

Just use:

attr_accessor :name, :age
Felton answered 20/1, 2017 at 7:32 Comment(3)
Neat but it doesn't seem to allow belongs_to. I want to use @filterModel.sector.name and use the sector_id in the model.Oleson
include ActiveModel::Model allows also to avoid the cancan ArgumentError: cancancan (3.0.0) lib/cancan/controller_resource_builder.rb:8:in initialize'`Winsor
Using ActiveModel is the right approach in 2022Mischa
M
11

The easiest answer is simply to not subclass from ActiveRecord::Base. Then you can just write your object code.

Mentally answered 17/1, 2013 at 22:19 Comment(8)
i dont need validation. all i need is an @colors variable with the colors, so i can put them in my select list form helper.Kreager
Then the file color.rb will just have def Color [some object code] end. It just becomes a plain old object.Mentally
Oh, sorry, I only saw half your comment. If thats really all you need, have you thought about using a constant? Assuming of course that you're just offering a static list of colors. Or perhaps even better, a partial with a select list with the colors you want available that you can just stick anywhere.Mentally
ok, thanks. i will try it. but do you know what i mean with the model? i have seen it anywhere, but couldnt find it now. the guy created a model with an array or a hash and no table.Kreager
I'm sorry, I don't think I'm understanding. Unless there is some other table-like behavior you're looking to keep, a Model without a table is just an Object. To add an array or hash is just a matter of adding it to the Object as either an instance or a class variable (which is explained here railstips.org/blog/archives/2006/11/18/…)Mentally
that article doesn't work for me using Rails 4.2 -- get undefined method errors on the first two lines class_inheritable_accessor and self.columns for MyModel(Table doesn't exist):ClassMessiah
article linked to doesn't solve, at least for Rails 4.2. However the article links to another article which does help snipplr.com/view/1849/tableless-modelMessiah
Article link is broken.Cumulonimbus
T
6

What worked for me in Rails 6:

class MyClass
  include ActiveModel::Model

  attr_accessor :my_property
end
Tatter answered 4/5, 2021 at 15:41 Comment(0)
A
2

If the reason you need a model without an associated table is to create an abstract class real models inherit from - ActiveRecord supports that:

class ModelBase < ActiveRecord::Base
  self.abstract_class = true
end
Anam answered 12/4, 2020 at 16:46 Comment(3)
Note an abstract class cannot be instantiated (at laest in Rails 6.0); ModelBase.new would raise NotImplementedErrorDevout
@MasaSakano It's also not needed in Rails 6. ActiveModel is already what an ActiveRecord with abstract_class is.Anam
ActiveModel and ActiveRecord are different. For example, having an object include ActiveModel would allow you to use that model in forms and views. But it won't allow you to use store_accessor. Methods that are defined in ActiveRecord. In my case, I would like to test some concerns, but not by testing the ActiveRecord object where I included the module, but on a "virtual" or new object defined in the test file. This is not possible to do with just including ActiveModel since the concern is using scope and store_accessor.Cephalonia
T
2

I am in Rails 7, but I think this works also in Rails 6:

class MyModel
  include ActiveModel::Model
  include ActiveModel::Attributes

  attribute :title, :string
  attribute :created_at, :datetime
end

I like this more than the attr_accessor alternative because it allows me to parse attributes to datatypes.

Tatter answered 21/9, 2023 at 14:31 Comment(0)
P
1

If you want to have a select list (which does not evolve) you can define a method in your ApplicationHelper that returns a list, for example:

 def my_color_list
   [
     "red",
     "green",
     "blue"
   ]
 end
Pyrology answered 17/1, 2013 at 22:20 Comment(1)
Yeah but collection_select only accepts models that respond to method names. api.rubyonrails.org/classes/ActionView/Helpers/…Oleson

© 2022 - 2024 — McMap. All rights reserved.