extend_at 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
- data/Gemfile +4 -0
- data/MIT-license.txt +23 -0
- data/README.markdown +208 -0
- data/Rakefile +1 -0
- data/extend_at.gemspec +22 -0
- data/lib/extend_at/version.rb +3 -0
- data/lib/extend_at.rb +294 -0
- metadata +65 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/MIT-license.txt
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2011 Andrés Borek
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any
|
4
|
+
person obtaining a copy of this software and associated
|
5
|
+
documentation files (the "Software"), to deal in the
|
6
|
+
Software without restriction, including without limitation
|
7
|
+
the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the
|
9
|
+
Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice
|
13
|
+
shall be included in all copies or substantial portions of
|
14
|
+
the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
17
|
+
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
18
|
+
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
19
|
+
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
20
|
+
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
21
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
22
|
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
23
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
# Extend at
|
2
|
+
|
3
|
+
This gem allows you to extend the columns from your model without migrations, you can, i.e., develop your own content types, like in Drupal
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
<code>gem install extend_at</code>
|
8
|
+
|
9
|
+
### Rails 3
|
10
|
+
Add in your Gemfile:
|
11
|
+
<code>gem 'extend_at', :git => 'git://github.com/anga/extend_at.git'</code>
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
Only you need to add the next line in your model.
|
16
|
+
|
17
|
+
<code>extend_at :configuration</code>
|
18
|
+
|
19
|
+
For example:
|
20
|
+
|
21
|
+
class User < ActiveRecord::Base
|
22
|
+
extend_at :extra
|
23
|
+
end
|
24
|
+
|
25
|
+
Now you can write your configuration like:
|
26
|
+
|
27
|
+
user.extra.private_photos = true
|
28
|
+
user.extra.subscribe_to_news = false
|
29
|
+
user.extra.perfil_description = ''
|
30
|
+
user.save
|
31
|
+
|
32
|
+
### Columns configuration
|
33
|
+
|
34
|
+
You can configurate each column.
|
35
|
+
|
36
|
+
#### Set column type
|
37
|
+
|
38
|
+
You can set the type of the colum.
|
39
|
+
|
40
|
+
class User < ActiveRecord::Base
|
41
|
+
extend_at :extra, :columns => {
|
42
|
+
:private_photos => {
|
43
|
+
:type => :boolean
|
44
|
+
}, :age => {
|
45
|
+
:type => :get_type
|
46
|
+
}, :perfil_description => {
|
47
|
+
:type => lambda {
|
48
|
+
String
|
49
|
+
}
|
50
|
+
}, :last_loggin => {
|
51
|
+
:type => Time.now.class
|
52
|
+
}, :subscribe_to_rss => :get_rss_config
|
53
|
+
}
|
54
|
+
|
55
|
+
protected
|
56
|
+
def get_type
|
57
|
+
Fixnum
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_rss_config
|
61
|
+
{
|
62
|
+
:type => :boolean
|
63
|
+
}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
You can use any class, but if you need use boolean values, you must use :boolean.
|
68
|
+
|
69
|
+
#### Set default value
|
70
|
+
|
71
|
+
class User < ActiveRecord::Base
|
72
|
+
extend_at :extra, :columns => {
|
73
|
+
:private_photos => {
|
74
|
+
:type => :boolean,
|
75
|
+
:default => true
|
76
|
+
}, :age => {
|
77
|
+
:type => :get_type,
|
78
|
+
:default => 1
|
79
|
+
}, :perfil_description => {
|
80
|
+
:type => lambda {
|
81
|
+
String
|
82
|
+
},
|
83
|
+
:default => :get_default_perfil_description
|
84
|
+
}, :last_loggin => {
|
85
|
+
:type => Time.now.class,
|
86
|
+
:default => lambda {
|
87
|
+
self.created_at.time
|
88
|
+
}
|
89
|
+
}, :subscribe_to_rss => :get_rss_config
|
90
|
+
}
|
91
|
+
|
92
|
+
protected
|
93
|
+
def get_type
|
94
|
+
Fixnum
|
95
|
+
end
|
96
|
+
|
97
|
+
def get_rss_config
|
98
|
+
{
|
99
|
+
:type => :boolean,
|
100
|
+
:default => true
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
def get_default_perfil_description
|
105
|
+
Description.where(:user_id => self.id).default
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
#### Set validation
|
110
|
+
class User < ActiveRecord::Base
|
111
|
+
extend_at :extra, :columns => {
|
112
|
+
:private_photos => {
|
113
|
+
:type => :boolean,
|
114
|
+
:default => true
|
115
|
+
}, :age => {
|
116
|
+
:type => :get_type,
|
117
|
+
:default => 1,
|
118
|
+
:validate => lambda {
|
119
|
+
|age|
|
120
|
+
errors.add :config_age, "Are you Matusalén?" if age > 150
|
121
|
+
errors.add :config_age, "Are you a fetus?" if age <= 0
|
122
|
+
}
|
123
|
+
}, :perfil_description => {
|
124
|
+
:type => lambda {
|
125
|
+
String
|
126
|
+
},
|
127
|
+
:default => :get_default_perfil_description,
|
128
|
+
:lambda => :must_not_have_strong_language
|
129
|
+
}, :last_loggin => {
|
130
|
+
:type => Time.now.class,
|
131
|
+
:default => lambda {
|
132
|
+
self.created_at.time
|
133
|
+
},
|
134
|
+
:validate => lambda {
|
135
|
+
|time|
|
136
|
+
errors.add :config_last_loggin, "You can't loggin in the future" if time > Time.now
|
137
|
+
}
|
138
|
+
}, :subscribe_to_rss => :get_rss_config
|
139
|
+
}
|
140
|
+
|
141
|
+
protected
|
142
|
+
STRONG_WORD = [
|
143
|
+
#...
|
144
|
+
]
|
145
|
+
|
146
|
+
def get_type
|
147
|
+
Fixnum
|
148
|
+
end
|
149
|
+
|
150
|
+
def get_rss_config
|
151
|
+
{
|
152
|
+
:type => :boolean,
|
153
|
+
:default => true
|
154
|
+
}
|
155
|
+
end
|
156
|
+
|
157
|
+
def get_default_perfil_description
|
158
|
+
Description.where(:user_id => self.id).default
|
159
|
+
end
|
160
|
+
|
161
|
+
def must_not_have_strong_language(desc)
|
162
|
+
errors.add :cofig_perfil_description, "You must not have strong language" if desc =~ /(#{STRONG_WORD.join('|')})/
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
### Integration in the views
|
167
|
+
|
168
|
+
If you like to use come configuration variable in your views you only need put the name of the input like <code>:config_name</code>, for example:
|
169
|
+
|
170
|
+
<% form_for(@user) do |f| %>
|
171
|
+
...
|
172
|
+
<div class="field">
|
173
|
+
<%= f.label :extra_private_photos %><br />
|
174
|
+
<%= f.check_box :extra_private_photos %>
|
175
|
+
</div>
|
176
|
+
...
|
177
|
+
<% end %>
|
178
|
+
|
179
|
+
### Tips
|
180
|
+
|
181
|
+
If you like to do something more dynamic, like create columns and validations depending of some model or configuration, the you can do something like this:
|
182
|
+
|
183
|
+
class User < ActiveRecord::Base
|
184
|
+
extend_at :extra, :columns => :get_columns
|
185
|
+
serialize :columns_name
|
186
|
+
|
187
|
+
protected
|
188
|
+
def get_columns
|
189
|
+
columns = {}
|
190
|
+
columns_name.each do |name|
|
191
|
+
config = ColumConfig.where(:user_id => self.id, :column => name).first
|
192
|
+
columns[name.to_sym] = {
|
193
|
+
:type => eval(config.class_type),
|
194
|
+
:default => config.default_value,
|
195
|
+
:validate => get_validation(config.validation)
|
196
|
+
}
|
197
|
+
end
|
198
|
+
|
199
|
+
columns
|
200
|
+
end
|
201
|
+
|
202
|
+
# Accept a name of a validation and return the Proc with the validation code
|
203
|
+
def get_validation(validation_type)
|
204
|
+
# ...
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
This code read the configuration of the columns when you acces to extra column
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/extend_at.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "extend_at/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "extend_at"
|
7
|
+
s.version = ExtendModelAt::VERSION
|
8
|
+
s.authors = ["Andrés José Borek"]
|
9
|
+
s.email = ["andres.b.dev@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Create dynamic fields in your models (like content types in Drupal)}
|
12
|
+
s.description = %q{This gem allows you to extend the columns from your model without migrations, you can, i.e., develop your own content types, like in Drupal}
|
13
|
+
|
14
|
+
s.rubyforge_project = "extend_at"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "rspec"
|
22
|
+
end
|
data/lib/extend_at.rb
ADDED
@@ -0,0 +1,294 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "extend_at/version"
|
3
|
+
|
4
|
+
module ExtendModelAt
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
# The object how controll the data
|
10
|
+
class Extention
|
11
|
+
def initialize(options={})
|
12
|
+
@model = options[:model]
|
13
|
+
@column_name = options[:column_name].to_s
|
14
|
+
@columns = options[:columns]
|
15
|
+
@value = get_defaults_values options
|
16
|
+
|
17
|
+
raise "#{@column_name} should by text or string not #{options[:model].column_for_attribute(@column_name.to_sym).type}" if not [:text, :stiring].include? options[:model].column_for_attribute(@column_name.to_sym).type
|
18
|
+
|
19
|
+
out = YAML.parse(@model[@column_name].to_s)
|
20
|
+
if out == false
|
21
|
+
db_value = nil
|
22
|
+
else
|
23
|
+
db_value = out.to_ruby
|
24
|
+
end
|
25
|
+
@value.merge! db_value if db_value.kind_of? Hash
|
26
|
+
|
27
|
+
initialize_values
|
28
|
+
|
29
|
+
@model.attributes[@column_name] = @value
|
30
|
+
@model.save(:validate => false)
|
31
|
+
end
|
32
|
+
|
33
|
+
def [](key)
|
34
|
+
@value[key.to_s]
|
35
|
+
end
|
36
|
+
|
37
|
+
def []=(key, value)
|
38
|
+
if @columns[key.to_sym].kind_of? Hash and ((@columns[key.to_sym][:type] == :boolean and (not [true.class, false.class].include? value.class)) or
|
39
|
+
((not [:boolean, nil].include?(@columns[key.to_sym][:type])) and @columns[key.to_sym][:type] != value.class ))
|
40
|
+
raise "#{value.inspect} is not a valid type, expected #{@columns[key.to_sym][:type]}"
|
41
|
+
end
|
42
|
+
@value[key.to_s] = value
|
43
|
+
@model.send :"#{@column_name}=", @value.to_yaml
|
44
|
+
end
|
45
|
+
|
46
|
+
# Use the undefined method as a column
|
47
|
+
def method_missing(m, *args, &block)
|
48
|
+
# If the method don't finish with "=" is fore read
|
49
|
+
if m !~ /\=$/
|
50
|
+
self[m.to_s]
|
51
|
+
# but if finish with "=" is for wirte
|
52
|
+
else
|
53
|
+
column_name = m.to_s.gsub(/\=$/, '')
|
54
|
+
self[column_name.to_s] = args.first
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def initialize_values
|
61
|
+
if not @value.kind_of? Hash
|
62
|
+
@model.attributes[@column_name] = {}.to_yaml
|
63
|
+
@model.save
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def get_defaults_values(options = {})
|
68
|
+
defaults_ = {}
|
69
|
+
options[:columns].each do |column, config|
|
70
|
+
defaults_[column.to_s] = @columns[column.to_sym][:default] || nil
|
71
|
+
end
|
72
|
+
defaults_
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
module ClassMethods
|
77
|
+
def extend_at(column_name, options = {})
|
78
|
+
assign_attributes_eval = "
|
79
|
+
# Rewrite the mass assignment method because we need to accept write code like User.new :config_born => 10.years.ago
|
80
|
+
def assign_attributes(attributes = nil, options = {})
|
81
|
+
attributes.each_pair do |key, value|
|
82
|
+
if key.to_s =~ /^#{column_name}_/
|
83
|
+
rb = \"#{column_name}.\#\{key.to_s.gsub(/^#{column_name}_/,'')\} = value\"
|
84
|
+
eval rb, binding
|
85
|
+
end
|
86
|
+
end
|
87
|
+
attributes.delete_if do |key,value|
|
88
|
+
key.to_s =~ /^#{column_name}_/
|
89
|
+
end
|
90
|
+
super attributes, options
|
91
|
+
end
|
92
|
+
|
93
|
+
# Return the value of <<attributes>> methods like <column name>_<extended column name>
|
94
|
+
def [](column)
|
95
|
+
if column.to_s =~ /^#{column_name}_[a-zA-Z_][a-zA-Z_0-9]*\=?$/
|
96
|
+
rb = \"#{column_name}.\#\{column.to_s.gsub(/^#{column_name}_/,'')\}\"
|
97
|
+
eval rb, binding
|
98
|
+
else
|
99
|
+
super
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Write the value of <<attributes>> methods like <column name>_<extended column name>
|
104
|
+
def []=(column, value)
|
105
|
+
if column.to_s =~ /^#{column_name}_[a-zA-Z_][a-zA-Z_0-9]*\=?$/
|
106
|
+
rb = \"#{column_name}.\#\{column\} = value\"
|
107
|
+
eval rb, binding
|
108
|
+
else
|
109
|
+
super
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Respond to ethod like <column name>_<extended column name> for read or write
|
114
|
+
def self.respond_to?(symbol, include_private=false)
|
115
|
+
if symbol.to_s =~ /^#{column_name}_[a-zA-Z_][a-zA-Z_0-9]*\=?$/
|
116
|
+
return true
|
117
|
+
else
|
118
|
+
super
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Accept method like <column name>_<extended column name> for read or write
|
123
|
+
def method_missing(m, *args, &block)
|
124
|
+
if m.to_s =~ /^#{column_name}_[a-zA-Z_][a-zA-Z_0-9]*\=$/
|
125
|
+
rb = \"self.#{column_name}.\#\{m.to_s.gsub(/^#{column_name}_/, '')} = args.first\"
|
126
|
+
return eval rb, binding
|
127
|
+
elsif m.to_s =~ /^#{column_name}_[a-zA-Z_][a-zA-Z_0-9]*$/
|
128
|
+
rb = \"self.#{column_name}.\#\{m.to_s.gsub(/^#{column_name}_/, '')}\"
|
129
|
+
return eval rb, binding
|
130
|
+
else
|
131
|
+
super
|
132
|
+
end
|
133
|
+
end
|
134
|
+
"
|
135
|
+
|
136
|
+
self.class_eval <<-EOS
|
137
|
+
eval assign_attributes_eval
|
138
|
+
EOS
|
139
|
+
|
140
|
+
class_eval <<-EOV
|
141
|
+
public
|
142
|
+
validate :extend_at_validations
|
143
|
+
|
144
|
+
def #{column_name.to_s}
|
145
|
+
if not @#{column_name.to_s}_configuration.kind_of? ExtendModelAt::Extention
|
146
|
+
opts = initialize_options(#{options})
|
147
|
+
options = {
|
148
|
+
:extensible => true # If is false, only the columns defined in :columns can be used
|
149
|
+
}.merge! opts
|
150
|
+
columns = initialize_columns expand_options(options, { :not_call_symbol => [:boolean], :not_expand => [:validate, :default] }) if options.kind_of? Hash
|
151
|
+
@#{column_name.to_s}_configuration ||= ExtendModelAt::Extention.new({:model => self, :column_name => :#{column_name.to_s}, :columns => columns})
|
152
|
+
end
|
153
|
+
@#{column_name.to_s}_configuration
|
154
|
+
end
|
155
|
+
|
156
|
+
protected
|
157
|
+
def extend_at_validations
|
158
|
+
self.#{column_name}.valid?
|
159
|
+
@extend_at_validation ||= {} if not @extend_at_validation.kind_of? Hash
|
160
|
+
@extend_at_validation.each do |column, validation|
|
161
|
+
if validation.kind_of? Symbol
|
162
|
+
self.send validation, eval("@#{column_name.to_s}_configuration.\#\{column.to_s\}")
|
163
|
+
elsif validation.kind_of? Proc
|
164
|
+
validation.call @#{column_name.to_s}_configuration[column.to_sym]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def initialize_options(options={})
|
170
|
+
opts = expand_options options, { :not_call_symbol => [:boolean], :not_expand => [:validate, :default] }
|
171
|
+
end
|
172
|
+
|
173
|
+
# Initialize each column configuration
|
174
|
+
def initialize_columns(options = {})
|
175
|
+
columns = {}
|
176
|
+
if options[:columns].kind_of? Hash
|
177
|
+
options[:columns].each do |column, config|
|
178
|
+
columns[column] = initialize_column column, config
|
179
|
+
end
|
180
|
+
elsif options[:columns].kind_of? Symbol
|
181
|
+
hash = self.send options[:columns]
|
182
|
+
raise "Invalid columns configuration" if not hash.kind_of? Hash
|
183
|
+
columns = initialize_columns :columns => hash
|
184
|
+
elsif options[:columns].kind_of? Proc
|
185
|
+
hash = options[:columns].call
|
186
|
+
raise "Invalid columns configuration" if not hash.kind_of? Hash
|
187
|
+
columns = initialize_columns :columns => hash
|
188
|
+
end
|
189
|
+
columns
|
190
|
+
end
|
191
|
+
|
192
|
+
def initialize_column(column,config={})
|
193
|
+
raise "The column \#\{column\} have an invalid configuration (\#\{config.class\} => \#\{config\})" if not config.kind_of? Hash
|
194
|
+
column = column.to_sym
|
195
|
+
column_config = {}
|
196
|
+
|
197
|
+
# Stablish the type
|
198
|
+
if config[:type].class == Class
|
199
|
+
# If exist :type, is a static column
|
200
|
+
column_config[:type] = config[:type]
|
201
|
+
else
|
202
|
+
# if not, is a dynamic column
|
203
|
+
if config[:type].to_sym == :any
|
204
|
+
column_config[:type] = nil
|
205
|
+
elsif config[:type].to_sym == :boolean
|
206
|
+
column_config[:type] = :boolean
|
207
|
+
else
|
208
|
+
raise "\#\{config[:type]\} is not a valid column type"
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# Stablish the default value
|
213
|
+
# if is a symbol, we execute the function from the model
|
214
|
+
if config[:default].kind_of? Symbol
|
215
|
+
column_config[:default] = self.send(:config[:default])
|
216
|
+
elsif config[:default].kind_of? Proc
|
217
|
+
column_config[:default] = config[:default].call
|
218
|
+
else
|
219
|
+
# If the column have a type, we verify the type
|
220
|
+
if not column_config[:type].nil?
|
221
|
+
if (column_config[:type] == :boolean and (not [true.class, false.class].include? config[:default].class)) or
|
222
|
+
((not [:boolean, nil].include?(column_config[:type])) and column_config[:type] != config[:default].class )
|
223
|
+
raise "The column \#\{column\} has an invalid default value. Expected \#\{column_config[:type]}, not \#\{config[:default].class}"
|
224
|
+
end
|
225
|
+
column_config[:default] = config[:default]
|
226
|
+
else
|
227
|
+
# If is dynamic, only we set the default value
|
228
|
+
column_config[:default] = config[:default]
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
# Set the validation
|
233
|
+
if [Symbol, Proc].include? config[:validate].class
|
234
|
+
column_config[:validate] = config[:validate]
|
235
|
+
create_validation_for column, config[:validate]
|
236
|
+
else
|
237
|
+
raise "The validation of \#\{column\} is invalid"
|
238
|
+
end
|
239
|
+
|
240
|
+
|
241
|
+
column_config
|
242
|
+
end
|
243
|
+
|
244
|
+
def create_validation_for(column, validation)
|
245
|
+
column = column.to_sym
|
246
|
+
@extend_at_validation ||= {}
|
247
|
+
@extend_at_validation[column] = validation
|
248
|
+
end
|
249
|
+
|
250
|
+
def expand_options(options={}, opts={})
|
251
|
+
config_opts = {
|
252
|
+
:not_expand => [],
|
253
|
+
:not_call_symbol => []
|
254
|
+
}.merge! opts
|
255
|
+
if options.kind_of? Hash
|
256
|
+
opts = {}
|
257
|
+
options.each do |column, config|
|
258
|
+
if not config_opts[:not_expand].include? column.to_sym
|
259
|
+
if not config_opts[:not_call_symbol].include? config
|
260
|
+
opts[column.to_sym] = expand_options(get_value_of(config), config_opts)
|
261
|
+
else
|
262
|
+
opts[column.to_sym] = expand_options(config, config_opts)
|
263
|
+
end
|
264
|
+
else
|
265
|
+
opts[column.to_sym] = config
|
266
|
+
end
|
267
|
+
end
|
268
|
+
return opts
|
269
|
+
else
|
270
|
+
return get_value_of options
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
def get_value_of(value)
|
275
|
+
if value.kind_of? Symbol
|
276
|
+
# If the function exist, we execute it
|
277
|
+
if self.respond_to? value
|
278
|
+
return self.send value
|
279
|
+
# if the the function not exist, whe set te symbol as a value
|
280
|
+
else
|
281
|
+
return value
|
282
|
+
end
|
283
|
+
elsif value.kind_of? Proc
|
284
|
+
return value.call
|
285
|
+
else
|
286
|
+
return value
|
287
|
+
end
|
288
|
+
end
|
289
|
+
EOV
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
ActiveRecord::Base.class_eval { include ExtendModelAt }
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: extend_at
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Andrés José Borek
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-12-31 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &10360080 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *10360080
|
25
|
+
description: This gem allows you to extend the columns from your model without migrations,
|
26
|
+
you can, i.e., develop your own content types, like in Drupal
|
27
|
+
email:
|
28
|
+
- andres.b.dev@gmail.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- .gitignore
|
34
|
+
- Gemfile
|
35
|
+
- MIT-license.txt
|
36
|
+
- README.markdown
|
37
|
+
- Rakefile
|
38
|
+
- extend_at.gemspec
|
39
|
+
- lib/extend_at.rb
|
40
|
+
- lib/extend_at/version.rb
|
41
|
+
homepage: ''
|
42
|
+
licenses: []
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
requirements: []
|
60
|
+
rubyforge_project: extend_at
|
61
|
+
rubygems_version: 1.8.11
|
62
|
+
signing_key:
|
63
|
+
specification_version: 3
|
64
|
+
summary: Create dynamic fields in your models (like content types in Drupal)
|
65
|
+
test_files: []
|