Have Several questions

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.

  1. 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.

  2. 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)?

  3. 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?

  4. 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?

Thanks for the help!

Taro,

Assuming your views do have error_messages_for, then in order for
those errors to be visible on your browser you should:

  1. Edit your css to set some formatting on the field in question by
    defining
    a class :fieldWithErrors (Agile Web Dev 2 page 493)

  2. 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

  3. Model attributes are automatically read/writeable for you

  4. 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

Regards,

–Kip

Taro,

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:

<%= error_message_on(:edit, :login_name) %>
<%= form.text_field :login_name, :size => 20, :disabled => true %>

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).

  1. 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.

  2. And you are quite right, update_attributes does a save. Too late at
    night it
    :slight_smile:

Cheers, --Kip

Thanks, Kip, I’ll try to do all that once I get home.
Even under your suggestions, however, I still have more questions:

  1. 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.

  2. 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

  1. 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.

-Thanks, #2

Oh, right! and one more thing!

Here’s my typical edit function:

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.

Taro, what do you get?

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:

  1. 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].
  2. 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].
  3. 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 :slight_smile: to see what
    I mean.

BTW, flash[:notice] is cleared after it is displayed so you shouldn’t
have to set it to nil.

Cheers, --Kip

Many thanks to your post, I think I understand now.

edit it in the
form. Like so:

    <%= error_message_on(:edit, :login_name) %>
    <%= form.text_field :login_name, :size => 20, :disabled => true %>

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.

  1. 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!

  1. And you are quite right, update_attributes does a save. Too late at
    night it
    :slight_smile:

OK, no need for that save line then :-).

On Aug 8, 10:46 am, Kip [email protected] wrote:

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.