Hi all I''m working on a custom FormBuilder that should be able to handle habtm and has_many relationships with just one single method call, similar to the existing text_field, text_area etc. methods. My code in a view looks like that: <%= error_messages_for ''member'' %> <%= form.text_field :email %> <%= form.text_area :signature %> <%= form.has_and_belongs_to_many :preferred_music_styles %> <%= form.belongs_to :origin_country %> And this results in a well-known textfield and textarea for email and signature AND in checkboxes for the habtm relation AND a dropdown select list for the belongs_to association. Anyway, I have adapted some code from the Rails Recipes book and it looks like the following so far: def self.create_tagged_field(method_name) define_method(method_name) do |label, *args| html_surround(label, super) # Provides the HTML code that surrounds the form label and the method (super) that generates the input tag(s) end end field_helpers.reject{|h| h == ''hidden_field''}.concat([:select]).each do |name| create_tagged_field(name) end def html_surround(label, content, options = {}) label_options = {} label_options[:for] = "#{@object_name}_#{label}" unless options[:print_label_for] @template.content_tag(:div, @template.content_tag(:div, @template.content_tag(:label, nil || label.to_s.humanize, # TODO: optional argument :caption instead of nil! label_options ), :class => :label ) + @template.content_tag(''div'', content, :class => :field), :class => :row ) end Now I''d like to offer some more options to the programmer, e.g. to set a custom caption instead of using the name of the database field: <%= form.belongs_to :origin_country, :caption => ''Where do you come from?'' %> Sadly I have no clue where to catch this option and remove it from the options for further processing, because so far Rails creates a "caption" attribute in the input tag with the given value: <select name="xxx" caption="Where do you come from?">... This is for sure not the wished effect, and it pollutes my perfectly valid HTML code! :-) So can anybody tell me how to 1) display this custom label instead of the default caption when this option is set and 2) how to prevent this option from being transmitted to the later Rails processings? Thanks a lot for help. Josh -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Josh, I''ve spent a bit of time with custom form builders. I originally started with help from the cookbook, but later branched out on my own, almost rewriting many of the field helpers to fit exactly what I wanted the output to be. Now, I don''t see where in your code you''re handling your own belongs_to helper, but I imagine it just does some processing to get the list of options and calls the select helper. The idea is to manipulate the options rather than simply passing them on as-is. Inspect args from the end (args.last) and see if it''s a hash. If so, those are your options (and if not, no options were supplied). The important thing to remember is that you want to manipulate the args, passing some of them on to html_surround and keeping them from the form helper (e.g. select). This means you have to provide explicit arguments to super. (Otherwise, the parent class''s method will be called with the original arguments.) So take html_surround(label, super) and change it to # manipulation goes here html_surround(label, super(arguments_for_super), options_for_html_surround) The select helper is a little trickier than the rest because it has two sets of options (''options'' and ''html_options'') where the rest only have one. -- -yossef --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Thanks for these hints, I''m gonna check it out. :-) -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
I''ve got another question... def self.create_tagged_field(method_name, options = {}) define_method(method_name) do |label, *args| html_surround(label, super, options) # Provides the HTML code that surrounds the form label and the method (super) that generates the input tag(s) end end field_helpers.reject{|h| h == ''hidden_field''}.concat([''has_and_belongs_to_many'', ''belongs_to'']).each do |name| label_clickable = true unless name == ''has_and_belongs_to_many'' create_tagged_field(name, :label_clickable => label_clickable) end How do I find out in define_method part what id attribute the created form field method will get? So far I''m guessing it myself in html_surround: caption_options[:for] = "#{@object_name}_#{label}" But sometimes this is not correct. Using a text_field it generates member_nickname which is fine but in other cases - e.g. a collection_select - it generates member_origin_country which is often incorrect because the ID depends there on the association name itself. In my case it should be member_country_id. So I guess there''s a way to examine the ID that Rails will assign to the form element --- but how? :-) Thanks Josh -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Hrm about your above answer... I changed it to the following: def self.create_tagged_field(method_name, options = {}) define_method(method_name) do |label, *args| html_surround(label, super(label, args), options) # Provides the HTML code that surrounds the form label and the method (super) that generates the input tag(s) end end But now I get the following error: undefined method `merge'' for []:Array -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Josh, About knowing the ID of the form element, there are methods in Action Pack for that. I can''t recall them off the top of my head, and to be honest, some of my immense form builder bypassed and provided its own IDs, so I knew exactly what was going on. But look for something like "assign_default_name_and_id" and you''ll see what''s going on. As for your Array#merge problem, if I''m not mistaken it''s just that you''re calling super(label, args) instead of super(label, *args). See this: def args_length(*args) args.length end def blah(arg1, *args) args_length(args) end blah(''test'') => 1 blah(''test'', 1, 2, 3, 4) => 1 def blah(arg1, *args) args_length(*args) end blah(''test'') => 0 blah(''test'', 1, 2, 3, 4) => 4 And there''s one thing that jumps out at me. You''ve changed it so you''re calling super for your brand-new association methods (has_and_belongs_to_many, belongs_to), but the parent class doesn''t have them (I assume). -- -yossef --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---