I need to use a form so i wanted to read the documentation on how the FormHelper, FormOptionsHelper, and FormTagHelper modules work (assuming they''re all useful for building forms). The first thing i find on this page: http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html is an example of what some code using FormHelper methods would "compile" to. I have a real hard time extracting any really definite information from this, though. It uses fields that i have no information about at all (except via guesswork). For instance, text_field takes 3 arguments: <%= text_field "person", "name", "size" => 20 %> Incidentally, i have a side question that''s been bothering me for a while that i tried to figure out via "Programming Ruby (latest edition) but didn''t find an answer for. My understanding is that "size" => 20 is a hash. Except i don''t get the grammar aspect of it. Is this a case of where the flexibility of the ruby parser allows you to leave off the {} that should surround the hash? I''ve never seen that written down anywhere, though, so this construction (which i''ve seen a lot) has always puzzled me. Anyway, the above "compiles" to: <input type="text" id="person_name" name="person[name]" size="20" value="<%= @person.name %>" /> person gets transformed to id="person_name" ... but why person_name? How am i to understand this? It appears as some sort of magic with no explanation. Which is why i typically have trouble understanding just about all of the documentation, because it''s all like this. Then we have "name" going to name="person[name]" How can i understand any of this without being told, up front, what the definition or meaning of the variables are that are being used to create examples from? It''s all guesswork on my part. I think that maybe if you have a lot of exposure to different parts of the documentation where certain common things are assumed, or you''ve already done a fair amount of programming in Rails, then maybe you can fill in the blanks fairly easily. But i''m a web newbie. And i find it almost impossible to fill in the blanks. Understanding most of the documentation i find to be _really_ difficult. I was going to try to ask some very pointed, specific questions so that i could actually understand what this example is showing, but now, having lapsed into complaining about the documentation again, i''ve run out of steam. craig
> <input type="text" id="person_name" name="person[name]" > size="20" value="<%= @person.name %>" /> > > person gets transformed to id="person_name" ... but why person_name? How am i to > understand this? It appears as some sort of magic with no explanation. Which is why > i typically have trouble understanding just about all of the documentation, because > it''s all like this. > > Then we have "name" going to name="person[name]"I''m sure this seems complex if you''re not already familiar with some web dev conventions. And it''s not explained that thoroughly, true. Let''s see: "person_name" is not magic or arbitrary, it''s simply a way to guarantee that that particular input field gets assigned an id that''s unique on the page. To avoid confusion and to conform to HTML validation rules, elements must have unique id''s. But what if you have *another* object or element on the page that needs "name" as part of its id? To guarantee the ids of elements won''t collide, we prepend the object''s name onto the property. The underscore_style is just Ruby variable name convention. "person[name]" is a little trickier and used a bit differently. Notice that the [] makes this array syntax? That syntax allows Rails to associate the fields in a form with the properties of an object. It''s really just a convenience for things like validation. The good thing is that you as the developer don''t really need to worry about these things (unless you''re writing some custom javascript, in which case you''ll want to be aware of these naming conventions when selecting elements by id). Typically you won''t need to refer directly to the "compiled" names of these fields. Although this example is PHP, there''s a decent explanation of using array syntax to name form fields here: http://www.codecomments.com/archive128-2004-12-353295.html Andrew
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 craig duncan wrote:> from this, though. It uses fields that i have no information about at > all (except via guesswork). For instance, text_field takes 3 arguments: > > <%= text_field "person", "name", "size" => 20 %> > > > Anyway, the above "compiles" to: > > <input type="text" id="person_name" name="person[name]" > size="20" value="<%= @person.name %>" /> >If this helps, maybe someone whould stick it in the docs somewhere.... Most of those functions have a similar pattern. "person" is the name of the AR class type, and "name" is the particular field of that AR record. The reason this is passed in like this is to create unique names for the form. "size" => 20 is indeed a hash, and I belive you could also write the above function as: <%= text_field("person", "name", {"size" => 20}) %> Ruby syntactical sugar lets you drop parens and braces if the function call is defined right. If there were any more foo => "bar" type parameters on the end, they would be assumed to be part of the hash. name="person[name]" This notation indicates an array... and when there are several from items, you may see the pattern forming: person[name] person[age] person[height] person[gender] Thus, when the from is sent back to the server, @params[''person''] has all of the attributes in it, and can be passed directly to almost all of the AR routines. id="person_name" : id attributes are more limited than name attributes, and cannot have [] characters in them. I think problems also arise when the id and name attributes are the same thing. IIRC, it was a javascript/DOM problem. Anyway, the id attribute is just the concatenation of the two values, using an underscore. Actualy, I think the contents of the two variables need to be underwscore notation first as well... see http://api.rubyonrails.com/classes/Inflector.html and the underscore method. So, Given an AR object of CustomerPerson < ActiveRecord::Base with database columns of first_name and age, <%= text_field "customer_person", "first_name", "size" => 20 %> <%= text_field "customer_person", "age", "size" => 20 %> <%= text_field "customer_person", "first_name", "size" => 20 %> should yield something like: <input type="text" id="customer_person_first_name" name="customer_person[first_name]" size="20" value="<%= @customer_person.first_name %>" /> <input type="text" id="customer_person_age" name="customer_person[age]" size="20" value="<%= @customer_person.age %>" /> - -- David Morton Maia Mailguard server side anti-spam/anti-virus solution: http://www.maiamailguard.com -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.5 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org iD8DBQFCb6vuSIxC85HZHLMRArFOAJ90EBCoAJh0w4Pe9l8Z4m5GtXB1YwCdFR3Z zNnN+Y+r1ZBXQKeSV+4tDlQ=w/HE -----END PGP SIGNATURE-----
David Morton wrote:> -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > craig duncan wrote: > >>from this, though. It uses fields that i have no information about at >>all (except via guesswork). For instance, text_field takes 3 arguments: >> >><%= text_field "person", "name", "size" => 20 %> >> >> >>Anyway, the above "compiles" to: >> >><input type="text" id="person_name" name="person[name]" >> size="20" value="<%= @person.name %>" /> >> > > If this helps, maybe someone whould stick it in the docs somewhere.... > > Most of those functions have a similar pattern. "person" is the name of > the AR class type, and "name" is the particular field of that AR > record. The reason this is passed in like this is to create unique > names for the form.So what is there that you can say about this person_name thing by way of explanation? What is it called? Where can you use it? Whatever else that is useful to know where this magic applies?> "size" => 20 is indeed a hash, and I belive you could also write the > above function as: > > <%= text_field("person", "name", {"size" => 20}) %> > > Ruby syntactical sugar lets you drop parens and braces if the function > call is defined right. If there were any more foo => "bar" type > parameters on the end, they would be assumed to be part of the hash.I guessed something like this (for hashes only). As i said, i''ve never seen that documented anywhere, though. Is the only place where this is allowed the argument of a method call? As far as dropping parens... i don''t recall seeing that before. In fact, i''m not sure how that would work. Obviously this doesn''t make sense: method( a,b,c ) # an [implicit] array of 3 elements... NOT!> id="person_name" : id attributes are more limited than name attributes, > and cannot have [] characters in them. I think problems also arise when > the id and name attributes are the same thing.Just to make sure i follow you... "id" and "name" are (x)html attributes, right? But Rails understands something grammatically similar, also, in order to compile to (x)html. And you''re referring to limitations in how Rails parses these (Rails)attributes?> IIRC, it was a > javascript/DOM problem. Anyway, the id attribute is just the > concatenation of the two values, using an underscore. Actualy, I think > the contents of the two variables need to be underwscore notation first > as well... see http://api.rubyonrails.com/classes/Inflector.html and the > underscore method.So is this, basically and mostly, about the rails way of creating id and name attribute values? (done by joing the table/class name with the field/value name)> So, > Given an AR object of CustomerPerson < ActiveRecord::Base with database > columns of first_name and age, > > <%= text_field "customer_person", "first_name", "size" => 20 %> > <%= text_field "customer_person", "age", "size" => 20 %> > <%= text_field "customer_person", "first_name", "size" => 20 %>(did you just accidentally include that last line twice?)> should yield something like: > > <input type="text" id="customer_person_first_name" > name="customer_person[first_name]" > size="20" value="<%= @customer_person.first_name %>" /> > <input type="text" id="customer_person_age" > name="customer_person[age]" > size="20" value="<%= @customer_person.age %>" /> > > - -- > David MortonIf the explanation of this is that Rails creates id & name attribute values using this mechanism, then i now get it. Thanks very much. craig
> David Morton wrote:> >> craig duncan wrote: >> >>> from this, though. It uses fields that i have no information about at >>> all (except via guesswork). For instance, text_field takes 3 arguments: >>> >>> <%= text_field "person", "name", "size" => 20 %> >>> >>> >>> Anyway, the above "compiles" to: >>> >>> <input type="text" id="person_name" name="person[name]" >>> size="20" value="<%= @person.name %>" /> No sooner had i hit "send" than I realized i''d confused myself. I was thinking "id" & "class" (confusing [html]"class" and "name"). name is needed to identify the text box (in this case) to your app. Ok, i get that. I understand "id" now, also. I guess i don''t get the rval side of name="person[name]". person is the class (table) name, you said. But its being accessed like a hash. Right below you have: @person.name, which is how i''d expect this to read. Could it, instead be, name="@person.name"? Actually, now i don''t understand why you have @person there. Isn''t @person an instance variable? I must say, i find this all rather confusing. And i''m not sure why. As long as i keep getting friendly help, though, it would be foolish not to keep struggling with it (i guess. :-)) craig
> No sooner had i hit "send" than I realized i''d confused myself. I was thinking "id" > & "class" (confusing [html]"class" and "name"). name is needed to identify the text > box (in this case) to your app. Ok, i get that. I understand "id" now, also. I > guess i don''t get the rval side of name="person[name]". person is the class (table) > name, you said. But its being accessed like a hash. Right below you have: > @person.name, which is how i''d expect this to read. Could it, instead be, > name="@person.name"? Actually, now i don''t understand why you have @person there. > Isn''t @person an instance variable? I must say, i find this all rather confusing. > And i''m not sure why.Ok, careful. Don''t mix HTML and Ruby. You would never use "name=''@person.name''" in an HTML element. @person is an instance variable in Ruby when the view is rendered. However, it''s not good HTML, so we don''t just slap it into the HTML element. Also, @person.name won''t have any meaning to Rails when the form is sent back when the user clicks "Submit." Instead, the forms "person_name" and "person[name]" are good HTML *for two different reasons.* The two are different because there are two different things that need to be done here: - "id=''person_html''" plays nicely with HTML validation and Javascript. - "name=''person[name]''" lets Rails do some helpful things like validation.
Andrew Otwell wrote:> Ok, careful. Don''t mix HTML and Ruby. You would never use > "name=''@person.name''" in an HTML element. @person is an instance > variable in Ruby when the view is rendered. However, it''s not good HTML, > so we don''t just slap it into the HTML element. Also, @person.name won''t > have any meaning to Rails when the form is sent back when the user > clicks "Submit." > > Instead, the forms "person_name" and "person[name]" are good HTML *for > two different reasons.* The two are different because there are two > different things that need to be done here: > > - "id=''person_html''" plays nicely with HTML validation and Javascript. > - "name=''person[name]''" lets Rails do some helpful things like validation.ok... now i get something that had slipped past me... within <% %> you can have ruby-type references (like @person.name) but in the instance: name=person[name] this is what you refer to as slapped directly into the HTML element (where Ruby code isn''t allowed... which is obvious, i just hadn''t paid enough attention to that distinction). So... about "person[name]" you said:> "person[name]" is a little trickier and used a bit differently. > Notice that the [] makes this array syntax? That syntax allows Rails > to associate the fields in a form with the properties of an object. > It''s really just a convenience for things like validation.<input type="text" id="person_name" name="person[name]" size="20" value="<%= @person.name %>" /> So, regarding person[name], Rails replaces the appearance of person[name] with person.name? And this sort of substitution happens because the seeming array reference triggers it? That''s the best sense i could make out of what you said. So, i''m betting i don''t really understand this yet, but if i did, i''d document this by saying that the appearance of an array type of reference (any or only when involving a class name?) signals (mention the specific Rails component responsible for this, which i''m not sure of) to substitute this array reference with <class>.<attribute> evaluated within Ruby. I still don''t get person. Person isn''t really a class. I assume that the actual class is defined as: class Person... So person is something else. Does Rails just scan for strings that have the "inflected" names of the classes it knows about and do substitutions where these appear to be specified via an array type of access? craig
Wanted to say a quick thanks to Andrew and David for their thoughtful answers to this question. This thread has helped to clear up a bit of confusion that I''ve had myself. But I feel Craig''s question points to a larger issue: <RANT> Where do you go to truely grok these concepts??? I''ve read the tutorial''s by Curt and other''s, made several variations on the recipe and ToDo applications, read PickAxe I and Matz''s docs on Ruby online, read some stuff on LoudThinking, as well as Amy Hoy''s Blog, and referred to the Rails API, AR, AP, and AS docs on rubyonrails.com, read nearly all of the howto''s on the wiki, and bugged the heck out of the good folks on IRC. Net result? I still don''t have a clue as to how to design an app that''s more complicated than the Recipe or ToDo list apps in the tutorial. This became crystal clear after I used Gems to upgrade rails and found myself going head on against the paginator in the list method and view. Curt''s article didn''t prepare me for this! The API docmentation was all there, and I could see that :condtion=> was what I needed,but how the heck do I bend it to my will? After a fruitless trip to IRC (the only time I''ve come away w/out an answer), I used trial and error to figure out that the value from my drop-down was accessed as: :conditions =>"category_id=#{@params[:person][:category_id]}" which I took to mean that my needed data was nested in a multi-dimesional array. Why this is, I still can''t quite explain. Reading the API documentation and the Wiki''s feels like I''m eating code McNuggets. Everything I read assumes knowledge from somewhere else. It isn''t so frustrating that I quit reading, because I know I''ve seen explainations for what''s being referred to elsewhere, and it all ''kind of'' makes sense, but the documentation just doesn''t feel cohesive. I''ve yet to find anything that starts as: This is concept 1 for RoR, Here''s two that builds on #1, and so on (I suppose I''m wanting a PickAxe style book or tutorial for RoR). I know it is not helpful to critize without offering a solution, and perhaps someday I can be part of the solution, but to write a more complete primer, one must understand the topic to begin with. So, again I ask, how did some of you RoR pro''s learn this material so quickly (Rails hasn''t been out that long)? I''m begining to think that the solution is to disect the RoR Ruby source from beginning to end, which might be a good exercise, but isn''t there an easier way? </RANT> Now, having gotten all that off of my chest, I have to say that RoR is a GREAT technology and I look forward to making many more apps with it, even if they are no more sophisticated than a ToDo list. Thanks to everyone who''s worked hard to make it a killer framework! Cheers, Howard P.S. I sincerely apologize if this sounds like I''m knocking Rails. I truely don''t mean to. I''m just hoping someone can say "go to Amazon and buy this book-- it is just what you''re looking for."
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 craig duncan wrote:> No sooner had i hit "send" than I realized i''d confused myself. I was > thinking "id" & "class" (confusing [html]"class" and "name"). name is > needed to identify the text box (in this case) to your app. Ok, i get > that. I understand "id" now, also. I guess i don''t get the rval side > of name="person[name]". person is the class (table) name, you said. > But its being accessed like a hash. Right below you have: @person.name, > which is how i''d expect this to read. Could it, instead be, > name="@person.name"? Actually, now i don''t understand why you have@person.name is used to extract the instance value while rendering the template... it assumes that you have defined a @person object in the controller somewhere. but the html name attribute has to be written as an array to pass the values back in a usefull form. @person wouldn''t make sense there, because AR objects don''t exist in html. - -- David Morton Maia Mailguard server side anti-spam/anti-virus solution: http://www.maiamailguard.com -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.5 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org iD8DBQFCcCujSIxC85HZHLMRAnDdAJ9rXbmRTL9skPjwF5Dlt8jVzDTtrwCbB3Ag H/gti1MjQUYeGp1cuKIipFs=jQC6 -----END PGP SIGNATURE-----
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 craig duncan wrote:> <input type="text" id="person_name" name="person[name]" > size="20" value="<%= @person.name %>" /> > > So, regarding person[name], Rails replaces the appearance of > person[name] with person.name? And this sort of substitution happens > because the seeming array reference triggers it? That''s the best sensenot quite. <%= @person.name %> is replaced by the value of @person.name. Nothing else is replaced.> I still don''t get person. Person isn''t really a class. I assume that > the actual class is defined as: class Person... So person is something > else. Does Rails just scan for strings that have the "inflected" names > of the classes it knows about and do substitutions where these appear to > be specified via an array type of access?Inflection is implied here, so that "person" the first parameter, assumes there is a "class Person" model defined. the input helper writes the html based on the parameters, and inserts the @person.name value in, if it exists. No array is in use yet. What the browser sees is: <input type="text" id="person_name" name="person[name]" size="20" value="david" /> Then when the form is submitted, the @params array/hash contains the info: @params => #hash of all params @params[''person''] => #hash of all items in ''person'' @params[''person''][''name''] => ''david'' - -- David Morton Maia Mailguard server side anti-spam/anti-virus solution: http://www.maiamailguard.com -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.5 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org iD8DBQFCcC+XSIxC85HZHLMRAvVHAKCht9MMZZ2Yaij/lWi4i5LwdRtTRwCdELc7 jV2xA3VShJvZximTyA6pDSg=qFwR -----END PGP SIGNATURE-----
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 craig duncan wrote:> I guessed something like this (for hashes only). As i said, i''ve never > seen that documented anywhere, though. Is the only place where this is > allowed the argument of a method call? As far as dropping parens... i > don''t recall seeing that before. In fact, i''m not sure how that would > work. Obviously this doesn''t make sense: > > method( a,b,c ) # an [implicit] array of 3 elements... NOT!It depends on the way the function is declared. def foo(a) #one parameter # foo( "bar") # => ok, parameter ''a'' is a string # foo "bar" # => ok, same thing # foo "bar", "baz" # => NOT ok # foo {"bar" => "baz"} # => ok, parameter ''a'' is a hash # foo "bar" => "baz" # => ok, same thing # foo "bar" => 1, "baz"=>2 # => still ok end def foo (a,b,c) #three individual parameters # foo ("bar", "baz" , ''c'' => 1, ''p'' =>2, ''q'' => 3) # here , the first two parameters are put ito a and b, # and the rest are scooped up into a hash and placed in c # same as: # foo ("bar", "baz" , { ''c'' => 1, ''p'' =>2, ''q'' => 3} ) # or # foo "bar", "baz" , ''c'' => 1, ''p'' =>2, ''q'' => 3 end> (did you just accidentally include that last line twice?)heh.. yeah> If the explanation of this is that Rails creates id & name attribute > values using this mechanism, then i now get it. Thanks very much.That is the purpose of the first two parameters, yes. The (html) id attribute is usefull for CSS and javascript manipulation of the DOM. The name attribute is for the form return... and so the parameters are to allow RoR to generate these attributes automatically. :) - -- David Morton Maia Mailguard server side anti-spam/anti-virus solution: http://www.maiamailguard.com -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.5 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org iD8DBQFCcDTSSIxC85HZHLMRAtzzAJ9ntwkN3Sq3dwPvX5VQZTPe0wXvfQCeMWGk BSGo/RVDJLrm0nLgBMKfwxQ=s4Pq -----END PGP SIGNATURE-----
David Morton wrote:> the input helper writes the html based on the parameters, and inserts > the @person.name value in, if it exists. No array is in use yet. What > the browser sees is: > > <input type="text" id="person_name" name="person[name]" > size="20" value="david" /> > > Then when the form is submitted, the @params array/hash contains the info: > > @params => #hash of all params > @params[''person''] => #hash of all items in ''person'' > @params[''person''][''name''] => ''david'' > > - -- > David MortonThis clearly distinguishes between what is HTML & browser functioning (which i''m also in the processing of learning) and what Rails does. That the array reference is just part of how the input element works was unknown to me. I get it. Thank you so very much. craig
> Reading the API documentation and the Wiki''s feels like I''m eating code > McNuggets. Everything I read assumes knowledge from somewhere else. It > isn''t so frustrating that I quit reading, because I know I''ve seen > explainations for what''s being referred to elsewhere, and it all ''kind > of'' makes sense, but the documentation just doesn''t feel cohesive. I''ve > yet to find anything that starts as: This is concept 1 for RoR, Here''s > two that builds on #1, and so on (I suppose I''m wanting a PickAxe style > book or tutorial for RoR). > > I know it is not helpful to critize without offering a solution, and > perhaps someday I can be part of the solution, but to write a more > complete primer, one must understand the topic to begin with. > > So, again I ask, how did some of you RoR pro''s learn this material so > quickly (Rails hasn''t been out that long)?Learning how RoR works (those "concepts" you mention that aren''t really documented) can be difficult, but it helps a lot if you have experience from languages/platforms which uses similar ones (PHP in my case).> I''m begining to think that the solution is to disect the RoR Ruby source > from beginning to end, which might be a good exercise, but isn''t there > an easier way?In my experience, reading tutorials will only get you so far, for me it works much better to sit down and make a (preferably small) project. Look for docs or ask questions as you go. Regards, Tomas