abstract_interface 0.1.0
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/Rakefile +64 -0
- data/lib/abstract_interface/abstract_interface.rb +64 -0
- data/lib/abstract_interface/controller_helper.rb +24 -0
- data/lib/abstract_interface/haml_builder.rb +56 -0
- data/lib/abstract_interface/support.rb +40 -0
- data/lib/abstract_interface/theme.rb +37 -0
- data/lib/abstract_interface/themed_form_helper.rb +74 -0
- data/lib/abstract_interface/view_builder.rb +100 -0
- data/lib/abstract_interface/view_helper.rb +42 -0
- data/lib/abstract_interface.rb +25 -0
- data/readme.md +3 -0
- data/spec/haml_builder_spec.rb +121 -0
- data/spec/helper.rb +9 -0
- data/spec/spec.opts +4 -0
- metadata +93 -0
data/Rakefile
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'fileutils'
|
3
|
+
current_dir = File.expand_path(File.dirname(__FILE__))
|
4
|
+
Dir.chdir current_dir
|
5
|
+
|
6
|
+
|
7
|
+
#
|
8
|
+
# Specs
|
9
|
+
#
|
10
|
+
require 'spec/rake/spectask'
|
11
|
+
|
12
|
+
task :default => :spec
|
13
|
+
|
14
|
+
Spec::Rake::SpecTask.new('spec') do |t|
|
15
|
+
t.spec_files = FileList["spec/**/*_spec.rb"].select{|f| f !~ /\/_/}
|
16
|
+
t.libs = ["#{current_dir}/lib"]
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
#
|
21
|
+
# Gem
|
22
|
+
#
|
23
|
+
require 'rake/clean'
|
24
|
+
require 'rake/gempackagetask'
|
25
|
+
|
26
|
+
gem_options = {
|
27
|
+
:name => "abstract_interface",
|
28
|
+
:version => "0.1.0",
|
29
|
+
:summary => "Ruby language extensions",
|
30
|
+
:dependencies => %w(facets)
|
31
|
+
}
|
32
|
+
|
33
|
+
spec = Gem::Specification.new do |s|
|
34
|
+
gem_options.delete(:dependencies).each{|d| s.add_dependency d}
|
35
|
+
gem_options.each{|k, v| s.send "#{k}=", v}
|
36
|
+
|
37
|
+
s.author = "Alexey Petrushin"
|
38
|
+
s.homepage = "http://github.com/alexeypetrushin/#{gem_options[:name]}"
|
39
|
+
s.require_path = "lib"
|
40
|
+
s.files = (%w{Rakefile readme.md} + Dir.glob("{lib,spec}/**/*"))
|
41
|
+
|
42
|
+
s.platform = Gem::Platform::RUBY
|
43
|
+
s.has_rdoc = true
|
44
|
+
end
|
45
|
+
|
46
|
+
package_dir = "#{current_dir}/build"
|
47
|
+
Rake::GemPackageTask.new(spec) do |p|
|
48
|
+
p.need_tar = true if RUBY_PLATFORM !~ /mswin/
|
49
|
+
p.need_zip = true
|
50
|
+
p.package_dir = package_dir
|
51
|
+
end
|
52
|
+
|
53
|
+
task :push do
|
54
|
+
# dir = Dir.chdir package_dir do
|
55
|
+
gem_file = Dir.glob("#{package_dir}/#{gem_options[:name]}*.gem").first
|
56
|
+
system "gem push #{gem_file}"
|
57
|
+
# end
|
58
|
+
end
|
59
|
+
|
60
|
+
task :clean do
|
61
|
+
system "rm -r #{package_dir}"
|
62
|
+
end
|
63
|
+
|
64
|
+
task :release => [:gem, :push, :clean]
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module AbstractInterface
|
2
|
+
class << self
|
3
|
+
inject :logger => :logger, :config => :config, :environment => :environment
|
4
|
+
|
5
|
+
attr_accessor :plugin_name
|
6
|
+
attr_accessor :layout_configurations_dir
|
7
|
+
|
8
|
+
def generate_helper_methods *args
|
9
|
+
AbstractInterface::ViewBuilder.generate_helper_methods *args
|
10
|
+
end
|
11
|
+
|
12
|
+
def available_themes; @available_themes ||= [] end
|
13
|
+
|
14
|
+
def theme_metadata theme
|
15
|
+
logger.warn "Complex calculation (AbstractInterface.theme_metadata) called in production!" if config.production?
|
16
|
+
|
17
|
+
metadata = {}
|
18
|
+
|
19
|
+
name = "/#{Crystal::Template::DIRECTORY_NAME}/#{THEMES_DIR}/#{theme}/metadata.rb"
|
20
|
+
if environment.file_exist? name
|
21
|
+
fname = environment.find_file name
|
22
|
+
code = File.read fname
|
23
|
+
metadata = eval code
|
24
|
+
metadata.must_be.a Hash
|
25
|
+
end
|
26
|
+
|
27
|
+
metadata.to_openobject
|
28
|
+
end
|
29
|
+
|
30
|
+
def layouts_defined?
|
31
|
+
!!layout_configurations_dir
|
32
|
+
end
|
33
|
+
|
34
|
+
# Place definitions of your layouts into :layout_configurations_dir folder, you can have multiple such directories
|
35
|
+
def layout_definitions_without_cache theme
|
36
|
+
name = "#{layout_configurations_dir.must_be.present}/#{theme}.yml"
|
37
|
+
raise "File '#{name}' not exist!" unless environment.file_exist? name
|
38
|
+
|
39
|
+
result = {}
|
40
|
+
environment.find_files(name).each do |fname|
|
41
|
+
lds = YAML.load_file(fname)
|
42
|
+
validate_layout_definition!(lds, theme)
|
43
|
+
result.merge! lds
|
44
|
+
end
|
45
|
+
result
|
46
|
+
end
|
47
|
+
cache_method_with_params_in_production :layout_definitions
|
48
|
+
|
49
|
+
protected
|
50
|
+
def validate_layout_definition! lds, theme
|
51
|
+
lds.must_be.a Hash
|
52
|
+
unless lds.include?('default')
|
53
|
+
raise "No 'default' layout definition for '#{theme}' Theme (there always should be definition for 'default' layout)!"
|
54
|
+
end
|
55
|
+
lds.each do |theme_name, ld|
|
56
|
+
ld.must_be.a Hash
|
57
|
+
ld.must.include 'layout_template'
|
58
|
+
ld.must.include 'slots'
|
59
|
+
ld['slots'].must_be.a Hash
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module AbstractInterface
|
2
|
+
module ControllerHelper
|
3
|
+
def current_theme
|
4
|
+
@current_theme ||= AbstractInterface::Theme.new
|
5
|
+
end
|
6
|
+
|
7
|
+
# TODO1
|
8
|
+
# def build_layout layout = nil
|
9
|
+
# # Configuring
|
10
|
+
# current_theme.layout = layout
|
11
|
+
#
|
12
|
+
# # Rendering
|
13
|
+
# current_theme.layout_definition['slots'].each do |slot_name, slots|
|
14
|
+
# slots = Array(slots)
|
15
|
+
# slots.each do |partial|
|
16
|
+
# content_for slot_name do
|
17
|
+
# render :partial => partial
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module AbstractInterface
|
2
|
+
class HamlBuilder < BasicObject
|
3
|
+
def initialize template, hash = OpenObject.new
|
4
|
+
@template = template
|
5
|
+
@hash, @array = hash, []
|
6
|
+
end
|
7
|
+
|
8
|
+
def method_missing m, value = nil, &block
|
9
|
+
@hash[m] = HamlBuilder.get_input @template, value, &block
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def add value = nil, &block
|
14
|
+
@array << HamlBuilder.get_input(@template, value, &block)
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
# def add_item content, opt = {}, &block
|
19
|
+
# opt[:content] = content
|
20
|
+
# opt[:content] ||= @template.capture &block if block
|
21
|
+
# add opt
|
22
|
+
# end
|
23
|
+
|
24
|
+
def get_value
|
25
|
+
!@array.empty? ? @array : @hash
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.get_input template, value, &block
|
29
|
+
value = value.to_openobject if value.is_a? Hash
|
30
|
+
|
31
|
+
block_value = if block
|
32
|
+
if block.arity <= 0
|
33
|
+
template.must_be.defined
|
34
|
+
template.capture &block
|
35
|
+
else
|
36
|
+
b = HamlBuilder.new template
|
37
|
+
block.call b
|
38
|
+
b.get_value
|
39
|
+
end
|
40
|
+
else
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
if value and block_value
|
45
|
+
if block_value.is_a? Hash
|
46
|
+
value = value.merge block_value
|
47
|
+
else
|
48
|
+
raise "Invalid usage!" if value.include? :content
|
49
|
+
value.content = block_value
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
value || block_value
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# content_or_self
|
2
|
+
[Hash, OpenObject].each do |aclass|
|
3
|
+
aclass.class_eval do
|
4
|
+
def hash?; true end
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
NilClass.class_eval do
|
9
|
+
def content; "" end
|
10
|
+
def hash?; false end
|
11
|
+
end
|
12
|
+
|
13
|
+
String.class_eval do
|
14
|
+
def content; self end
|
15
|
+
def hash?; false end
|
16
|
+
end
|
17
|
+
|
18
|
+
# OpenObject
|
19
|
+
OpenObject.class_eval do
|
20
|
+
HTML_ATTRIBUTES = [:id, :class]
|
21
|
+
|
22
|
+
def merge_html_attributes hash
|
23
|
+
# html attributes
|
24
|
+
result = {}
|
25
|
+
HTML_ATTRIBUTES.each{|k| result[k.to_s] = self[k] if include? k}
|
26
|
+
html_attributes.each{|k, v| result[k.to_s] = v} if html_attributes?
|
27
|
+
|
28
|
+
# merging html attributes with hash
|
29
|
+
hash.each do |k, v|
|
30
|
+
k = k.to_s
|
31
|
+
if result.include?(k) and v.is_a?(String)
|
32
|
+
string = result[k].must_be.a [Symbol, String]
|
33
|
+
result[k] = "#{result[k]}#{v}"
|
34
|
+
else
|
35
|
+
result[k] = v
|
36
|
+
end
|
37
|
+
end
|
38
|
+
result
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module AbstractInterface
|
2
|
+
class Theme
|
3
|
+
attr_writer :name, :layout_template, :layout
|
4
|
+
def name; @name || 'default' end
|
5
|
+
def layout; @layout || 'default' end
|
6
|
+
|
7
|
+
def layout_template
|
8
|
+
if @layout_template
|
9
|
+
# Check if this template exists
|
10
|
+
exists = layout_definitions.any?{|layout_name, ld| ld['layout_template'] == @layout_template}
|
11
|
+
exists ? @layout_template : 'default'
|
12
|
+
else
|
13
|
+
layout_definition['layout_template'] || 'default'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def layout_definition
|
18
|
+
layout_definitions[layout] || layout_definitions['default'] || {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def layout_definitions
|
22
|
+
if AbstractInterface.layouts_defined?
|
23
|
+
AbstractInterface.layout_definitions(name)
|
24
|
+
else
|
25
|
+
{}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def available_layouts_names
|
30
|
+
layout_definitions.keys
|
31
|
+
end
|
32
|
+
|
33
|
+
def metadata
|
34
|
+
AbstractInterface.theme_metadata(name)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module AbstractInterface
|
2
|
+
class ThemedFormHelper
|
3
|
+
attr_accessor :template
|
4
|
+
|
5
|
+
def initialize template
|
6
|
+
self.template = template
|
7
|
+
end
|
8
|
+
|
9
|
+
def error_messages *errors
|
10
|
+
errors = errors.first if errors.size == 1 and errors.first.is_a? Array
|
11
|
+
template.render template.themed_partial('forms/errors'), :object => errors
|
12
|
+
end
|
13
|
+
|
14
|
+
def form_field options, &block
|
15
|
+
html_options = options.to_openobject
|
16
|
+
options = OpenObject.new
|
17
|
+
|
18
|
+
# prepare options
|
19
|
+
%w(errors label description required theme).each do |k|
|
20
|
+
v = html_options.delete k
|
21
|
+
options[k] = v unless v.nil?
|
22
|
+
end
|
23
|
+
options.errors = options.errors.to_a
|
24
|
+
|
25
|
+
# CSS style
|
26
|
+
html_options.class ||= ""
|
27
|
+
html_options << " themed_input"
|
28
|
+
|
29
|
+
options.content = template.capture{block.call(html_options)}
|
30
|
+
|
31
|
+
html = template.render(template.themed_partial('forms/field'), :object => options)
|
32
|
+
template.concat html
|
33
|
+
end
|
34
|
+
|
35
|
+
def line *items
|
36
|
+
template.render template.themed_partial('forms/line'), :object => {:items => items, :delimiter => false}.to_openobject
|
37
|
+
end
|
38
|
+
|
39
|
+
def line_with_delimiters *items
|
40
|
+
template.render template.themed_partial('forms/line'), :object => {:items => items, :delimiter => true}.to_openobject
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
#
|
45
|
+
# Form fields
|
46
|
+
#
|
47
|
+
%w(
|
48
|
+
check_box_tag
|
49
|
+
field_set_tag
|
50
|
+
file_field_tag
|
51
|
+
password_field_tag
|
52
|
+
radio_button_tag
|
53
|
+
select_tag
|
54
|
+
text_field_tag
|
55
|
+
text_area_tag
|
56
|
+
).each do |m|
|
57
|
+
define_method m do |*args|
|
58
|
+
options = args.extract_options!
|
59
|
+
template.capture do
|
60
|
+
form_field options do |html_options|
|
61
|
+
args << html_options
|
62
|
+
template.concat(template.send(m, *args))
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
%w(
|
69
|
+
hidden_field_tag
|
70
|
+
submit_tag
|
71
|
+
).each{|m| delegate m, :to => :template}
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module AbstractInterface
|
2
|
+
class ViewBuilder
|
3
|
+
|
4
|
+
def self.generate_helper_methods methods
|
5
|
+
methods.each do |folder, templates|
|
6
|
+
templates.each do |template|
|
7
|
+
code = %{\
|
8
|
+
def #{template} *args, &block
|
9
|
+
render_haml_builder "#{folder}", "#{template}", *args, &block
|
10
|
+
end}
|
11
|
+
|
12
|
+
eval code, binding, __FILE__, __LINE__
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
attr_reader :template
|
19
|
+
def initialize template
|
20
|
+
@template = template
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
#
|
25
|
+
# Template methods
|
26
|
+
#
|
27
|
+
%w(
|
28
|
+
capture
|
29
|
+
concat
|
30
|
+
content_for
|
31
|
+
tag
|
32
|
+
render
|
33
|
+
themed_resource
|
34
|
+
themed_partial
|
35
|
+
controller
|
36
|
+
).each do |m|
|
37
|
+
delegate m, :to => :template
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
#
|
42
|
+
# Builders
|
43
|
+
#
|
44
|
+
def options *args, &block
|
45
|
+
opt = args.extract_options!
|
46
|
+
args.size.must_be.in 0..1
|
47
|
+
opt[:content] = args.first if args.size == 1
|
48
|
+
|
49
|
+
AbstractInterface::HamlBuilder.get_input self.template, opt, &block
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
#
|
54
|
+
# Forms
|
55
|
+
#
|
56
|
+
def form_tag *args, &block
|
57
|
+
f = ThemedFormHelper.new(template)
|
58
|
+
|
59
|
+
content = block ? capture{block.call(f)} : ""
|
60
|
+
html = render(
|
61
|
+
themed_partial('forms/form'),
|
62
|
+
:object => {:form_attributes => options, :content => content}.to_openobject
|
63
|
+
)
|
64
|
+
|
65
|
+
if block
|
66
|
+
template.concat html
|
67
|
+
else
|
68
|
+
html
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def form_for *args, &block
|
73
|
+
model_helper, options = template.build_form_model_helper_and_form_options *args
|
74
|
+
|
75
|
+
form_tag options do |themed_form_helper|
|
76
|
+
model_helper.form_helper = themed_form_helper
|
77
|
+
|
78
|
+
block.call model_helper if block
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def render_haml_builder folder, template, *args, &block
|
85
|
+
opt = options *args, &block
|
86
|
+
|
87
|
+
partial = "#{folder}/#{template}"
|
88
|
+
|
89
|
+
html = render themed_partial(partial), :object => opt
|
90
|
+
|
91
|
+
block ? self.concat(html) : html
|
92
|
+
end
|
93
|
+
|
94
|
+
def prepare_form! options, *args
|
95
|
+
buff = template.form_tag *args
|
96
|
+
options[:begin] = buff
|
97
|
+
options[:end] = '</form>'
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module AbstractInterface
|
2
|
+
module ViewHelper
|
3
|
+
def b
|
4
|
+
@b ||= AbstractInterface::ViewBuilder.new self
|
5
|
+
end
|
6
|
+
alias_method :builder, :b
|
7
|
+
|
8
|
+
def themed_resource resource
|
9
|
+
"/#{AbstractInterface.plugin_name.must_not_be.blank}/#{THEMES_DIR}/#{current_theme.name}/#{resource}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def themed_partial partial
|
13
|
+
themed_partial = "/#{THEMES_DIR}/#{current_theme.name}/#{partial}"
|
14
|
+
if Crystal::Template.exist? themed_partial
|
15
|
+
themed_partial
|
16
|
+
else
|
17
|
+
"/#{THEMES_DIR}/default/#{partial}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def current_theme
|
22
|
+
controller.current_theme
|
23
|
+
end
|
24
|
+
|
25
|
+
# TODO1
|
26
|
+
# def build_layout layout = nil
|
27
|
+
# # Configuring
|
28
|
+
# current_theme.layout = layout
|
29
|
+
#
|
30
|
+
# # Rendering
|
31
|
+
# current_theme.layout_definition['slots'].each do |slot_name, slots|
|
32
|
+
# slots = Array(slots)
|
33
|
+
# slots.each do |partial|
|
34
|
+
# content_for slot_name do
|
35
|
+
# render :partial => partial
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'abstract_interface/support'
|
2
|
+
|
3
|
+
module AbstractInterface
|
4
|
+
THEMES_DIR = 'themes'
|
5
|
+
|
6
|
+
autoload :Theme, 'abstract_interface/theme'
|
7
|
+
autoload :HamlBuilder, 'abstract_interface/haml_builder'
|
8
|
+
autoload :ThemedFormHelper, 'abstract_interface/themed_form_helper'
|
9
|
+
autoload :ViewBuilder, 'abstract_interface/view_builder'
|
10
|
+
autoload :ViewHelper, 'abstract_interface/view_helper'
|
11
|
+
autoload :ControllerHelper, 'abstract_interface/controller_helper'
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'abstract_interface/abstract_interface'
|
15
|
+
|
16
|
+
Crystal::ControllerContext.inherit AbstractInterface::ViewHelper
|
17
|
+
Crystal::AbstractController.inherit AbstractInterface::ControllerHelper
|
18
|
+
|
19
|
+
# TODO2
|
20
|
+
# ActionView::Base.field_error_proc = lambda do |html_tag, instance|
|
21
|
+
# html_tag
|
22
|
+
# end
|
23
|
+
|
24
|
+
# TODO1
|
25
|
+
# Rails.development{RailsExt.create_public_symlinks!} # rails_ext.css, rails_ext.js in development mode
|
data/readme.md
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
dir = File.expand_path(File.dirname(__FILE__))
|
2
|
+
require "#{dir}/helper"
|
3
|
+
|
4
|
+
#
|
5
|
+
# Don't use should ==, it doesn't works with OpenObject
|
6
|
+
#
|
7
|
+
describe "HamlBuilder use cases" do
|
8
|
+
class TemplateStub
|
9
|
+
def self.capture &block
|
10
|
+
block.call
|
11
|
+
self.output
|
12
|
+
end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
attr_accessor :output
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def build *args, &block
|
20
|
+
opt = args.extract_options!
|
21
|
+
args.size.must_be.in 0..1
|
22
|
+
opt[:content] = args.first if args.size == 1
|
23
|
+
|
24
|
+
AbstractInterface::HamlBuilder.get_input(TemplateStub, opt, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should accept OpenObject as input" do
|
28
|
+
build({:a => :b}.to_openobject).should == {:a => :b}
|
29
|
+
end
|
30
|
+
|
31
|
+
it "hash" do
|
32
|
+
(build do |o|
|
33
|
+
o.a :b
|
34
|
+
end).should == {:a => :b}
|
35
|
+
|
36
|
+
build(:a => :b).should == {:a => :b}
|
37
|
+
end
|
38
|
+
|
39
|
+
it "array" do
|
40
|
+
(build do |a|
|
41
|
+
a.add 1
|
42
|
+
a.add 2
|
43
|
+
end).should == {:content => [1, 2]}
|
44
|
+
|
45
|
+
(build do |o|
|
46
|
+
o.a :b
|
47
|
+
o.ar do |a|
|
48
|
+
a.add 1
|
49
|
+
a.add 2
|
50
|
+
end
|
51
|
+
end).should == {:a => :b, :ar => [1, 2]}
|
52
|
+
end
|
53
|
+
|
54
|
+
it "capture" do
|
55
|
+
build("value").should == {:content => "value"}
|
56
|
+
|
57
|
+
(build do
|
58
|
+
TemplateStub.output = "value"
|
59
|
+
end).should == {:content => "value"}
|
60
|
+
|
61
|
+
(build do |o|
|
62
|
+
o.content do
|
63
|
+
TemplateStub.output = "value"
|
64
|
+
end
|
65
|
+
end).should == {:content => "value"}
|
66
|
+
|
67
|
+
(build do |o|
|
68
|
+
o.value do
|
69
|
+
TemplateStub.output = "value"
|
70
|
+
end
|
71
|
+
end).should == {:value => "value"}
|
72
|
+
end
|
73
|
+
|
74
|
+
it "invalid usage" do
|
75
|
+
lambda{
|
76
|
+
build "value" do
|
77
|
+
TemplateStub.output = "value"
|
78
|
+
end
|
79
|
+
}.should raise_error(/Invalid usage!/)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "merge" do
|
83
|
+
(build :a => :b do
|
84
|
+
TemplateStub.output = "value"
|
85
|
+
end).should == {:a => :b, :content => "value"}
|
86
|
+
|
87
|
+
(build :a => :b do |o|
|
88
|
+
o.c :d
|
89
|
+
end).should == {:a => :b, :c => :d}
|
90
|
+
end
|
91
|
+
|
92
|
+
it "nested" do
|
93
|
+
(build :a => :b do |o|
|
94
|
+
o.a do |o|
|
95
|
+
o.b :c
|
96
|
+
end
|
97
|
+
end).should == {
|
98
|
+
:a => {:b => :c}
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
it "complex" do
|
103
|
+
(build :a => :b do |o|
|
104
|
+
o.hs do |h|
|
105
|
+
h.c :d
|
106
|
+
end
|
107
|
+
o.ar do |a|
|
108
|
+
a.add 1
|
109
|
+
a.add 2
|
110
|
+
end
|
111
|
+
o.html do
|
112
|
+
TemplateStub.output = "value"
|
113
|
+
end
|
114
|
+
end).should == {
|
115
|
+
:a => :b,
|
116
|
+
:hs => {:c => :d},
|
117
|
+
:ar => [1, 2],
|
118
|
+
:html => 'value'
|
119
|
+
}
|
120
|
+
end
|
121
|
+
end
|
data/spec/helper.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
dir = File.expand_path(File.dirname(__FILE__))
|
2
|
+
lib_dir = File.expand_path("#{dir}/../../../lib")
|
3
|
+
$LOAD_PATH << lib_dir unless $LOAD_PATH.include? lib_dir
|
4
|
+
|
5
|
+
require 'crystal/support'
|
6
|
+
require 'abstract_interface/support'
|
7
|
+
require "abstract_interface/haml_builder"
|
8
|
+
|
9
|
+
require 'spec_ext'
|
data/spec/spec.opts
ADDED
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: abstract_interface
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Alexey Petrushin
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-10-11 00:00:00 +04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: facets
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
description:
|
36
|
+
email:
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files: []
|
42
|
+
|
43
|
+
files:
|
44
|
+
- Rakefile
|
45
|
+
- readme.md
|
46
|
+
- lib/abstract_interface/abstract_interface.rb
|
47
|
+
- lib/abstract_interface/controller_helper.rb
|
48
|
+
- lib/abstract_interface/haml_builder.rb
|
49
|
+
- lib/abstract_interface/support.rb
|
50
|
+
- lib/abstract_interface/theme.rb
|
51
|
+
- lib/abstract_interface/themed_form_helper.rb
|
52
|
+
- lib/abstract_interface/view_builder.rb
|
53
|
+
- lib/abstract_interface/view_helper.rb
|
54
|
+
- lib/abstract_interface.rb
|
55
|
+
- spec/haml_builder_spec.rb
|
56
|
+
- spec/helper.rb
|
57
|
+
- spec/spec.opts
|
58
|
+
has_rdoc: true
|
59
|
+
homepage: http://github.com/alexeypetrushin/abstract_interface
|
60
|
+
licenses: []
|
61
|
+
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
hash: 3
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
version: "0"
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
hash: 3
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
version: "0"
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 1.3.7
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: Ruby language extensions
|
92
|
+
test_files: []
|
93
|
+
|