Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails gem/plugin for dynamic custom fields in model

Is there any gem/plugin for ruby on rails which gives the ability to define custom fields in a model at runtime with no need to change the model itself for every different field.

I'm looking for something like Redmine acts_as_customizable plugin which is packaged as a gem usable in the rails way, i.e.

gem 'gemname'
rails g something
rails db:migrate

class Model < ActiveRecord::Base
  acts_as_something
end

Here are the CustomField and the CustomValue classes used in Redmine.

Edit:

Since my question is not clear I add a brief use case which explains my need better:

I want users to be able to design their own forms, and collect data submitted on those forms. An important decision is the design of how these custom dynamic records are stored and accessed.

Taken from here, in this article approach the problem with different ideas, but they all have drawbacks. For this reason I'm asking if the issue has been approached in some gem with no need to rethink the whole problem.

like image 500
Fabio Avatar asked Apr 13 '12 16:04

Fabio


3 Answers

I'm not aware of a gem that does this, but serialize works quite well and it's a built-in. You get a NoSQL-ish document store backed by JSON/YAML.

If you allow user to create a custom form, you can pass nested arrays et cetera directly into the attribute. However, if you need to validate the structure, you're on your own.

like image 98
Prathan Thananart Avatar answered Sep 20 '22 15:09

Prathan Thananart


I'm afraid it could be tricky and complicated to do it in ActiveRecoand (generally in standard relational database). Take a look at http://mongoid.org/docs/documents/dynamic.html - this mechanism is using nosql feature.

You can also may try the following trick:

1/ Serialize a hash with your custom fields in the database column, for example { :foo => 'bar', :fiz => 'biz' }

2/ After load a record from database do some metaprogramming and define corresponding methods on the record's singleton class, for instance (assume that custom fields are stored and serialized in custom_fields column):

after_initialize :define_custom_methods
# ..or other the most convinient callback

def define_custom_methods
  # this trick will open record's singleton class
  singleton_class = (class << self; self; end)
  # iterate through custom values and define dynamic methods
  custom_fields.each_with_key do |key, value|
    singleton_class.send(:define_method, key) do
      value
    end
  end
end
like image 37
luacassus Avatar answered Sep 19 '22 15:09

luacassus


Since rails 3.2 you can use store method. Just include following in your model:

store :properties, accessors: [:property1, :property2, :property3...]

You only need to change your model once (to add properties field to db table). You can add more properties later without altering the schema.

The way this works is by serializing properties hash into YAML and saving it into database. It it suitable for most cases, but not if you'd like to use these values in db queries later.

like image 39
Milovan Zogovic Avatar answered Sep 18 '22 15:09

Milovan Zogovic