Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
simonoff committed Nov 28, 2011
0 parents commit baebaa1
Show file tree
Hide file tree
Showing 25 changed files with 370 additions and 0 deletions.
17 changes: 17 additions & 0 deletions .gitignore
@@ -0,0 +1,17 @@
*.gem
*.rbc
.bundle
.config
.yardoc
Gemfile.lock
InstalledFiles
_yardoc
coverage
doc/
lib/bundler/man
pkg
rdoc
spec/reports
test/tmp
test/version_tmp
tmp
4 changes: 4 additions & 0 deletions Gemfile
@@ -0,0 +1,4 @@
source 'http://rubygems.org'

# Specify your gem's dependencies in acts_as_virtual_field.gemspec
gemspec
20 changes: 20 additions & 0 deletions MIT-LICENSE
@@ -0,0 +1,20 @@
Copyright (c) 2011 Alexander Simonov

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2 changes: 2 additions & 0 deletions Rakefile
@@ -0,0 +1,2 @@
#!/usr/bin/env rake
require "bundler/gem_tasks"
22 changes: 22 additions & 0 deletions acts_as_virtual_field.gemspec
@@ -0,0 +1,22 @@
# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
require 'acts_as_virtual_field/version'

Gem::Specification.new do |gem|
gem.authors = ["Alexander Simonov"]
gem.email = ["alex@simonov.me"]
gem.platform = Gem::Platform::RUBY
gem.description = %q{Rails3 plugin to define virtual field types on any column of model}
gem.summary = %q{Rails3 plugin to define virtual field types on any column of model}
gem.homepage = ""
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
gem.files = `git ls-files`.split("\n")
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
gem.name = %q{acts_as_virtual_field}
gem.require_paths = ["lib"]
gem.licenses = ["MIT"]
gem.version = ::ActsAsVirtualField::VERSION
gem.add_dependency 'rails', '~> 3.1'
gem.add_dependency 'formtastic', '~> 2.0'
gem.add_development_dependency 'rspec', "~> 2.6"
end
5 changes: 5 additions & 0 deletions lib/acts_as_virtual_field.rb
@@ -0,0 +1,5 @@
require "acts_as_virtual_field/version"

module ActsAsVirtualField
require 'acts_as_virtual_field/virtual_field'
end
34 changes: 34 additions & 0 deletions lib/acts_as_virtual_field/active_record/acts/virtual_field.rb
@@ -0,0 +1,34 @@
module ActiveRecord
module Acts #:nodoc:
module VirtualField #:nodoc:
def acts_as_virtual_field(*args)
options = args.extract_options!
cattr_accessor :virtual_field_column, :virtual_field_association
self.virtual_field_association = options[:class] || 'VirtualField'
self.virtual_field_column = options[:column] || :value

belongs_to :virtual_field,
:class_name => self.virtual_field_association.to_s,
:foreign_key => 'virtual_field_id'
:dependent => :delete_all

include InstanceMethods
end

module InstanceMethods
def formtastic_options
field_type = self.virtual_field.field_type
klass = "::ActsAsVirtualField::VirtualField::#{field_type}".constantize
opts = {
:label => self.virtual_field.label,
:requried => self.virtual_field.required?,
:as => klass.view_as
}
opts[:collection] = self.virtual_field.field_meta.split(/\r?\n/) if klass.collection?
opts[:input_html] = klass.html_options if klass.has_html_options?
end
end

end
end
end
19 changes: 19 additions & 0 deletions lib/acts_as_virtual_field/fields/base.rb
@@ -0,0 +1,19 @@
module ActsAsVirtualField
module VirtualField
class Base
class << self
def view_as
self.class.VIEW_AS || :string
end

def has_html_options?
self.class.HTML_OPTIONS || false
end

def html_options
self.class.HTML_OPTIONS
end
end
end
end
end
10 changes: 10 additions & 0 deletions lib/acts_as_virtual_field/fields/date.rb
@@ -0,0 +1,10 @@
module ActsAsVirtualField
class Date < Base

VIEW_AS = :string
HTML_OPTIONS = {
:class => 'date-picker'
}

end
end
21 changes: 21 additions & 0 deletions lib/acts_as_virtual_field/fields/datetime.rb
@@ -0,0 +1,21 @@
module ActsAsVirtualField
class Datetime < Base
REGEXP = /^(?<hours>\d{1,2}):(?<minutes>\d{1,2}) (?<day>\d{1,2}).(?<month>\d{1,2}).(?<year>\d{4})$/
FORMAT = '%H:%M %d.%m.%Y'

def set_value
@value = ::DateTime.strptime(@original_value, FORMAT)
end

def to_s
@value.strftime FORMAT
end

def self.to_formtastic(*args)
options = args.extract_options!
options.merge!(:as => :datetime)
options
end

end
end
22 changes: 22 additions & 0 deletions lib/acts_as_virtual_field/fields/decimal.rb
@@ -0,0 +1,22 @@
module ActsAsVirtualField
class Decimal < Base

DIGITS = 2
REGEXP = /^\d+(\,\d{1,2})?$/

def set_value
@value = ::BigDecimal.new(@original_value.gsub(/,/,'.'),DIGITS)
end

def to_s
@value.to_s.gsub(/\./,',')
end

