diff --git a/lib/curly/presenter.rb b/lib/curly/presenter.rb index c93b700..ffb601f 100644 --- a/lib/curly/presenter.rb +++ b/lib/curly/presenter.rb @@ -188,6 +188,13 @@ def presenter_for_name(name) end end + def presenter_for?(name) + presenter_for_name(name) + true + rescue NameError + false + end + # Whether a component is available to templates rendered with the # presenter. # @@ -215,6 +222,67 @@ def available_components methods.map(&:to_s) end + # Gives a description of the presenter. Gives information about its + # components, and what parameters they are allowed. + # + # Returns a Hash. + def description + result = {} + components = result[:components] = [] + + available_components.each do |component| + data = { name: component, + type: "", + attributes: [], + identifier: nil, + block: false } + + if component.end_with?("?") + data[:type] = "conditional" + elsif presenter_for?(component) + data[:type] = "context" + elsif presenter_for?(component.singularize) + data[:type] = "collection" + else + data[:type] = "value" + end + + instance_method(component.intern).parameters.each do |param| + add = {} + add[:name] = param[1].to_s + + case param[0] + when :keyreq + add[:type] = "keyword" + add[:required] = true + when :key + add[:type] = "keyword" + add[:required] = false + when :req + data[:identifier] = add + add[:required] = true + add = nil + when :opt + data[:identifier] = add + add[:required] = false + add = nil + when :block + data[:block] = add[:name] + add = nil + else + add[:type] = "unknown" + add[:required] = false + end + + data[:attributes] << add if add + end + + components << data + end + + result + end + # The set of view paths that the presenter depends on. # # Examples diff --git a/spec/presenter_spec.rb b/spec/presenter_spec.rb index 6c09b15..bc24251 100644 --- a/spec/presenter_spec.rb +++ b/spec/presenter_spec.rb @@ -13,6 +13,26 @@ def monkey presents :elephant, default: "Dumbo" attr_reader :midget, :clown, :elephant + + def alpha(name, age: 12) + name + end + + def beta(test:, this: "thing") + test + this + end + + def charlie(&test) + end + + def delta? + false + end + + def cats + end + + class CatPresenter < Curly::Presenter; end end class FrenchCircusPresenter < CircusPresenter @@ -112,6 +132,72 @@ class CircusPresenter::MonkeyPresenter < Curly::Presenter end end + describe ".description" do + it "gives a hash" do + CircusPresenter.description.should be_a Hash + end + + it "describes the components" do + description = CircusPresenter.description + + description[:components].should have(9).items + description[:components].should == [ + { name: "midget", + type: "value", + attributes: [], + identifier: nil, + block: false }, + { name: "clown", + type: "value", + attributes: [], + identifier: nil, + block: false }, + { name: "elephant", + type: "value", + attributes: [], + identifier: nil, + block: false }, + + { name: "alpha", + type: "value", + attributes: [ + { name: "age", type: "keyword", required: false }], + identifier: { name: "name", required: true }, + block: false }, + + { name: "beta", + type: "value", + attributes: [ + { name: "test", type: "keyword", required: true }, + { name: "this", type: "keyword", required: false }], + identifier: nil, + block: false }, + + { name: "charlie", + type: "value", + attributes: [], + identifier: nil, + block: "test" }, + + { name: "delta?", + type: "conditional", + attributes: [], + identifier: nil, + block: false }, + { name: "cats", + type: "collection", + attributes: [], + identifier: nil, + block: false }, + { name: "monkey", + type: "context", + attributes: [], + identifier: nil, + block: false } + ] + end + end + describe ".version" do it "sets the version of the presenter" do presenter1 = Class.new(Curly::Presenter) do