shway 3.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/CHANGELOG +11 -0
- data/Manifest +41 -0
- data/README +14 -0
- data/Rakefile +47 -0
- data/init.rb +2 -0
- data/install.rb +0 -0
- data/install_files/javascripts/iepngfix.htc +193 -0
- data/install_files/javascripts/iepngfix_tilebg.js +155 -0
- data/install_files/stylesheets/reset.css +47 -0
- data/install_files/templates/example_presenter.rb +12 -0
- data/install_files/templates/example_stylesheet.css.rb +20 -0
- data/lib/rubygems/commands/shway_init_command.rb +112 -0
- data/lib/rubygems_plugin.rb +3 -0
- data/lib/shway/controllers/shway_controller.rb +22 -0
- data/lib/shway/css/css_helper.rb +221 -0
- data/lib/shway/css/css_parser.rb +155 -0
- data/lib/shway/css/css_styles.rb +368 -0
- data/lib/shway/extensions/routing_extensions.rb +22 -0
- data/lib/shway/helpers/html_helper.rb +54 -0
- data/lib/shway/helpers/shway_controller_helper.rb +51 -0
- data/lib/shway/helpers/shway_helper.rb +187 -0
- data/lib/shway/presenters/shway_model_presenter.rb +10 -0
- data/lib/shway/presenters/shway_presenter.rb +184 -0
- data/lib/shway/test/shway_test_helper.rb +78 -0
- data/lib/shway.rb +129 -0
- data/shway.gemspec +31 -0
- data/templates/css.html.erb +3 -0
- data/templates/css.rhtml +3 -0
- data/test/shway_core/css_config_test.rb +186 -0
- data/test/shway_core/css_helper_test.rb +655 -0
- data/test/shway_core/css_parser_test.rb +219 -0
- data/test/shway_core/html_helper_test.rb +32 -0
- data/test/shway_core/shway_controller_test.rb +44 -0
- data/test/shway_core/shway_core_test_helper.rb +45 -0
- data/test/shway_core/shway_helper_test.rb +280 -0
- data/test/shway_core/shway_presenter_test.rb +173 -0
- data/test/shway_core/shway_routes_test.rb +31 -0
- data/test/shway_core/views/mock_foos/_list_header.html.erb +1 -0
- data/test/shway_core/views/mock_foos/_list_item.html.erb +5 -0
- data/test/shway_core/views/model_list/list_for_action.html.erb +1 -0
- data/test/shway_core/views/model_list/list_item_for_action.html.erb +1 -0
- data/test/shway_core/views/shway_helper_test.html.erb +24 -0
- metadata +123 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class ShwayModelPresenter < ShwayPresenter
|
|
2
|
+
|
|
3
|
+
def initialize(template, model, options={})
|
|
4
|
+
super(template, options)
|
|
5
|
+
model_name = self.class.name.chomp('Presenter').underscore # model_name = 'deployment'
|
|
6
|
+
self.class.send :attr_accessor, model_name.intern # self.class.send :attr_accessor, :deployment
|
|
7
|
+
self.send "#{model_name}=".intern, model # self.send "deployment=".itern, model
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
end
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
class ShwayPresenter
|
|
2
|
+
|
|
3
|
+
attr_reader :template, :options
|
|
4
|
+
|
|
5
|
+
def initialize(template, options={})
|
|
6
|
+
if template.kind_of? ShwayPresenter
|
|
7
|
+
template = template.template
|
|
8
|
+
elsif template.kind_of? ActionController::Base
|
|
9
|
+
template = template.response.template
|
|
10
|
+
end
|
|
11
|
+
raise "must supply a template to #{self.class.name}.new, not #{template.class.name}" unless template.kind_of?(ActionView::Base)
|
|
12
|
+
@template = template
|
|
13
|
+
@options = {}
|
|
14
|
+
setup_options options
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def render(name=:default, *args)
|
|
18
|
+
unless name.kind_of?(Symbol)
|
|
19
|
+
args.unshift name
|
|
20
|
+
name = :default
|
|
21
|
+
end
|
|
22
|
+
_start
|
|
23
|
+
raise "#{self.class.name} has no renderer defined for :#{name}. To create one, use: renderer :#{name} do ... end" unless self.respond_to? "render_#{name}_presenter"
|
|
24
|
+
send "render_#{name}_presenter", 'called_from_render', *args
|
|
25
|
+
_finish
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def r(string=nil, options={}, &block)
|
|
29
|
+
raise "#{self.class.name} rendering has not been started. Be sure you call render(:name)" unless @result
|
|
30
|
+
string, options = nil, string if string.kind_of? Hash
|
|
31
|
+
string = capture(&block) if block
|
|
32
|
+
@result << render_to_string(:partial => options[:partial], :locals => options[:locals]) if options[:partial]
|
|
33
|
+
@result << string if string
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.renderer_with_method(name, options={}, &block)
|
|
37
|
+
options, block = {}, options if options.is_a? Proc
|
|
38
|
+
options[:method] = true
|
|
39
|
+
renderer(name, options, &block)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.renderer(name, options={}, &block)
|
|
43
|
+
options, block = {}, options if options.is_a? Proc
|
|
44
|
+
method_name = "render_#{name}_presenter"
|
|
45
|
+
define_method "_#{method_name}", block
|
|
46
|
+
|
|
47
|
+
arg_string = arg_string_for_renderer_block block
|
|
48
|
+
arg_string_with_comma = arg_string.blank? ? '' : ", #{arg_string}"
|
|
49
|
+
arg_string_without_nils = arg_string.gsub '=nil', ''
|
|
50
|
+
arg_string_with_comma_without_nils = arg_string_without_nils.blank? ? nil : ", #{arg_string_without_nils}"
|
|
51
|
+
|
|
52
|
+
presenter_string = <<-CLASS_EVAL
|
|
53
|
+
def render_#{name}_presenter(render_check#{arg_string_with_comma})
|
|
54
|
+
raise "Don't call \\"#{method_name}\\" directly. Instead use render(:#{name})" unless render_check == 'called_from_render'
|
|
55
|
+
_#{method_name}(#{arg_string_without_nils})
|
|
56
|
+
end
|
|
57
|
+
CLASS_EVAL
|
|
58
|
+
class_eval presenter_string
|
|
59
|
+
#this is optional, since it pollutes the presenter with potentially duplicate method names. But it sure feels nice to use.
|
|
60
|
+
if options[:method]
|
|
61
|
+
presenter_method_string = <<-CLASS_EVAL
|
|
62
|
+
def #{name}(#{arg_string})
|
|
63
|
+
render(:#{name}#{arg_string_with_comma_without_nils})
|
|
64
|
+
end
|
|
65
|
+
CLASS_EVAL
|
|
66
|
+
class_eval presenter_method_string
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def self.arg_string_for_renderer_block(block)
|
|
71
|
+
s = []
|
|
72
|
+
#TODO look into a better way to actually do this. Like maybe looping and adding the [ and ] chars where necessary.
|
|
73
|
+
splat = block.arity < 0
|
|
74
|
+
argument_count = block.arity.abs
|
|
75
|
+
argument_count -= 1 if splat
|
|
76
|
+
argument_count.times do |number|
|
|
77
|
+
s << "arg_#{number+1}=nil"
|
|
78
|
+
end
|
|
79
|
+
s << "*arg_splat" if splat
|
|
80
|
+
s.join ','
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
#TODO make sure I actually need this. put it back if so.
|
|
84
|
+
# def render_to_string(partial)
|
|
85
|
+
# template.controller.send :render_to_string, partial
|
|
86
|
+
# end
|
|
87
|
+
|
|
88
|
+
def shared_instance_variable(var_name_symbol)
|
|
89
|
+
template.controller.instance_variable_get(var_name_symbol) || template.instance_variable_get(var_name_symbol)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
#for any options that match methods on this presenter, set them on this presenter. Merge the remaining options onto any existing options.
|
|
93
|
+
def setup_options(options={})
|
|
94
|
+
return if options.blank?
|
|
95
|
+
options = options.clone
|
|
96
|
+
options.keys.each do |key|
|
|
97
|
+
setter = "#{key}=".intern
|
|
98
|
+
#if there is a setter, call it
|
|
99
|
+
if self.respond_to? setter
|
|
100
|
+
self.send setter, options.delete(key)
|
|
101
|
+
next
|
|
102
|
+
end
|
|
103
|
+
#if there is a no setter, but there is a method, call it with *args
|
|
104
|
+
#TODO write some tests for varying method signatures
|
|
105
|
+
if self.respond_to?(key) && (method(key).arity == 1 || method(key).arity <= -2)
|
|
106
|
+
self.send key, *options.delete(key)
|
|
107
|
+
next
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
self.options.merge! options
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
## accessors/cache for model presenters. potentially move this somewhere else.
|
|
114
|
+
def model_presenters
|
|
115
|
+
@model_presenters ||= {}
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
#NOTE: if the model might ever be nil, you need to supply :model_class, and the model presenter should be able to handle the nil model.
|
|
119
|
+
def presenter_for(model, model_class=nil, options={}, &block)
|
|
120
|
+
model_class, options = options, model_class if model_class.is_a? Hash
|
|
121
|
+
model_class ||= options.delete :model_class
|
|
122
|
+
#presenters for nil objects end up being cached with the model_class as their key
|
|
123
|
+
presenter = model_presenters[model || model_class] ||= presenter_class_for(model || model_class).new(self, model, options)
|
|
124
|
+
yield presenter if block
|
|
125
|
+
presenter
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def presenters_for(models, model_class=nil, options={}, &block)
|
|
129
|
+
presenters = []
|
|
130
|
+
models.each do |model|
|
|
131
|
+
presenters << presenter_for(model, model_class, options, &block)
|
|
132
|
+
end
|
|
133
|
+
presenters
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
#you can pass a model or a model_class here
|
|
137
|
+
def presenter_class_for(model)
|
|
138
|
+
@presenter_classes_for_models ||= {}
|
|
139
|
+
model_class = model.is_a?(Class) ? model : model.class
|
|
140
|
+
if @presenter_classes_for_models[model_class]
|
|
141
|
+
@presenter_classes_for_models[model_class]
|
|
142
|
+
else
|
|
143
|
+
presenter_class_name = "#{model_class.to_s.split('::').last}Presenter"
|
|
144
|
+
presenter_class = Module.const_get(presenter_class_name)
|
|
145
|
+
@presenter_classes_for_models[model_class] = presenter_class
|
|
146
|
+
presenter_class
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
#this prevents redcloth's t method from winning over the I18N's t method
|
|
151
|
+
def t(*args)
|
|
152
|
+
template.t(*args)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
private
|
|
156
|
+
|
|
157
|
+
def _start
|
|
158
|
+
@results ||= []
|
|
159
|
+
@results << []
|
|
160
|
+
@result = @results.last
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def _finish
|
|
164
|
+
html = @result.join("\n")
|
|
165
|
+
@results.pop
|
|
166
|
+
@result = @results.last
|
|
167
|
+
html
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def method_missing(method, *args, &block)
|
|
171
|
+
raise "No template was given to #{self.class.name} and the method '#{method}' was not found. Either define it or supply a template if it is a rails method (eg link_to)" unless template
|
|
172
|
+
#NOTE: ActionView::Base doesn't "respond_to?" :h since it is a method_missing thing with no asociated respond_to? implementation.
|
|
173
|
+
# it also doesn't respond to :method_javascript_function. I'm sure there will be more of these. Is there a list somewhere?
|
|
174
|
+
#TODO: Put these extra methods in a config or at least an array at some point
|
|
175
|
+
if template.respond_to?(method) || method == :h || method == :method_javascript_function
|
|
176
|
+
template.__send__(method, *args, &block)
|
|
177
|
+
elsif template.controller.respond_to?(method)
|
|
178
|
+
template.controller.__send__(method, *args, &block)
|
|
179
|
+
else
|
|
180
|
+
super
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
module ShwayTestHelper
|
|
2
|
+
|
|
3
|
+
def assert_ajax_redirected_to(url)
|
|
4
|
+
url = @request.referer if url == :back
|
|
5
|
+
assert_displayed %{window.location.href = "#{url}"}, :rjs => true
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def assert_attributes_displayed(model, *attributes)
|
|
9
|
+
# TODO look into preventing the attributes from being nil
|
|
10
|
+
attributes.compact.each do |attribute|
|
|
11
|
+
value = model
|
|
12
|
+
#this will walk the attributes as long as they resolve to a value, not a collection or model.
|
|
13
|
+
atts = []
|
|
14
|
+
attribute.to_s.split('.').each do |att|
|
|
15
|
+
atts << att
|
|
16
|
+
raise "the model doesn't appear to have the attribute you specified (#{attribute.inspect}) (specifically: #{atts.join('.')})" unless value.respond_to? att
|
|
17
|
+
value = value.send att
|
|
18
|
+
end
|
|
19
|
+
# puts "**testing for attribute: #{attribute}=#{value}"
|
|
20
|
+
if value.kind_of?(ActiveRecord::Base) || value.kind_of?(Array)
|
|
21
|
+
raise "assert_attributes_displayed can only test attributes, not associations (#{attribute.inspect} == #{value}) "
|
|
22
|
+
end
|
|
23
|
+
assert_displayed value, :message => %{The value (#{value}) for the attribute "#{attribute}" was not found in the response body.} unless value.blank? || attribute.blank?
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
alias_method :assert_attribute_displayed, :assert_attributes_displayed
|
|
27
|
+
|
|
28
|
+
def assert_attributes_displayed_for_collection(collection, *attributes)
|
|
29
|
+
collection.each do |model|
|
|
30
|
+
assert_attributes_displayed(model, *attributes)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def assert_links_displayed(*urls)
|
|
35
|
+
urls.each do |url|
|
|
36
|
+
assert_displayed %{#{url}}, :message => %{The url (#{url}) was not found in the response body.}
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
alias_method :assert_link_displayed, :assert_links_displayed
|
|
40
|
+
|
|
41
|
+
def assert_links_not_displayed(*urls)
|
|
42
|
+
urls.each do |url|
|
|
43
|
+
assert_not_displayed %{#{url}}, :message => %{The url (#{url}) should not be in the response body, but it is.}
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
alias_method :assert_link_not_displayed, :assert_links_not_displayed
|
|
47
|
+
|
|
48
|
+
def assert_displayed(text, options={})
|
|
49
|
+
if text.blank?
|
|
50
|
+
fail %{The text given was blank, and it should not be.}
|
|
51
|
+
end
|
|
52
|
+
message = options.delete :message
|
|
53
|
+
message ||= %{The text "#{text}" was not found in the response body, but it should have been.}
|
|
54
|
+
html = options.delete :html
|
|
55
|
+
html ||= @response.body
|
|
56
|
+
if options[:rjs]
|
|
57
|
+
html = unescape_rjs html
|
|
58
|
+
html.gsub! '&', '&'
|
|
59
|
+
end
|
|
60
|
+
assert html =~ /#{Regexp.escape(text.to_s)}/i, message
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def assert_not_displayed(text, options={})
|
|
64
|
+
if text.blank?
|
|
65
|
+
fail %{The text given was blank, and it should not be.}
|
|
66
|
+
end
|
|
67
|
+
message = options.delete :message
|
|
68
|
+
message ||= %{The text "#{text}" was found in the response body, but it should not have been.}
|
|
69
|
+
html = options.delete :html
|
|
70
|
+
html ||= @response.body
|
|
71
|
+
if options[:rjs]
|
|
72
|
+
html = unescape_rjs html
|
|
73
|
+
html.gsub! '&', '&'
|
|
74
|
+
end
|
|
75
|
+
assert_nil html =~ /#{Regexp.escape(text)}/i, message
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
end
|
data/lib/shway.rb
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#loading order matters... so don't alphabetize these. (trust me, I tried)
|
|
2
|
+
require 'shway/helpers/shway_helper'
|
|
3
|
+
|
|
4
|
+
require 'shway/css/css_styles'
|
|
5
|
+
require 'shway/css/css_parser'
|
|
6
|
+
require 'shway/css/css_helper'
|
|
7
|
+
require 'shway/helpers/shway_controller_helper'
|
|
8
|
+
|
|
9
|
+
require 'shway/extensions/routing_extensions'
|
|
10
|
+
|
|
11
|
+
require 'shway/controllers/shway_controller'
|
|
12
|
+
|
|
13
|
+
require 'shway/presenters/shway_presenter'
|
|
14
|
+
require 'shway/presenters/shway_model_presenter'
|
|
15
|
+
|
|
16
|
+
included_shway_helpers = [
|
|
17
|
+
Shway::Helpers::ShwayHelper,
|
|
18
|
+
Shway::Css::CssHelper,
|
|
19
|
+
Shway::Helpers::ShwayControllerHelper,
|
|
20
|
+
Shway::Helpers::HtmlHelper,
|
|
21
|
+
]
|
|
22
|
+
required_rails_helpers = [
|
|
23
|
+
ActionView::Helpers::TagHelper
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
#auto-include the shway helpers in the views, controllers and form builders
|
|
27
|
+
required_rails_helpers.each do |rails_helper|
|
|
28
|
+
ActionView::Helpers::FormBuilder.send :include, rails_helper
|
|
29
|
+
ActionController::Base.send :include, rails_helper
|
|
30
|
+
end
|
|
31
|
+
included_shway_helpers.each do |shway_helper|
|
|
32
|
+
ActionController::Base.send :include, shway_helper
|
|
33
|
+
ActionView::Base.send :include, shway_helper
|
|
34
|
+
ActionView::Helpers::FormBuilder.send :include, shway_helper
|
|
35
|
+
end
|
|
36
|
+
ActionController::Routing::RouteSet::Mapper.send :include, Shway::Extensions::Routing::MapperExtensions
|
|
37
|
+
|
|
38
|
+
module Shway
|
|
39
|
+
|
|
40
|
+
class << self
|
|
41
|
+
|
|
42
|
+
def load_styles
|
|
43
|
+
Shway::Css::CssStyles.load_styles
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def reload_styles
|
|
47
|
+
Shway::Css::CssStyles.reload_styles
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
#load the app's presenters and create accessors for them on ApplicationHelper
|
|
55
|
+
#TRICK: we can't just use the after_initialize trick below for this since, in development, the helpers get reloaded every request and this gets lost.
|
|
56
|
+
#TODO: make SURE this is the right way to do this. It does work though.
|
|
57
|
+
#NOTE: I've tested this, and to_prepare is called on each request in development, but only once in production. So this looks like the right way to go.
|
|
58
|
+
|
|
59
|
+
#this one adds the presenter helpers. I don't think I actually need this any more.
|
|
60
|
+
Rails.configuration.to_prepare do
|
|
61
|
+
presenters_path = File.join(RAILS_ROOT, 'app', 'presenters')
|
|
62
|
+
if File.exist?(presenters_path)
|
|
63
|
+
Dir.glob(File.join(presenters_path, '*_presenter.rb')).sort.each do |presenter_path|
|
|
64
|
+
#do NOT require the presenter. If you do, Rails class reloading won't work for the presenters.
|
|
65
|
+
# require presenter_path
|
|
66
|
+
presenter_name = File.split(presenter_path).last.chomp('.rb')
|
|
67
|
+
presenter_class_name = presenter_name.camelize
|
|
68
|
+
define_string = %{
|
|
69
|
+
def #{presenter_name}(options={})
|
|
70
|
+
#{presenter_class_name}.new(self, options)
|
|
71
|
+
end
|
|
72
|
+
}
|
|
73
|
+
ApplicationHelper.class_eval define_string
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
#this will reload the styles once per request so you don't have to use css_reload anymore.
|
|
79
|
+
Rails.configuration.to_prepare do
|
|
80
|
+
Shway.reload_styles
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
#this one adds the presenters to the load path
|
|
84
|
+
Rails.configuration.after_initialize do
|
|
85
|
+
presenters_paths = [File.join(RAILS_ROOT, 'app', 'presenters'), File.join(RAILS_ROOT, 'app', 'presenters')]
|
|
86
|
+
presenters_paths.each do |presenters_path|
|
|
87
|
+
if File.exist?(presenters_path)
|
|
88
|
+
Dir.glob(File.join(presenters_path, '*_presenter.rb')).sort.each do |presenter_path|
|
|
89
|
+
presenter_dir = File.dirname presenter_path
|
|
90
|
+
presenter_name = File.split(presenter_path).last.chomp('.rb')
|
|
91
|
+
presenter_class_name = presenter_name.camelize
|
|
92
|
+
ActiveSupport::Dependencies.load_paths += %W( #{presenter_dir} )
|
|
93
|
+
ActiveSupport::Dependencies.explicitly_unloadable_constants << presenter_class_name
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
#MASSIVE HACK MODIFIED FROM fckeditor plugin init.
|
|
100
|
+
|
|
101
|
+
# add the shway css routes
|
|
102
|
+
class ActionController::Routing::RouteSet
|
|
103
|
+
unless (instance_methods.include?('draw_with_shway'))
|
|
104
|
+
class_eval %{
|
|
105
|
+
def draw_with_shway
|
|
106
|
+
draw_without_shway do |map|
|
|
107
|
+
map.shway_css
|
|
108
|
+
yield map
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
alias_method_chain :draw, :shway
|
|
112
|
+
}
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# add the presenter helper and set it up in a before_filter a before
|
|
117
|
+
|
|
118
|
+
class ActionController::Base
|
|
119
|
+
|
|
120
|
+
before_filter :setup_shway_presenter unless filter_chain.include? :setup_shway_presenter
|
|
121
|
+
|
|
122
|
+
#this is being done here now so that local stylesheets can reference skin styles and values.
|
|
123
|
+
# Shway.reload_styles
|
|
124
|
+
|
|
125
|
+
def setup_shway_presenter
|
|
126
|
+
@current_shway_presenter = ApplicationPresenter.new(self)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
end
|
data/shway.gemspec
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |s|
|
|
4
|
+
s.name = %q{shway}
|
|
5
|
+
s.version = "3.0"
|
|
6
|
+
|
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
|
8
|
+
s.authors = ["Ryan Owens"]
|
|
9
|
+
s.date = %q{2009-07-28}
|
|
10
|
+
s.description = %q{Provides powerful UI programming with dynamic css and presenters..}
|
|
11
|
+
s.email = %q{ryan@infoether.com}
|
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "lib/rubygems/commands/shway_init_command.rb", "lib/rubygems_plugin.rb", "lib/shway/controllers/shway_controller.rb", "lib/shway/css/css_helper.rb", "lib/shway/css/css_parser.rb", "lib/shway/css/css_styles.rb", "lib/shway/extensions/routing_extensions.rb", "lib/shway/helpers/html_helper.rb", "lib/shway/helpers/shway_controller_helper.rb", "lib/shway/helpers/shway_helper.rb", "lib/shway/presenters/shway_model_presenter.rb", "lib/shway/presenters/shway_presenter.rb", "lib/shway/test/shway_test_helper.rb", "lib/shway.rb", "README"]
|
|
13
|
+
s.files = ["CHANGELOG", "init.rb", "install.rb", "install_files/javascripts/iepngfix.htc", "install_files/javascripts/iepngfix_tilebg.js", "install_files/stylesheets/reset.css", "install_files/templates/example_presenter.rb", "install_files/templates/example_stylesheet.css.rb", "lib/rubygems/commands/shway_init_command.rb", "lib/rubygems_plugin.rb", "lib/shway/controllers/shway_controller.rb", "lib/shway/css/css_helper.rb", "lib/shway/css/css_parser.rb", "lib/shway/css/css_styles.rb", "lib/shway/extensions/routing_extensions.rb", "lib/shway/helpers/html_helper.rb", "lib/shway/helpers/shway_controller_helper.rb", "lib/shway/helpers/shway_helper.rb", "lib/shway/presenters/shway_model_presenter.rb", "lib/shway/presenters/shway_presenter.rb", "lib/shway/test/shway_test_helper.rb", "lib/shway.rb", "Manifest", "Rakefile", "README", "templates/css.html.erb", "templates/css.rhtml", "test/shway_core/css_config_test.rb", "test/shway_core/css_helper_test.rb", "test/shway_core/css_parser_test.rb", "test/shway_core/html_helper_test.rb", "test/shway_core/shway_controller_test.rb", "test/shway_core/shway_core_test_helper.rb", "test/shway_core/shway_helper_test.rb", "test/shway_core/shway_presenter_test.rb", "test/shway_core/shway_routes_test.rb", "test/shway_core/views/mock_foos/_list_header.html.erb", "test/shway_core/views/mock_foos/_list_item.html.erb", "test/shway_core/views/model_list/list_for_action.html.erb", "test/shway_core/views/model_list/list_item_for_action.html.erb", "test/shway_core/views/shway_helper_test.html.erb", "shway.gemspec"]
|
|
14
|
+
s.homepage = %q{http://rubyforge.org/projects/shway}
|
|
15
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Shway", "--main", "README"]
|
|
16
|
+
s.require_paths = ["lib"]
|
|
17
|
+
s.rubyforge_project = %q{shway}
|
|
18
|
+
s.rubygems_version = %q{1.3.5}
|
|
19
|
+
s.summary = %q{Provides powerful UI programming with dynamic css and presenters..}
|
|
20
|
+
s.test_files = ["test/shway_core/css_config_test.rb", "test/shway_core/css_helper_test.rb", "test/shway_core/css_parser_test.rb", "test/shway_core/html_helper_test.rb", "test/shway_core/shway_controller_test.rb", "test/shway_core/shway_helper_test.rb", "test/shway_core/shway_presenter_test.rb", "test/shway_core/shway_routes_test.rb"]
|
|
21
|
+
|
|
22
|
+
if s.respond_to? :specification_version then
|
|
23
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
|
24
|
+
s.specification_version = 3
|
|
25
|
+
|
|
26
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
|
27
|
+
else
|
|
28
|
+
end
|
|
29
|
+
else
|
|
30
|
+
end
|
|
31
|
+
end
|
data/templates/css.rhtml
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<%# This file is copied from css.html.erb and is necessary for older rails installs that don't support the new extentions %>
|
|
2
|
+
<%# The filepaths are changed to *.rhtml from *.css.erb %>
|
|
3
|
+
<%= render :file => "#{RAILS_ROOT}/public/stylesheets/#{@css_template}.rhtml", :use_full_path => true -%>
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'shway_test_helper')
|
|
2
|
+
|
|
3
|
+
class CssConfigTest < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
include Shway::Css::CssHelper
|
|
6
|
+
include Shway::Helpers::ShwayHelper
|
|
7
|
+
|
|
8
|
+
def test_can_set_and_get_css_config_with_a_symbol_as_one_of_its_values_without_altering_it
|
|
9
|
+
set_valid_simple_css_config
|
|
10
|
+
retreived_config = get_css_config valid_simple_css_config_name
|
|
11
|
+
expected_valid_simple_css_config = valid_simple_css_config_values
|
|
12
|
+
assert_hashes_equal expected_valid_simple_css_config, retreived_config
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def test_can_set_and_get_css_config_with_css_value_substitution
|
|
16
|
+
set_simple_css_value
|
|
17
|
+
set_valid_complex_css_config
|
|
18
|
+
retreived_config = get_css_config valid_complex_css_config_name
|
|
19
|
+
assert_hashes_equal expected_valid_complex_css_config, retreived_config
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_getting_nonexistent_css_config_raises
|
|
23
|
+
assert_raises RuntimeError do
|
|
24
|
+
get_css_config :nonexistent_css_config_name
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_can_get_css_hash
|
|
29
|
+
set_valid_simple_css_style
|
|
30
|
+
retreived_hash = get_css_hash valid_simple_css_config_name
|
|
31
|
+
expected_css_hash = valid_simple_css_config_values
|
|
32
|
+
assert_hashes_equal expected_css_hash, retreived_hash
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
#TODO figure out how to test a custom assertion like this
|
|
38
|
+
#TODO this is really an assert_hashes_equal with nice messages.
|
|
39
|
+
def assert_hashes_equal(hash_one, hash_two)
|
|
40
|
+
hash_one = hash_one.clone
|
|
41
|
+
hash_two = hash_two.clone
|
|
42
|
+
messages = []
|
|
43
|
+
hash_one.each do |key,value|
|
|
44
|
+
value_two = hash_two.delete key
|
|
45
|
+
unless value_two
|
|
46
|
+
messages << ":#{key} was only set in the first hash."
|
|
47
|
+
else
|
|
48
|
+
messages << ":#{key} has different values [#{value} (#{value.class}) | #{value_two} (#{value_two.class})] " unless value == value_two
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
hash_two.each do |key,value|
|
|
52
|
+
messages << ":#{key} was only set in the second hash."
|
|
53
|
+
end
|
|
54
|
+
fail messages.join unless messages.empty?
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
#TODO it is unclear what the difference between these is. Clarify and improve tests.
|
|
58
|
+
def set_valid_simple_css_config
|
|
59
|
+
CssStyles.css_config valid_simple_css_config_name, valid_simple_css_config_values
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def set_valid_simple_css_style
|
|
63
|
+
CssStyles.css_style valid_simple_css_config_name, valid_simple_css_config_values
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def valid_simple_css_config_name
|
|
67
|
+
:valid_simple_config
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def valid_simple_css_config_values
|
|
71
|
+
{
|
|
72
|
+
:integer_value => integer_value,
|
|
73
|
+
:string_value => string_value,
|
|
74
|
+
:symbol_value => symbol_value,
|
|
75
|
+
:class_value => class_value,
|
|
76
|
+
:hash_value => hash_value,
|
|
77
|
+
}
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def set_valid_complex_css_config
|
|
81
|
+
CssStyles.css_config valid_complex_css_config_name, valid_complex_css_config_values
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def valid_complex_css_config_name
|
|
85
|
+
:valid_complex_config
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def valid_complex_css_config_values
|
|
89
|
+
{
|
|
90
|
+
:integer_value => integer_value,
|
|
91
|
+
:string_value => string_value,
|
|
92
|
+
:css_value => simple_css_value_name, ### name!
|
|
93
|
+
:class_value => class_value,
|
|
94
|
+
:hash_value => hash_value,
|
|
95
|
+
}
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def expected_valid_complex_css_config
|
|
99
|
+
{
|
|
100
|
+
:integer_value => integer_value,
|
|
101
|
+
:string_value => string_value,
|
|
102
|
+
:css_value => simple_css_value_value, ### value!
|
|
103
|
+
:class_value => class_value,
|
|
104
|
+
:hash_value => hash_value,
|
|
105
|
+
}
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def integer_value
|
|
109
|
+
1
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def string_value
|
|
113
|
+
'string'
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def symbol_value
|
|
117
|
+
:symbol
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def class_value
|
|
121
|
+
CssStyles
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def hash_value
|
|
125
|
+
{ :test => 'test'}
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def set_simple_css_value
|
|
129
|
+
CssStyles.value simple_css_value_name => simple_css_value_value
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def simple_css_value_name
|
|
133
|
+
:css_value_name
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def simple_css_value_value
|
|
137
|
+
"Test Simple CSS Value"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def shway_config_names
|
|
141
|
+
[
|
|
142
|
+
:shway_edit_button,
|
|
143
|
+
:shway_done_button,
|
|
144
|
+
:shway_save_button,
|
|
145
|
+
:shway_change_button,
|
|
146
|
+
:shway_cancel_button,
|
|
147
|
+
:shway_delete_button,
|
|
148
|
+
:shway_child_image,
|
|
149
|
+
:shway_spacer_image,
|
|
150
|
+
:link_spacer
|
|
151
|
+
]
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def shway_config_value_test_name
|
|
155
|
+
:shway_edit_button
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def shway_config_value_test_expected_values
|
|
159
|
+
{
|
|
160
|
+
:image => 'shway/rest/edit_button.gif',
|
|
161
|
+
:width => 45,
|
|
162
|
+
:height => 19,
|
|
163
|
+
:style => 'vertical-align: text-top',
|
|
164
|
+
}
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
# these were removed from shway core. they should be added to shway_browser
|
|
173
|
+
|
|
174
|
+
# def test_shway_configs_get_loaded
|
|
175
|
+
# assert_nothing_raised do
|
|
176
|
+
# shway_config_names.each do |shway_config_name|
|
|
177
|
+
# get_css_config shway_config_name
|
|
178
|
+
# end
|
|
179
|
+
# end
|
|
180
|
+
# end
|
|
181
|
+
|
|
182
|
+
#this one is brittle, which is why we're only testing one
|
|
183
|
+
# def test_the_values_of_one_shway_config_were_loaded_correctly
|
|
184
|
+
# actual_config_values = get_css_config shway_config_value_test_name
|
|
185
|
+
# assert_equal shway_config_value_test_expected_values, actual_config_values
|
|
186
|
+
# end
|