Extension progress

Hello again,

I’m making some progress on extensions and now I’m looking for a little
push in
the right direction.

I’m working on an extension for displaying data from database for the
FAQ
section of a site using tags (mental branch).

  • Created a FaqExtension and include the tag:

    def activate
    Page.send :include, FaqTag
    end

  • in lib/faq_tag.rb:
    module FaqTag
    include Radiant::Taggable

    class TagError < StandardError; end

    tag “faq” do |tag|
    faq = Answerbookpages.find(:all)
    raise TagError.new(“Faq cannot be found”) unless faq
    tag.locals.faq = faq
    tag.expand
    end

    tag “faqhello” do |tag|
    “Hello #{tag.attr[‘name’] || ‘mundo’}!”
    end

end

  • “faqhello” (<r:faqhello/>) works and “faq” tag is retrieving from db.
    (Obviously, I have an Answerbookpages class

I’m looking for some insight to take it further.

In my FAQ page, I’d like to use something like the following:

<r:faq>
<r:answername />
<r:summary />
</r:faq>

where “answername” and “summary” are fields in the answerbookpages
table.

Not sure where to begin…

In the StandardTags class, I see:

<r:url />

<r:title />

etc…

((Page.column_names.dup << ‘url’) - [‘class_name’, ‘created_by’,
‘updated_by’]).each do |method|
tag(method.to_s) do |tag|
tag.locals.page.send(method)
end

Maybe the answer I’m looking for is something similar to this?

Any thoughts or suggestions are really appreciated

Thank you,
Todd

Howdy Todd,

A combination of cloning the <r:children:each> tag (slightly lower in
the same file) and the metamethod you pointed out should work just
fine. So it would look more like:

<r:faq:each>
<r:answername />
<r:summary />
</r:faq:each>

-jamie

On second glance… what do you need from a FAQ that can’t be
accomplished with page children and a plethora of page parts?

-jamie

It’s the same thing I thought! But, on further review, the site has an
existing
table that is periodically updated from their CRM system (automated,
batch
style).

Jamie, thank you, I really appreciate the suggestion from earlier today.
Haven’t had a chance to further work on it more today, but will report
back to
the list when progress is made. I assume other people want to be able
to pull
in existing database content in one way or another!? Hope that’s not a
stretch and it helps other people out with there extension attempts.

Thanks again,
Todd

Quoting Jamie W. [email protected]:

Todd: I’d make a few tweaks so you don’t have problems:

(Answerbookpage.content_columns.dup).each do |column|
tag “faq:#{column.name}” do |tag|
tag.locals.answer.send(column.name).to_s if tag.locals.answer
end
end

[snip]

tag “faq:each” do |tag|
result = “”
Answerbookpage.find(:all).each do |item|
tag.locals.answer = item
result << tag.expand
end
result
end

Let me explain why I suggest these.

  1. Unless you want to display things like foreign keys, you probably
    don’t want ALL of the columns from your Answerbookpage model – just the
    ones that have actual useful content.
  2. Scoping the tag under “faq” will prevent tags like <r:answername />
    from working under any invalid context.
  3. In both “faq:each” and the dynamically created tags, it’s best to
    define your own local rather than overwriting page. tags.locals.page
    should always refer to the currently rendering page (including
    contextual ones). I’m assuming you just grabbed some code from
    “children:each”. Besides “tag.locals.answer” says better what you’re
    passing around.
  4. I added “.to_s if tag.locals.answer” at the end of your line for a
    little safety. First, sometimes objects that you could get from a model
    could return some ugly inspect string instead of a real representation,
    and also, if somehow your tag gets out of context or gets ‘nil’ in
    tag.locals.answer, you won’t output anything ugly.
  5. Everything you are outputting is a string , so ‘result’ in “faq:each”
    should be a string.

Hope this helps!

Cheers,
Sean C.

Well, that is exactly what I needed. Thanks again, Jamie!

I can’t say if the following code is the best, most efficient way, but
here it
is for posterity sake-

module FaqTag
include Radiant::Taggable

class TagError < StandardError; end

<r:answername />

<r:summary />

etc…

(Answerbookpage.column_names.dup).each do |method|
tag(method.to_s) do |tag|
tag.locals.page.send(method)
end
end

tag “faq” do |tag|
tag.expand
end

tag “faq:each” do |tag|
result = []
Answerbookpage.find(:all).each do |item|
tag.locals.child = item
tag.locals.page = item
result << tag.expand
end
result
end

end

Quoting Jamie W. [email protected]:

Got it nad it makes sense. Thank you!

Quoting Sean C. [email protected]: