ruhl 1.2.0 → 1.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/.gitignore CHANGED
@@ -2,3 +2,4 @@
2
2
  *.swp
3
3
  pkg/**
4
4
  coverage/**
5
+ test.log
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.2.0
1
+ 1.3.0
data/lib/ruhl.rb CHANGED
@@ -10,6 +10,7 @@ module Ruhl
10
10
  attr_accessor :logger, :encoding
11
11
  attr_accessor :inspect_local_object, :inspect_block_object
12
12
  attr_accessor :inspect_scope
13
+ attr_accessor :use_instance_variables, :log_instance_variable_warning
13
14
  end
14
15
 
15
16
  self.logger = Logger.new(STDOUT)
@@ -19,4 +20,7 @@ module Ruhl
19
20
  self.inspect_local_object = false
20
21
  self.inspect_block_object = false
21
22
  self.inspect_scope = false
23
+
24
+ self.use_instance_variables = true
25
+ self.log_instance_variable_warning = true
22
26
  end
data/lib/ruhl/engine.rb CHANGED
@@ -44,7 +44,7 @@ module Ruhl
44
44
  def render_with_layout
45
45
  raise LayoutNotFoundError.new(@layout) unless File.exists?(@layout)
46
46
 
47
- render_nodes Nokogiri::HTML( @layout_source || File.read(@layout) )
47
+ render_nodes Nokogiri::HTML( @layout_source || file_contents(@layout) )
48
48
  end
49
49
 
50
50
  def render_partial
@@ -52,7 +52,7 @@ module Ruhl
52
52
  raise PartialNotFoundError.new(call_result)
53
53
  end
54
54
 
55
- render_nodes Nokogiri::HTML.fragment( File.read(call_result) )
55
+ render_nodes Nokogiri::HTML.fragment( file_contents(call_result) )
56
56
  end
57
57
 
58
58
  def render_collection
@@ -64,7 +64,7 @@ module Ruhl
64
64
  new_content = call_result.collect do |item|
65
65
 
66
66
  if actions.empty? && current_tag.xpath('.//*[@data-ruhl]').empty?
67
- if item.is_a?(Hash)
67
+ if item.kind_of?(Hash)
68
68
  t = current_tag.dup
69
69
  apply_hash(t, item)
70
70
  t.to_html
@@ -131,7 +131,7 @@ module Ruhl
131
131
  if attribute =~ /^_/
132
132
  send("ruhl#{attribute}")
133
133
  else
134
- current_tag[attribute] = call_result.to_s
134
+ write_tag_attribute(current_tag, attribute, call_result)
135
135
  end
136
136
  end
137
137
  rescue NoMethodError => nme
@@ -195,7 +195,7 @@ module Ruhl
195
195
  end
196
196
 
197
197
  def process_results
198
- if call_result.is_a?(Hash)
198
+ if call_result.kind_of?(Hash)
199
199
  apply_hash(current_tag, call_result)
200
200
  else
201
201
  current_tag.inner_html = call_result.to_s
@@ -207,30 +207,52 @@ module Ruhl
207
207
  if key == :inner_html
208
208
  tag.inner_html = value.to_s
209
209
  else
210
- tag[key.to_s] = value.to_s
210
+ write_tag_attribute(tag, key.to_s, value)
211
211
  end
212
212
  end
213
213
  end
214
214
 
215
+ def write_tag_attribute(tag, attribute, value)
216
+ if tag[attribute] && attribute.downcase == 'class'
217
+ tag[attribute] = "#{tag[attribute]} #{value}"
218
+ else
219
+ tag[attribute] = value.to_s
220
+ end
221
+ end
222
+
215
223
  def execute_ruby(code)
216
224
  if code == '_render_'
217
225
  _render_
218
226
  else
219
227
  args = code.strip.split('|').collect{|p| p.strip}
220
228
 
221
- if block_object.respond_to?(args.first)
222
- block_object.send(*args)
223
- elsif local_object.respond_to?(args.first)
224
- local_object.send(*args)
225
- else
226
- scope.send(*args)
229
+ [block_object, local_object, scope].compact.each do |obj|
230
+ return call_to(obj, args) rescue NoMethodError
231
+ end
232
+
233
+ if Ruhl.use_instance_variables
234
+ # No luck so far, lets see if code is actually an instance
235
+ # variable.
236
+ ivar = :"@#{code}"
237
+ if scope.instance_variable_defined?(ivar)
238
+ if Ruhl.log_instance_variable_warning
239
+ Ruhl.logger.warn("Ruhl did NOT find a method named: #{code} but did find and is using: @#{code}")
240
+ end
241
+ return scope.instance_variable_get(ivar)
242
+ end
227
243
  end
244
+
245
+ log_context(code)
246
+ raise NoMethodError.new("Neither method nor instance variable found: #{args.first}")
247
+ end
248
+ end
249
+
250
+ def call_to(object, args)
251
+ if object.kind_of?(Hash) && ( object.has_key?(args.first) || object.has_key?(args.first.to_sym))
252
+ object[args.first] || object[args.first.to_sym]
253
+ else
254
+ object.send(*args)
228
255
  end
229
- rescue NoMethodError => nme
230
- Ruhl.logger.error(nme.message)
231
- Ruhl.logger.error(nme.backtrace.join("\n"))
232
- log_context(code)
233
- raise nme
234
256
  end
235
257
 
236
258
  def set_scope(current_scope)
@@ -250,8 +272,8 @@ module Ruhl
250
272
 
251
273
  def call_result_populated_array?
252
274
  call_result.kind_of?(Array) && !call_result.empty?
253
-
254
275
  end
276
+
255
277
  def call_result_empty_array?
256
278
  call_result.kind_of?(Array) && call_result.empty?
257
279
  end
@@ -279,5 +301,19 @@ CONTEXT
279
301
  send(object_str).class.to_s
280
302
  end
281
303
  end
304
+
305
+ if RUBY_VERSION == '1.8.6'
306
+ def file_contents(path_to_file)
307
+ File.open(path_to_file,'r') do |f|
308
+ f.read
309
+ end
310
+ end
311
+ else
312
+ def file_contents(path_to_file)
313
+ File.open(path_to_file, "r:#{Ruhl.encoding}") do |f|
314
+ f.read
315
+ end
316
+ end
317
+ end
282
318
  end # Engine
283
319
  end # Ruhl
data/ruhl.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ruhl}
8
- s.version = "1.2.0"
8
+ s.version = "1.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Andrew Stone"]
12
- s.date = %q{2010-02-01}
12
+ s.date = %q{2010-02-10}
13
13
  s.description = %q{Make your HTML dynamic with the addition of a data-ruhl attribute.}
14
14
  s.email = %q{andy@stonean.com}
15
15
  s.extra_rdoc_files = [
@@ -34,6 +34,7 @@ Gem::Specification.new do |s|
34
34
  "spec/html/basic.html",
35
35
  "spec/html/collection_of_hashes.html",
36
36
  "spec/html/collection_of_strings.html",
37
+ "spec/html/combination.html",
37
38
  "spec/html/form.html",
38
39
  "spec/html/fragment.html",
39
40
  "spec/html/hash.html",
@@ -44,7 +45,6 @@ Gem::Specification.new do |s|
44
45
  "spec/html/loop.html",
45
46
  "spec/html/main_with_form.html",
46
47
  "spec/html/main_with_sidebar.html",
47
- "spec/html/medium.html",
48
48
  "spec/html/parameters.html",
49
49
  "spec/html/seo.html",
50
50
  "spec/html/sidebar.html",
@@ -0,0 +1,32 @@
1
+ <html>
2
+ <head>
3
+ <title>This is a title template</title>
4
+ </head>
5
+ <body>
6
+ <h1>This is the header template</h1>
7
+ <p id='time'>It is now <span data-ruhl='_swap:time'/> time</p>
8
+ <table>
9
+ <thead>
10
+ <tr>
11
+ <td>First Name</td>
12
+ <td>Last Name</td>
13
+ <td>Email</td>
14
+ </tr>
15
+ </thead>
16
+ <tbody>
17
+ <tr class='user_data' data-ruhl="_collection: user_list, class: user_id">
18
+ <td data-ruhl="first_name">Andrew</td>
19
+ <td data-ruhl="last_name">Stone</td>
20
+ <td data-ruhl="email">andy@stonean.com</td>
21
+ </tr>
22
+ </tbody>
23
+ </table>
24
+ </ul>
25
+
26
+ <ul id="ruby_urls">
27
+ <li data-ruhl="_use: ruby_urls">
28
+ <a href="http://rubytrends.com" data-ruhl="href: href, name">RubyTrends</a>
29
+ </li>
30
+ </ul>
31
+ </body>
32
+ </html>
data/spec/ruhl_spec.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  require File.join(File.dirname(__FILE__), 'spec_helper')
2
3
 
3
4
  describe Ruhl do
@@ -34,25 +35,59 @@ describe Ruhl do
34
35
  end
35
36
  end
36
37
 
37
- describe "medium.html" do
38
+ describe "combination.html" do
38
39
  before do
39
- @html = File.read html(:medium)
40
- @doc = create_doc
40
+ @html = File.read html(:combination)
41
41
  end
42
42
 
43
- it "first data row should equal first user " do
44
- table = @doc.xpath('/html/body/table/tr//td')
43
+ it 'first data row should equal first user' do
44
+ doc = create_doc
45
+ table = doc.xpath('/html/body/table/tbody/tr//td')
45
46
  table.children[0].to_s.should == "Jane"
46
47
  table.children[1].to_s.should == "Doe"
47
48
  table.children[2].to_s.should == "jane@stonean.com"
48
49
  end
49
50
 
50
- it "last data row should equal last user " do
51
- table = @doc.xpath('/html/body/table/tr//td')
51
+ it 'last data row should equal last user' do
52
+ doc = create_doc
53
+ table = doc.xpath('/html/body/table/tbody/tr//td')
52
54
  table.children[9].to_s.should == "Paul"
53
55
  table.children[10].to_s.should == "Tin"
54
56
  table.children[11].to_s.should == "paul@stonean.com"
55
57
  end
58
+
59
+ it 'should append user_id to class' do
60
+ doc = create_doc
61
+ rows = doc.xpath('/html/body/table/tbody//tr')
62
+ rows.each do |row|
63
+ row['class'].should =~ /^user_data user_\d+$/
64
+ end
65
+ end
66
+
67
+ it 'should set href from hash' do
68
+ doc = create_doc
69
+ rows = doc.xpath("/html/body/ul[@id='ruby_urls']/li//a")
70
+ rows[0].inner_html.should == 'Ruby Lang'
71
+ rows[0]['href'].should == 'http://ruby-lang.org'
72
+ rows[1].inner_html.should == 'RubyonRails'
73
+ rows[1]['href'].should == 'http://rubyonrails.com'
74
+ rows[2].inner_html.should == 'RubyFlow'
75
+ rows[2]['href'].should == 'http://rubyflow.com'
76
+ rows[3].inner_html.should == 'RubyTrends'
77
+ rows[3]['href'].should == 'http://rubytrends.com'
78
+ end
79
+
80
+ it 'should use instance variable' do
81
+ doc = create_doc
82
+ p = doc.xpath("/html/body/p[@id='time']")
83
+ p.inner_html.should == 'It is now Peanut Butter Jelly time'
84
+ end
85
+
86
+ it 'should not use instance variable' do
87
+ Ruhl.use_instance_variables = false
88
+ lambda{ create_doc }.should raise_error(NoMethodError)
89
+ Ruhl.use_instance_variables = true
90
+ end
56
91
  end
57
92
 
58
93
  describe "fragment.html" do
@@ -362,6 +397,11 @@ describe Ruhl do
362
397
  options = @doc.xpath('/html/body/select//option')
363
398
  options.children.length.should == @co.state_options.length
364
399
  end
400
+
401
+ it "should have selected Georgia" do
402
+ state = @doc.xpath('/html/body/select//option[@selected]')
403
+ state[0]['value'].should == "GA"
404
+ end
365
405
  end
366
406
  end
367
407
 
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib ruhl]))
2
2
 
3
+ Ruhl.logger = Logger.new('test.log')
4
+
3
5
  def html(name)
4
6
  File.join( File.dirname(__FILE__), 'html', "#{name}.html" )
5
7
  end
@@ -30,9 +32,13 @@ class TestUser
30
32
  end
31
33
 
32
34
  def radio_input
33
- { :inner_html => first_name, :id => "user_#{id.to_s}",
35
+ { :inner_html => first_name, :id => user_id,
34
36
  :name => "user[id]", :value => last_name.downcase}
35
37
  end
38
+
39
+ def user_id
40
+ "user_#{id}"
41
+ end
36
42
  end
37
43
 
38
44
  def user
@@ -41,6 +47,10 @@ end
41
47
 
42
48
 
43
49
  class ContextObject
50
+ def initialize
51
+ @time = 'Peanut Butter Jelly'
52
+ end
53
+
44
54
  def language
45
55
  'Ruby'
46
56
  end
@@ -163,7 +173,7 @@ class ContextObject
163
173
  {:value => 'CT', :inner_html => 'Connecticut'},
164
174
  {:value => 'DE', :inner_html => 'Delaware'},
165
175
  {:value => 'FL', :inner_html => 'Florida'},
166
- {:value => 'GA', :inner_html => 'Georgia'},
176
+ {:value => 'GA', :inner_html => 'Georgia', :selected => true},
167
177
  {:value => 'HI', :inner_html => 'Hawaii'},
168
178
  {:value => 'ID', :inner_html => 'Idaho'},
169
179
  {:value => 'IL', :inner_html => 'Illinois'},
@@ -210,6 +220,14 @@ class ContextObject
210
220
  {:class => "pretty", :id => "8675309", :inner_html => "jenny"}
211
221
  end
212
222
 
223
+ def ruby_urls
224
+ [
225
+ {:name => 'Ruby Lang', :href => 'http://ruby-lang.org'},
226
+ {'name' => 'RubyonRails', :href => 'http://rubyonrails.com'},
227
+ {:name => 'RubyFlow', 'href' => 'http://rubyflow.com'},
228
+ {'name' => 'RubyTrends', 'href' => 'http://rubytrends.com'}
229
+ ]
230
+ end
213
231
  end
214
232
 
215
233
  def points_of_interest
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruhl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Stone
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-01 00:00:00 -05:00
12
+ date: 2010-02-10 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -59,6 +59,7 @@ files:
59
59
  - spec/html/basic.html
60
60
  - spec/html/collection_of_hashes.html
61
61
  - spec/html/collection_of_strings.html
62
+ - spec/html/combination.html
62
63
  - spec/html/form.html
63
64
  - spec/html/fragment.html
64
65
  - spec/html/hash.html
@@ -69,7 +70,6 @@ files:
69
70
  - spec/html/loop.html
70
71
  - spec/html/main_with_form.html
71
72
  - spec/html/main_with_sidebar.html
72
- - spec/html/medium.html
73
73
  - spec/html/parameters.html
74
74
  - spec/html/seo.html
75
75
  - spec/html/sidebar.html
@@ -1,23 +0,0 @@
1
- <html>
2
- <head>
3
- <title>This is a title template</title>
4
- </head>
5
- <body>
6
- <h1>This is the header template</h1>
7
- <table>
8
- <thead>
9
- <tr>
10
- <td>First Name</td>
11
- <td>Last Name</td>
12
- <td>Email</td>
13
- </tr>
14
- </thead>
15
- <tr data-ruhl="_collection: user_list">
16
- <td data-ruhl="first_name">Andrew</td>
17
- <td data-ruhl="last_name">Stone</td>
18
- <td data-ruhl="email">andy@stonean.com</td>
19
- </tr>
20
- </table>
21
- </ul>
22
- </body>
23
- </html>