Perhaps more a Ruby question than a Radiant question, but…
I’d like to alter the html that the Mailer Extension outputs for
<r:mailer:option> tags within a <r:mailer:radiogroup>. Rather than have
the Label tag follow the Input tag, I want to wrap in Input tag in the
Label tag (with the label text inside a span). This way, you can have
the action of clicking on the label activate the associated control
(even in IE 6, which for some reason, doesn’t do it with just the for
attribute).
Is there an easy way to “monkey patch” MailerPage to alter the tag
‘mailer:option’ method?
So, instead of:
Yes
No
I’d like to instead output:
Yes
No
One of the main features of Ruby is that it’s “open” in the sense that
your code can modify any other loaded coded as desired.
In your case, make an extension that loads after the mailer extension
and
patches the MailerPage class as desired.
Other option is to patch your local mailer extension directly.
/AITOR
I use svn:externals for my extensions, so directly editing the
MailerPage class is out. I understand that Ruby classes are open, but
the Pages in radiant use a DSL for tags, containing a desc, tag pair.
This is whats throwing me off.
It sounds like you’re saying I can create an extension that loads after
Mailer, and that defines a radius tag that is named the same as the one
whose functionality I am looking to replace (r:mailer:option), and it
will override the one defined in the Mailer extension. Do I understand
you correctly? Could it be that simple?
(Sorry, c# .Net puts food on the table right now, so I’ve grown
accustomed to be skeptical of simple solutions, because there are none
in .Net, not that I’ve found, anyway).
==
Will G.
Yes, you can directly replace MailerExtension’s tag definition with
something in the line of:
class MailerExtension
desc {
-> you will need to duplicate the original desc here, or if you
don’t care just don’t put it (you won’t get docs)
}
tag “r:mailer:option” do |tag|
-> your new code here
end
end
Be sure to define the tag inside the MailerExtension class so it can
access that context. Your tag definition will replace the original one.
The best of Rails is Ruby...
/AITOR
Sadly, thats not working
I did a script/generate extension MailerAlternateRender, then I tried
the following code
(in
/vendor/extensions/mailer_alternate_render/app_models/mailer_alternate_render_tags.rb):
class MailerPage
desc %{ Renders an @@ tag if the parent is a
@<r:mailer:select>…</r:mailer:select>@ tag, an @@ tag if
the parent is a @<r:mailer:radiogroup>…</r:mailer:radiogroup>@ }
tag ‘mailer:option’ do |tag|
@tag_attr = tag.attr.symbolize_keys
raise_error_if_name_missing “mailer:option”
result = “”
if tag.locals.parent_tag_type == ‘select’
result << %Q|<option value="#{tag_attr.delete(:value) ||
tag_attr[:name]}" #{add_attrs_to("")}>#{tag_attr[:name]}|
elsif tag.locals.parent_tag_type == ‘radiogroup’
tag.globals.option_count = tag.globals.option_count.nil? ? 1 :
tag.globals.option_count += 1
options = tag_attr.clone.update({
:id =>
“#{tag.locals.parent_tag_name}_#{tag.globals.option_count}”,
:value => tag_attr.delete(:value) || tag_attr[:name],
:name => tag.locals.parent_tag_name
})
result << %Q|#{tag_attr[:name]}|
result << input_tag_html( ‘radio’, options )
result << “”
#result << input_tag_html( ‘radio’, options )
#result << %Q|#{tag_attr[:name]}|
end
end
end
I’ve also tried putting it in a MailerAlternateRenderTags module
(replacing the class declaration),
and including Page.send :include, MailerAlternateRenderTags in
mailer_alternate_render_extension.rb
Any thoughts?
==
Will G.
Sorry, that’s
vendor/extensions/mailer_alternate_render/app/models/mailer_alternate_render_tags.rb
==
Will G.
Did you get an error? Or your changes did not apply?
In the second case, probably your extension is being loaded before
the
mailer extension. Search this list on how to specify the loading order
of
extensions.
Anyway, don't let pass Sean's offering to apply your changes to the
original code.
/AITOR
Will,
It sounds like you’re jumping through a bunch of unnecessary hoops.
Could you just create a patch for the existing code, put it in a ticket,
and let me know about it? I’ll fix it up right away.
Sean
So I went and solved my own problem by modifying things
(http://github.com/adsmart/radiant-directory-mailer-extension) and it
turns out that it was a very simply addition.
Simply change recipients to directory in you mailer part and add
recipients_field. The value of the recipients field is now a list of the
indexes of items in the directory to use as the recipients.
That is, given a mailer of:
subject: “Sent from your mailer form”
recipient_field: destination
directory:
- [email protected]
- [email protected]
and the form from my original post, the message will be sent only to the
email address(es) that are selected in the form.
I do need help with one bit. I’m not well versed on (T|B)DD so I haven’t
modified the specs to account for the new behaviour. I’m not quite sure
how to do it.
Manually keeping the form and the mailer config in sync is more prone to
error than I’d like so I’m thinking of adding a tag that would let you
do:
<r:mailer:select name=“destination”>
<r:directory />
</r:mailer:select>
To get the names, I’m not sure if I prefer
directory:
- [email protected]
- [email protected]
names:
- “First Address”
- “Second Address”
or
directory:
-
name: “First Address”
email: [email protected]
-
name: “Second Address”
email: [email protected]
either approach has its advantages and disadvantages.
On Thu, 2009-04-09 at 23:26 -0700, Adam van den Hoven wrote:
<r:option value="0">First</r:option>
from_field: email
I’d rather not have to customize the extension if I don’t have to.
–
Adam van den Hoven
Hybrid Web D.
Little Fyr Media
p: 604.618.0845
e: [email protected]
w: http://www.littlefyr.com