def self.to_formtastic(*args)
options = args.extract_options!
options.merge!(:as => :numeric)
options
end

end
end
28 changes: 28 additions & 0 deletions lib/acts_as_virtual_field/fields/gender.rb
@@ -0,0 +1,28 @@
module ActsAsVirtualField
class Gender < Base
GENDERS = {
"male" => I18n.t("genders.male", :default => "Male"),
"female" => I18n.t("genders.female", :default => "Female"),
"unknown" => I18n.t("genders.unknown", :default => "Unknown")
}

def check_value
raise unless GENDERS.keys.include?(@original_value)
end

def self.for_select
@genders ||= GENDERS.to_a.map(&:reverse)
end

def to_s
GENDERS[@value]
end

def self.to_formtastic(*args)
options = args.extract_options!
options.merge!(:as => :select, :collection => for_select)
options
end

end
end
5 changes: 5 additions & 0 deletions lib/acts_as_virtual_field/fields/image.rb
@@ -0,0 +1,5 @@
module ActsAsVirtualField
class Image < Base

end
end
4 changes: 4 additions & 0 deletions lib/acts_as_virtual_field/fields/images.rb
@@ -0,0 +1,4 @@
module ActsAsVirtualField
class Images < Base
end
end
16 changes: 16 additions & 0 deletions lib/acts_as_virtual_field/fields/integer.rb
@@ -0,0 +1,16 @@
module Fields
class Integer < Base
REGEXP = /^[+-]?\d+$/

def set_value
@value = @match[0].to_i
end

def self.to_formtastic(*args)
options = args.extract_options!
options.merge!(:as => :numeric)
options
end

end
end
19 changes: 19 additions & 0 deletions lib/acts_as_virtual_field/fields/list.rb
@@ -0,0 +1,19 @@
module ActsAsVirtualField
class List < Base

def self.collection?
true
end

def initialize(meta, value)
raise unless meta.is_a?(::String)
raise unless value.is_a?(::String)
@original_value = Yajl::Parser.parse(value)
@meta = Yajl::Parser.parse(meta)
raise unless @meta.is_a?(::Hash)
raise unless value_valid?
set_value
end

end
end
20 changes: 20 additions & 0 deletions lib/acts_as_virtual_field/fields/mail.rb
@@ -0,0 +1,20 @@
module ActsAsVirtualField
require 'mail'
class Mail < Base

def check_value
m = ::Mail::Address.new(@original_value)
r = m.domain && m.address == @original_value
t = m.__send__(:tree)
r &&= (t.domain.dot_atom_text.elements.size > 1)
raise unless r
end

def self.to_formtastic(*args)
options = args.extract_options!
options.merge!(:as => :email)
options
end

end
end
27 changes: 27 additions & 0 deletions lib/acts_as_virtual_field/fields/multiple_list.rb
@@ -0,0 +1,27 @@
module ActsAsVirtualField
class MultipleList < List

def value_valid?
return false unless @original_value.is_a?(::Array)
return false unless @original_value.present?
intersection = @meta.keys & @original_value
return false unless intersection.present?
return false unless intersection.eql? @original_value
true
end

def set_value
@value = @original_value.inject({}) do |memo, key|
memo[key] = @meta[key]
memo
end
end

def self.to_formtastic(*args)
options = args.extract_options!
options.merge!(:as => :check_boxes)
options
end

end
end
12 changes: 12 additions & 0 deletions lib/acts_as_virtual_field/fields/phone.rb
@@ -0,0 +1,12 @@
module ActsAsVirtualField
class Phone < Base
REGEXP = /^[+\-\/0-9]+$/

def self.to_formtastic(*args)
options = args.extract_options!
options.merge!(:as => :phone)
options
end

end
end
5 changes: 5 additions & 0 deletions lib/acts_as_virtual_field/fields/postal_code.rb
@@ -0,0 +1,5 @@
module ActsAsVirtualField
class PostalCode < Base
REGEXP = /^\d{5}$/
end
end
21 changes: 21 additions & 0 deletions lib/acts_as_virtual_field/fields/single_list.rb
@@ -0,0 +1,21 @@
module ActsAsVirtualField
class SingleList < List

def value_valid?
return false unless @original_value.is_a?(::String)
return false unless @meta.has_key? @original_value
true
end

def set_value
@value = {@original_value => @meta[@original_value]}
end

def self.to_formtastic(*args)
options = args.extract_options!
options.merge!(:as => :select)
options
end

end
end
3 changes: 3 additions & 0 deletions lib/acts_as_virtual_field/fields/string.rb
@@ -0,0 +1,3 @@
module ActsAsVirtualField
class String < Base; end
end
11 changes: 11 additions & 0 deletions lib/acts_as_virtual_field/fields/text.rb
@@ -0,0 +1,11 @@
module ActsAsVirtualField
class Text < String

def self.to_formtastic(*args)
options = args.extract_options!
options.merge(:as => :text)
options
end

end
end
3 changes: 3 additions & 0 deletions lib/acts_as_virtual_field/version.rb
@@ -0,0 +1,3 @@
module ActsAsVirtualField
VERSION = "0.0.1"
end

0 comments on commit baebaa1

Please sign in to comment.