liquor 0.1.1 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (176) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +3 -9
  5. data/Gemfile +7 -0
  6. data/Guardfile +11 -0
  7. data/MIT-LICENSE +6 -2
  8. data/README.md +4 -122
  9. data/Rakefile +20 -23
  10. data/doc/language-spec.html +768 -0
  11. data/doc/language-spec.md +698 -0
  12. data/lib/liquor.rb +39 -68
  13. data/lib/liquor/ast_tools.rb +28 -0
  14. data/lib/liquor/compiler.rb +110 -0
  15. data/lib/liquor/context.rb +76 -254
  16. data/lib/liquor/diagnostics.rb +151 -0
  17. data/lib/liquor/drop/drop.rb +168 -0
  18. data/lib/liquor/drop/drop_delegation.rb +24 -0
  19. data/lib/liquor/drop/drop_scope.rb +118 -0
  20. data/lib/liquor/drop/dropable.rb +17 -0
  21. data/lib/liquor/emitter.rb +313 -0
  22. data/lib/liquor/extensions/kaminari.rb +14 -0
  23. data/lib/liquor/extensions/pagination.rb +235 -0
  24. data/lib/liquor/extensions/rails.rb +97 -0
  25. data/lib/liquor/extensions/thinking_sphinx.rb +14 -0
  26. data/lib/liquor/extensions/tire.rb +30 -0
  27. data/lib/liquor/external.rb +79 -0
  28. data/lib/liquor/function.rb +94 -0
  29. data/lib/liquor/grammar/lexer.rb +1223 -0
  30. data/lib/liquor/grammar/lexer.rl +297 -0
  31. data/lib/liquor/grammar/parser.racc +288 -0
  32. data/lib/liquor/grammar/parser.rb +885 -0
  33. data/lib/liquor/library.rb +41 -0
  34. data/lib/liquor/manager.rb +146 -0
  35. data/lib/liquor/runtime.rb +167 -0
  36. data/lib/liquor/stdlib/builtin_functions.rb +315 -0
  37. data/lib/liquor/stdlib/builtin_tags.rb +228 -0
  38. data/lib/liquor/stdlib/html_truncater.rb +162 -0
  39. data/lib/liquor/stdlib/partial_tags.rb +76 -0
  40. data/lib/liquor/tag.rb +83 -14
  41. data/lib/liquor/version.rb +1 -1
  42. data/liquor.gemspec +29 -6
  43. data/spec/builtins_spec.rb +264 -0
  44. data/spec/compiler_spec.rb +136 -0
  45. data/spec/context_spec.rb +49 -0
  46. data/spec/drop_delegation_spec.rb +21 -0
  47. data/spec/drop_spec.rb +222 -0
  48. data/spec/errors_spec.rb +40 -0
  49. data/spec/external_spec.rb +207 -0
  50. data/spec/function_spec.rb +80 -0
  51. data/spec/lexer_spec.rb +173 -0
  52. data/spec/library_spec.rb +18 -0
  53. data/spec/manager_spec.rb +84 -0
  54. data/spec/parser_spec.rb +381 -0
  55. data/spec/partials_spec.rb +74 -0
  56. data/spec/runtime_spec.rb +97 -0
  57. data/spec/spec_helper.rb +94 -0
  58. data/spec/tag_spec.rb +7 -0
  59. metadata +216 -173
  60. data/AUTHORS +0 -2
  61. data/CHANGELOG +0 -48
  62. data/Gemfile.lock +0 -91
  63. data/History.txt +0 -44
  64. data/LICENSE +0 -23
  65. data/example/server/example_servlet.rb +0 -37
  66. data/example/server/liquid_servlet.rb +0 -28
  67. data/example/server/liquor_servlet.rb +0 -28
  68. data/example/server/server.rb +0 -12
  69. data/example/server/templates/index.liquid +0 -6
  70. data/example/server/templates/index.liquor +0 -6
  71. data/example/server/templates/products.liquid +0 -45
  72. data/example/server/templates/products.liquor +0 -45
  73. data/init.rb +0 -8
  74. data/lib/extras/liquid_view.rb +0 -51
  75. data/lib/extras/liquor_view.rb +0 -51
  76. data/lib/liquor/block.rb +0 -101
  77. data/lib/liquor/condition.rb +0 -120
  78. data/lib/liquor/document.rb +0 -17
  79. data/lib/liquor/drop.rb +0 -256
  80. data/lib/liquor/errors.rb +0 -11
  81. data/lib/liquor/extensions.rb +0 -72
  82. data/lib/liquor/file_system.rb +0 -62
  83. data/lib/liquor/htmltags.rb +0 -74
  84. data/lib/liquor/module_ex.rb +0 -60
  85. data/lib/liquor/standardfilters.rb +0 -315
  86. data/lib/liquor/strainer.rb +0 -58
  87. data/lib/liquor/tags/assign.rb +0 -33
  88. data/lib/liquor/tags/capture.rb +0 -35
  89. data/lib/liquor/tags/case.rb +0 -83
  90. data/lib/liquor/tags/comment.rb +0 -9
  91. data/lib/liquor/tags/content_for.rb +0 -54
  92. data/lib/liquor/tags/cycle.rb +0 -59
  93. data/lib/liquor/tags/for.rb +0 -136
  94. data/lib/liquor/tags/if.rb +0 -80
  95. data/lib/liquor/tags/ifchanged.rb +0 -20
  96. data/lib/liquor/tags/include.rb +0 -56
  97. data/lib/liquor/tags/unless.rb +0 -33
  98. data/lib/liquor/tags/yield.rb +0 -49
  99. data/lib/liquor/template.rb +0 -181
  100. data/lib/liquor/variable.rb +0 -52
  101. data/performance/shopify.rb +0 -92
  102. data/performance/shopify/comment_form.rb +0 -33
  103. data/performance/shopify/database.rb +0 -45
  104. data/performance/shopify/json_filter.rb +0 -7
  105. data/performance/shopify/liquid.rb +0 -18
  106. data/performance/shopify/liquor.rb +0 -18
  107. data/performance/shopify/money_filter.rb +0 -18
  108. data/performance/shopify/paginate.rb +0 -93
  109. data/performance/shopify/shop_filter.rb +0 -98
  110. data/performance/shopify/tag_filter.rb +0 -25
  111. data/performance/shopify/vision.database.yml +0 -945
  112. data/performance/shopify/weight_filter.rb +0 -11
  113. data/performance/tests/dropify/article.liquid +0 -74
  114. data/performance/tests/dropify/blog.liquid +0 -33
  115. data/performance/tests/dropify/cart.liquid +0 -66
  116. data/performance/tests/dropify/collection.liquid +0 -22
  117. data/performance/tests/dropify/index.liquid +0 -47
  118. data/performance/tests/dropify/page.liquid +0 -8
  119. data/performance/tests/dropify/product.liquid +0 -68
  120. data/performance/tests/dropify/theme.liquid +0 -105
  121. data/performance/tests/ripen/article.liquid +0 -74
  122. data/performance/tests/ripen/blog.liquid +0 -13
  123. data/performance/tests/ripen/cart.liquid +0 -54
  124. data/performance/tests/ripen/collection.liquid +0 -29
  125. data/performance/tests/ripen/index.liquid +0 -32
  126. data/performance/tests/ripen/page.liquid +0 -4
  127. data/performance/tests/ripen/product.liquid +0 -75
  128. data/performance/tests/ripen/theme.liquid +0 -85
  129. data/performance/tests/tribble/404.liquid +0 -56
  130. data/performance/tests/tribble/article.liquid +0 -98
  131. data/performance/tests/tribble/blog.liquid +0 -41
  132. data/performance/tests/tribble/cart.liquid +0 -134
  133. data/performance/tests/tribble/collection.liquid +0 -70
  134. data/performance/tests/tribble/index.liquid +0 -94
  135. data/performance/tests/tribble/page.liquid +0 -56
  136. data/performance/tests/tribble/product.liquid +0 -116
  137. data/performance/tests/tribble/search.liquid +0 -51
  138. data/performance/tests/tribble/theme.liquid +0 -90
  139. data/performance/tests/vogue/article.liquid +0 -66
  140. data/performance/tests/vogue/blog.liquid +0 -32
  141. data/performance/tests/vogue/cart.liquid +0 -58
  142. data/performance/tests/vogue/collection.liquid +0 -19
  143. data/performance/tests/vogue/index.liquid +0 -22
  144. data/performance/tests/vogue/page.liquid +0 -3
  145. data/performance/tests/vogue/product.liquid +0 -62
  146. data/performance/tests/vogue/theme.liquid +0 -122
  147. data/test/assign_test.rb +0 -11
  148. data/test/block_test.rb +0 -58
  149. data/test/capture_test.rb +0 -41
  150. data/test/condition_test.rb +0 -115
  151. data/test/content_for_test.rb +0 -15
  152. data/test/context_test.rb +0 -479
  153. data/test/drop_test.rb +0 -162
  154. data/test/error_handling_test.rb +0 -89
  155. data/test/extra/breakpoint.rb +0 -547
  156. data/test/extra/caller.rb +0 -80
  157. data/test/file_system_test.rb +0 -30
  158. data/test/filter_test.rb +0 -147
  159. data/test/helper.rb +0 -24
  160. data/test/html_tag_test.rb +0 -31
  161. data/test/if_else_test.rb +0 -139
  162. data/test/include_tag_test.rb +0 -129
  163. data/test/module_ex_test.rb +0 -89
  164. data/test/output_test.rb +0 -121
  165. data/test/parsing_quirks_test.rb +0 -54
  166. data/test/regexp_test.rb +0 -45
  167. data/test/security_test.rb +0 -41
  168. data/test/standard_filter_test.rb +0 -170
  169. data/test/standard_tag_test.rb +0 -405
  170. data/test/statements_test.rb +0 -137
  171. data/test/strainer_test.rb +0 -27
  172. data/test/template_test.rb +0 -82
  173. data/test/test_helper.rb +0 -28
  174. data/test/unless_else_test.rb +0 -27
  175. data/test/variable_test.rb +0 -173
  176. data/test/yield_test.rb +0 -24
