I’m trying to create a Member class with create, update, and delete
methods, but they’re not working because, as I later realized, I
programmed my validations that way. Realizing the truth, I have
several questions before I seriously screw around with the model and
edit methods.
The <%=error_messages_for ‘member’%> doesn’t print out anything.
This was pretty much the reason why I didn’t notice any validation
errors for quite a while (out of random, it suddenly popped out the
error, then disappeared thereafter). I was wondering why
errors_messages_for may not print out any errors regardless of obvious
validation violations. Does flash[:notice] override the
error_messages_for methods? Since I have a single-inheritance models
branching from Member, do I have to call it off of the higher class
name? I thought polymorphism took care of that.
Realizing that some text-fields must be left blank during member
editing (say, admin can edit member description, but not it’s username
or email address), despite the fact that some of those fields cannot
be left empty according to the validation rules, I decided instead of
using @temporaryMember.update_attributes(params[:member]), I should
create a member object, change it’s parameters there, and then call @temporaryMember.save(). First I wanted to make sure: does all
variables in a Model have getters (i.e. the statement
@temporaryMember.username=‘tommy’ is valid)?
In continuation to the previous question, how does a model know
whether to use create or update? What happens if, say, I changed the
model’s id? Will Rails get confused and create a new object in the
database?
Finally, because I only need to check whether the password is
actually there during the creation method, I was wondering if I can
call validates_presence_of :password on the before_create filter?
Assuming your views do have error_messages_for, then in order for
those errors to be visible on your browser you should:
Edit your css to set some formatting on the field in question by
defining
a class :fieldWithErrors (Agile Web Dev 2 page 493)
Check your return code from update_attributes and if not
successful make
sure to “render”, and not “redirect”. If you redirect then you’ll
lose all your
error info. flash[:notice] does not interfer and its helpful to use it
as well as errors_for
Model attributes are automatically read/writeable for you
Rails knows to create or update based upon there being an non-null
ID column
(assuming that’s your primary key). Generally, a hidden_field of ID
in your form
means all of that should work transparently. Changing your ID is not
very helpful
in most cases (ie. since its used to manage foreign key relationships
you will
lost that relationship if you change the id)
A really basic setup might look something like this to process your
form:
def edit
if request.post? then # form posting data
# if the row is in the database then get it, if not make a new one
info = Info.find(params[data][id]) || Info.new
if info.update_attributes([data]) then
if info.save then
# all is OK - redirect, or some other processing
else
# woops - save error
end
else
# woops - update error
end
render the same template again to display error
else
# its a get request, so check the parameters from the url and
retrieve
# the row to edit then render
end
end
The ID attribute is special and important to Rails for maintaining a
unique
identity of a row and for creating and managing foreign key
relationships.
So you would normally have it in your form, hidden, so that it can be
used to locate your row again when you’re updating.
If you want to display columns but not have them editable then you can
use
“disable” a form field. This will display the info but not let you
edit it in the
form. Like so:
There is no need to include information in your form that you have no
business logic need for (ID being a special case - and I’m sure you
know I’m
upcasing id in the text here just so you can see it, it should be
lower case).
You can move the “validates_” around in your file - they define
functions
that are called as appropriate they so they can be placed anywhere you
would
define a function. However it is useful to have them at the top of
the file.
And you are quite right, update_attributes does a save. Too late at
night it
Thanks, Kip, I’ll try to do all that once I get home.
Even under your suggestions, however, I still have more questions:
So, if params accepts hidden text-fields, does that mean I have to
make all fields that shouldn’t be changed to hidden? Originally, I
didn’t code any text-fields (within form_for method in the view) that
are restricted from editting.
I have a line of code that says “validates_presence_of :password”,
and I was wondering if it was safe to move this under before_create:
def before create
validates_presence_of :password
end
You say in your sample code:
if info.update_attributes(params[:data])
if info.save
…
but I thought update_attributes automatically saves for you. That’s
what it looked like in the depot web from Agile.
def edit_member
@member=Member.find(params[:id])
end
def update_member
@member=Member.find(params[:id])
if !params[:member]
flash[:notice]=nil
render :action => ‘edit_member’
elsif @member.update_attributes(params[:member])
flash[:notice]=“The member was succesfully updated!”
redirect_to(members_english_url(:controller=>@you.class.name.downcase))
else
flash[:notice]=“Failed to update this member. Please try again.”
render :action => ‘edit_member’
end
end
What’s going on? I call render, and I still don’t don’t get any
error_messages_for.
I think your issue may be that you should probably be calling
@member = Member.find(params[:member]][:id])
Remember we’re talking about two different kinds of params:
First kind is what you get from the URL when an edit is requested.
If you’re using default routes then that probably is params[:id].
But the form data comes back dependent on your form. In your case
I see that’s params[:member]. So to retrieve that row so you can
update it you need to use the id from the form. And thats
params[:member][:id].
You’re logic isn’t quite there I think either. If your Member.find
fails (as I’m guessing it is) , but you do have params[:member] -
which you do - then you’ll render “edit_member” but with no errors -
because you haven’t actually tried to validate yet. Because of
browser behaviour you’ll see the form data you previously entered, but
nothing has actually happened in your action. Take a look at my
example of an edit action above (without the save part to see what
I mean.
BTW, flash[:notice] is cleared after it is displayed so you shouldn’t
have to set it to nil.
There is no need to include information in your form that you have no
business logic need for (ID being a special case - and I’m sure you
know I’m
upcasing id in the text here just so you can see it, it should be
lower case).
I think it was you who mentioned earlier that updates_attributes
already ignores un-filled params values. So I think not showing the
field at all is more efficient for the rhtml than actually doing so.
Seeing, though, that most of the parameters I’m editting are required
by the validation of the object anyways, I think it’s safer to use you
method.
You can move the “validates_” around in your file - they define
functions
that are called as appropriate they so they can be placed anywhere you
would
define a function. However it is useful to have them at the top of
the file.
That’s what I figured. Thanks for the confirmation!
And you are quite right, update_attributes does a save. Too late at
night it
I see that’s params[:member]. So to retrieve that row so you can
flash[:notice]="The member was succesfully updated!"
redirect_to(members_english_url(:controller=>@you.class.name.downcase))
else
flash[:notice]=“Failed to update this member. Please try again.”
render :action => ‘edit_member’
end
end
What’s going on? I call render, and I still don’t don’t get any
error_messages_for.
Actually, that’s a good point. I use params[:id] because when you
first redirect into the function, that’s the only params that’s
available. Up to here everything works fine (I can tell because all
the text-fields are automatically filled for you). After the
validation fails, however, I’m not exactly sure what happens to
params[:id]. All I know is that it redirects back to the same page,
with the fields filled with values before the edit. I’ve made a debug
div tag, so I should check more thoroughly there, but as far as I
know, the system seems to recognize params[:id] is still there.
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.