@@ -1,51 +0,0 @@
1
- # LiquorView is a action view extension class. You can register it with rails
2
- # and use liquor as an template system for .liquor files
3
- #
4
- # Example
5
- #
6
- # ActionView::Base::register_template_handler :liquor, LiquorView
7
- class LiquorView
8
- PROTECTED_ASSIGNS = %w( template_root response _session template_class action_name request_origin session template
9
- _response url _request _cookies variables_added _flash params _headers request cookies
10
- ignore_missing_templates flash _params logger before_filter_chain_aborted headers )
11
- PROTECTED_INSTANCE_VARIABLES = %w( @_request @controller @_first_render @_memoized__pick_template @view_paths
12
- @helpers @assigns_added @template @_render_stack @template_format @assigns )
13
-
14
- def self.call(template)
15
- "LiquorView.new(self).render(template, local_assigns)"
16
- end
17
-
18
- def initialize(view)
19
- @view = view
20
- end
21
-
22
- def render(template, local_assigns = nil)
23
- @view.controller.headers["Content-Type"] ||= 'text/html; charset=utf-8'
24
-
25
- # Rails 2.2 Template has source, but not locals
26
- if template.respond_to?(:source) && !template.respond_to?(:locals)
27
- assigns = (@view.instance_variables - PROTECTED_INSTANCE_VARIABLES).inject({}) do |hash, ivar|
28
- hash[ivar[1..-1]] = @view.instance_variable_get(ivar)
29
- hash
30
- end
31
- else
32
- assigns = @view.assigns.reject{ |k,v| PROTECTED_ASSIGNS.include?(k) }
33
- end
34
-
35
- source = template.respond_to?(:source) ? template.source : template
36
- local_assigns = (template.respond_to?(:locals) ? template.locals : local_assigns) || {}
37
-
38
- if content_for_layout = @view.instance_variable_get("@content_for_layout")
39
- assigns['content_for_layout'] = content_for_layout
40
- end
41
- assigns.merge!(local_assigns.stringify_keys)
42
-
43
- liquor = Liquor::Template.parse(source)
44
- liquor.render(assigns, :filters => [@view.controller.master_helper_module], :registers => {:action_view => @view, :controller => @view.controller})
45
- end
46
-
47
- def compilable?
48
- false
49
- end
50
-
51
- end
@@ -1,101 +0,0 @@
1
- module Liquor
2
-
3
- class Block < Tag
4
- IsTag = /^#{TagStart}/
5
- IsVariable = /^#{VariableStart}/
6
- FullToken = /^#{TagStart}\s*(\w+)\s*(.*)?#{TagEnd}$/
7
- ContentOfVariable = /^#{VariableStart}(.*)#{VariableEnd}$/
8
-
9
- def parse(tokens)
10
- @nodelist ||= []
11
- @nodelist.clear
12
-
13
- while token = tokens.shift
14
-
15
- case token
16
- when IsTag
17
- if token =~ FullToken
18
-
19
- # if we found the proper block delimitor just end parsing here and let the outer block
20
- # proceed
21
- if block_delimiter == $1
22
- end_tag
23
- return
24
- end
25
-
26
- # fetch the tag from registered blocks
27
- if tag = Template.tags[$1]
28
- @nodelist << tag.new($1, $2, tokens)
29
- else
30
- # this tag is not registered with the system
31
- # pass it to the current block for special handling or error reporting
32
- unknown_tag($1, $2, tokens)
33
- end
34
- else
35
- raise SyntaxError, "Tag '#{token}' was not properly terminated with regexp: #{TagEnd.inspect} "
36
- end
37
- when IsVariable
38
- @nodelist << create_variable(token)
39
- when ''
40
- # pass
41
- else
42
- @nodelist << token
43
- end
44
- end
45
-
46
- # Make sure that its ok to end parsing in the current block.
47
- # Effectively this method will throw and exception unless the current block is
48
- # of type Document
49
- assert_missing_delimitation!
50
- end
51
-
52
- def end_tag
53
- end
54
-
55
- def unknown_tag(tag, params, tokens)
56
- case tag
57
- when 'else'
58
- raise SyntaxError, "#{block_name} tag does not expect else tag"
59
- when 'end'
60
- raise SyntaxError, "'end' is not a valid delimiter for #{block_name} tags. use #{block_delimiter}"
61
- else
62
- raise SyntaxError, "Unknown tag '#{tag}'"
63
- end
64
- end
65
-
66
- def block_delimiter
67
- "end#{block_name}"
68
- end
69
-
70
- def block_name
71
- @tag_name
72
- end
73
-
74
- def create_variable(token)
75
- token.scan(ContentOfVariable) do |content|
76
- return Variable.new(content.first)
77
- end
78
- raise SyntaxError.new("Variable '#{token}' was not properly terminated with regexp: #{VariableEnd.inspect} ")
79
- end
80
-
81
- def render(context)
82
- render_all(@nodelist, context)
83
- end
84
-
85
- protected
86
-
87
- def assert_missing_delimitation!
88
- raise SyntaxError.new("#{block_name} tag was never closed")
89
- end
90
-
91
- def render_all(list, context)
92
- list.collect do |token|
93
- begin
94
- token.respond_to?(:render) ? token.render(context) : token
95
- rescue Exception => e
96
- context.handle_error(e)
97
- end
98
- end
99
- end
100
- end
101
- end
@@ -1,120 +0,0 @@
1
- module Liquor
2
- # Container for liquor nodes which conveniently wraps decision making logic
3
- #
4
- # Example:
5
- #
6
- # c = Condition.new('1', '==', '1')
7
- # c.evaluate #=> true
8
- #
9
- class Condition #:nodoc:
10
- @@operators = {
11
- '==' => lambda { |cond, left, right| cond.send(:equal_variables, left, right) },
12
- '!=' => lambda { |cond, left, right| !cond.send(:equal_variables, left, right) },
13
- '<>' => lambda { |cond, left, right| !cond.send(:equal_variables, left, right) },
14
- '<' => :<,
15
- '>' => :>,
16
- '>=' => :>=,
17
- '<=' => :<=,
18
- 'contains' => lambda { |cond, left, right| left && right ? left.include?(right) : false }
19
- }
20
-
21
- def self.operators
22
- @@operators
23
- end
24
-
25
- attr_reader :attachment
26
- attr_accessor :left, :operator, :right
27
-
28
- def initialize(left = nil, operator = nil, right = nil)
29
- @left, @operator, @right = left, operator, right
30
- @child_relation = nil
31
- @child_condition = nil
32
- end
33
-
34
- def evaluate(context = Context.new)
35
- result = interpret_condition(left, right, operator, context)
36
-
37
- case @child_relation
38
- when :or
39
- result || @child_condition.evaluate(context)
40
- when :and
41
- result && @child_condition.evaluate(context)
42
- else
43
- result
44
- end
45
- end
46
-
47
- def or(condition)
48
- @child_relation, @child_condition = :or, condition
49
- end
50
-
51
- def and(condition)
52
- @child_relation, @child_condition = :and, condition
53
- end
54
-
55
- def attach(attachment)
56
- @attachment = attachment
57
- end
58
-
59
- def else?
60
- false
61
- end
62
-
63
- def inspect
64
- "#<Condition #{[@left, @operator, @right].compact.join(' ')}>"
65
- end
66
-
67
- private
68
-
69
- def equal_variables(left, right)
70
- if left.is_a?(Symbol)
71
- if right.respond_to?(left)
72
- return right.send(left.to_s)
73
- else
74
- return nil
75
- end
76
- end
77
-
78
- if right.is_a?(Symbol)
79
- if left.respond_to?(right)
80
- return left.send(right.to_s)
81
- else
82
- return nil
83
- end
84
- end
85
-
86
- left == right
87
- end
88
-
89
- def interpret_condition(left, right, op, context)
90
- # If the operator is empty this means that the decision statement is just
91
- # a single variable. We can just poll this variable from the context and
92
- # return this as the result.
93
- return context[left] if op == nil
94
-
95
- left, right = context[left], context[right]
96
-
97
- operation = self.class.operators[op] || raise(ArgumentError.new("Unknown operator #{op}"))
98
-
99
- if operation.respond_to?(:call)
100
- operation.call(self, left, right)
101
- elsif left.respond_to?(operation) and right.respond_to?(operation)
102
- left.send(operation, right)
103
- else
104
- nil
105
- end
106
- end
107
- end
108
-
109
-
110
- class ElseCondition < Condition
111
- def else?
112
- true
113
- end
114
-
115
- def evaluate(context)
116
- true
117
- end
118
- end
119
-
120
- end
@@ -1,17 +0,0 @@
1
- module Liquor
2
- class Document < Block
3
- # we don't need markup to open this block
4
- def initialize(tokens)
5
- parse(tokens)
6
- end
7
-
8
- # There isn't a real delimter
9
- def block_delimiter
10
- []
11
- end
12
-
13
- # Document blocks don't need to be terminated since they are not actually opened
14
- def assert_missing_delimitation!
15
- end
16
- end
17
- end
@@ -1,256 +0,0 @@
1
- module Liquor
2
-
3
- # A drop in liquor is a class which allows you to to export DOM like things to liquor
4
- # Methods of drops are callable.
5
- # The main use for liquor drops is the implement lazy loaded objects.
6
- # If you would like to make data available to the web designers which you don't want loaded unless needed then
7
- # a drop is a great way to do that
8
- #
9
- # Example:
10
- #
11
- # class ProductDrop < Liquor::Drop
12
- # def top_sales
13
- # Shop.current.products.find(:all, :order => 'sales', :limit => 10 )
14
- # end
15
- # end
16
- #
17
- # tmpl = Liquor::Template.parse( ' {% for product in product.top_sales %} {{ product.name }} {%endfor%} ' )
18
- # tmpl.render('product' => ProductDrop.new ) # will invoke top_sales query.
19
- #
20
- # Your drop can either implement the methods sans any parameters or implement the before_method(name) method which is a
21
- # catch all
22
- class Drop
23
- attr_writer :context
24
-
25
- class_attribute :liquor_attributes
26
- self.liquor_attributes = []
27
-
28
- class_attribute :liquor_scopes
29
- self.liquor_scopes = []
30
- attr_reader :source
31
-
32
- class_attribute :has_manies
33
- self.has_manies = []
34
-
35
- def logger
36
- Rails.logger
37
- end
38
-
39
- def self.allow_all_methods(allow = true)
40
- if allow
41
- class_eval <<-"END"
42
- def before_method(method)
43
- @source.send(method.to_sym)
44
- end
45
-
46
- def respond_to?(val)
47
- return true if @source.respond_to?(val.to_sym)
48
- return true if liquor_attributes.include? val.to_sym
49
- super
50
- end
51
- END
52
- end
53
- end
54
-
55
- def self.has_one(name)
56
- self.instance_eval do
57
- define_method(name) do
58
- (@source.send(name)).to_liquor
59
- end
60
- end
61
- end
62
-
63
- def self.belongs_to(name)
64
- self.instance_eval do
65
- define_method(name) do
66
- (@source.send(name)).to_liquor
67
- end
68
- end
69
- end
70
-
71
- def respond_to?(val)
72
- return true if liquor_attributes.include? val.to_sym
73
- super
74
- end
75
-
76
- def self.has_many(name, options={})
77
- options = options.reverse_merge({ :class_name => name.to_s.classify + "Drop", :sort_scope => :recent, :source_class_name => name.to_s.classify })
78
-
79
- klass = options[:class_name].constantize
80
- source_klass = options[:source_class_name].constantize
81
-
82
- self.class_eval do
83
- self.has_manies << name
84
-
85
- define_method name do
86
- proxy = DropProxy.new(self, name, klass)
87
- proxy = proxy.send(options[:with_scope]) if options[:with_scope].present? && source_klass.respond_to?(options[:with_scope])
88
- proxy = proxy.send(options[:sort_scope]) if options[:sort_scope].present? && source_klass.respond_to?(options[:sort_scope])
89
- proxy
90
- end
91
- end
92
- end
93
-
94
- def initialize(source = nil)
95
- @source = source
96
- @liquor = liquor_attributes.inject({}) { |h, k| h.update k.to_s => @source.send(k) }
97
- end
98
-
99
- def drop_name
100
- self.class.name
101
- end
102
-
103
- def source_id
104
- @source.id
105
- end
106
-
107
- def has_scope?(meth)
108
- liquor_scopes.include?(meth.to_sym)
109
- end
110
-
111
- def has_many?(meth)
112
- has_manies.include?(meth.to_sym)
113
- end
114
-
115
- # Catch all for the method
116
- def before_method(method)
117
- @liquor[method.to_s]
118
- end
119
-
120
- def ==(comparison_object)
121
- our_self = self.source ? self.source : source
122
- our_self == (comparison_object.is_a?(self.class) ? comparison_object.source : comparison_object)
123
- end
124
-
125
- # called by liquor to invoke a drop
126
- def invoke_drop(method)
127
- # for backward compatibility with Ruby 1.8
128
- methods = self.class.public_instance_methods.map { |m| m.to_s }
129
- if methods.include?(method.to_s)
130
- send(method.to_sym)
131
- else
132
- before_method(method)
133
- end
134
- end
135
-
136
- def has_key?(name)
137
- true
138
- end
139
-
140
- def to_liquor
141
- self
142
- end
143
-
144
- def as_json(options = {})
145
- options = options.duplicable? ? options.dup : {}
146
-
147
- only = liquor_attributes
148
-
149
- if options[:include].present?
150
- klass_name = options[:include].to_s.singularize.classify + "Drop"
151
- only += klass_name.constantize.liquor_attributes
152
- end
153
-
154
- options = options.reverse_merge(:only => only)
155
- @source.as_json(options)
156
- end
157
-
158
- alias :[] :invoke_drop
159
-
160
- # converts an array of records to an array of liquor drops, and assigns the given context to each of them
161
- def self.liquify(current_context, *records, &block)
162
- i = -1
163
- records =
164
- records.inject [] do |all, r|
165
- i+=1
166
- attrs = (block && block.arity == 1) ? [r] : [r, i]
167
- all << (block ? block.call(*attrs) : r.to_liquor)
168
- all.last.context = current_context if all.last.is_a?(Drop)
169
- all
170
- end
171
- records.compact!
172
- records
173
- end
174
-
175
- protected
176
- def liquify(*records, &block)
177
- self.class.liquify(@context, *records, &block)
178
- end
179
-
180
- class DropProxy
181
- attr_reader :current, :parent
182
-
183
- def initialize(parent, name, klass)
184
- @parent = parent
185
- @klass = klass
186
-
187
- if @parent.class == DropProxy
188
- @current = @parent.current
189
- elsif name.present?
190
- @current = @parent.source.send name
191
- end
192
- end
193
-
194
- def liquify(*collection)
195
- @parent.send :liquify, *collection
196
- end
197
-
198
- def self.liquor_scopes
199
- @parent.class.liquor_scopes
200
- end
201
-
202
- #
203
- # It is very important that we do not delegate the 'to_liquor' method and it returns 'self'.
204
- NON_DELEGATE_METHODS = ['class', 'send', 'to_liquor', 'respond_to?']
205
- [].methods.each do |m|
206
- unless m =~ /^__/ || NON_DELEGATE_METHODS.include?(m.to_s)
207
- delegate m, :to => :proxy_found
208
- end
209
- end
210
-
211
- def to_liquor
212
- self
213
- end
214
-
215
- def proxy_found
216
- @collection ||= get_collection
217
- @parent.send :liquify, *@collection
218
- end
219
-
220
- def has_scope?(meth)
221
- @klass.liquor_scopes.include?(meth.to_sym)
222
- end
223
-
224
- private
225
- def method_missing(meth, *args)
226
- if has_scope?(meth)
227
- converted_args = args.collect{|arg|
228
- if arg.is_a? DropProxy
229
- arg.current
230
- elsif arg.is_a?(Drop)
231
- arg.source
232
- else
233
- if arg.is_a?(Array)
234
- arg = arg.collect{|x| x.source }
235
- end
236
- arg
237
- end
238
- }
239
- @current = @current.send(meth, *converted_args)
240
- DropProxy.new(self, meth, @klass)
241
- else
242
- super
243
- end
244
- end
245
-
246
- def get_collection
247
- @collection = @current
248
- end
249
-
250
- # HACK
251
- def set_current(val)
252
- @current = val
253
- end
254
- end
255
- end
256
- end