Ruby Forum Ruby on Rails > ActiveRecord::Base.new

Posted by pepe (Guest)
on 07.05.2008 06:14
(Received via mailing list)
I am new to RoR (new to both Ruby and Rails) and am creating a test
'wizard' that allows to enter information for an employee through
several pages. Only when reaching the last one and passing all
validations through all the pages a row should be created in the
table; however I've found that when I issue 'Employee.new' a row is
automatically created EVERY TIME and whenever I press enter on any of
the pages the page's data gets automatically transferred to the newly
created row with no 'save' or 'create' operation being executed on my
part.

This causes trouble for a couple of reasons:
1. It is not the desired behavior.
2. All automatically created rows stay in the table, regardless if I
save them or not. Some of them empty and others partially filled with
information.

The database is MySQL in case it makes a difference.

Does anybody know what could be going on? And most importantly how I
can make it work the way I need it to work?

Thanks a lot to everybody.
Posted by Ryan Bigg (ryan-bigg)
on 07.05.2008 07:18
(Received via mailing list)
Calling new on a model will not enter rows into the table. You are 
somewhere
calling either save on that object or skipping new and calling create.

Pastie your model please.

On Wed, May 7, 2008 at 1:36 PM, pepe <Pepe@betterrpg.com> wrote:

>
>
> Thanks a lot to everybody.
>
> >
>


--
Ryan Bigg
http://www.frozenplague.net
Feel free to add me to MSN and/or GTalk as this email.
Posted by Amos King (Guest)
on 07.05.2008 21:12
(Received via mailing list)
This may help you out.

http://github.com/Adkron/actsaswizard/tree/master

It is a plugin for creating wizards.

Amos

On Tue, May 6, 2008 at 11:06 PM, pepe <Pepe@betterrpg.com> wrote:
>
>
>  Thanks a lot to everybody.
>
>  >
>



--
Amos King
A. King Software Development and Consulting, L.C.
http://dirtyInformation.com
--
Looking for something to do? Visit http://ImThere.com
Posted by pepe (Guest)
on 07.05.2008 22:14
(Received via mailing list)
Hi Ryan.

Thanks for taking an interest on this. I am only using 'save' on the
last page's action method in the controller (4 pages: name, address,
phones and save; page 'save' has a button to invoke 'new', which just
redirects to 'name'). There is no use of 'create' anywhere in the
model, the controller or the view. I created some validation methods
in the model because that's where they are supposed to be but seeing
what was happening I took them out and put the validations in the
controller to see if somehow the model was using functionality I
didn't know it might have that would post the data to the row whenever
a method is invoked (just trying to guess). The problem persists.
Below is the full controller's code and the model is now empty. The
table was created with a migration so in addition to the fields in the
validation methods there is the 'id' field in it. Thanks again for
helping:

class EmployeesController < ApplicationController
  def name
    get_employee
    flash[:employee] = @employee
  end

  def address
    validate 'name'
  end

  def phones
    validate 'address'
  end

  def save
    validate 'phones'
    return if !@employee.errors.empty?
    @employee.save
  end

  def new
    flash[:employee] = Employee.new
    redirect_to :action => :name
  end

  private
  def validate( action_name )
    get_employee
    if @employee.errors.empty?
      update_employee
      if action_name == 'name'
        #@employee.validate_name
        validate_name
      elsif action_name == 'address'
        #@employee.validate_address
        validate_address
      elsif action_name == 'phones'
        #@employee.validate_phones
        validate_phones
      end
      redirect_to :action => action_name.to_sym if !
@employee.errors.empty?
    end

    flash[:employee] = @employee
  end # def validate( method_name )

  def get_employee
    @employee = flash[:employee] ||= Employee.new
  end

  def update_employee
    @employee.update_attributes(params[:employee])
  end

  def validate_name
    @employee.errors.clear
    @employee.errors.add(:first, 'Please enter first name.') unless !
@employee.first.nil? && @employee.first != ''
    @employee.errors.add(:last, 'Please enter last name.') unless !
@employee.last.nil? && @employee.last != ''
    @employee.errors.add(:identification, 'Please enter
identification.') unless !@employee.identification.nil? &&
@employee.identification != ''
  end

  def validate_address
    @employee.errors.clear
    @employee.errors.add(:street, 'Please enter street.') unless !
@employee.street.nil? && @employee.street != ''
    @employee.errors.add(:city, 'Please enter city.') unless !
@employee.city.nil? && @employee.city != ''
    @employee.errors.add(:state, 'Please enter state.') unless !
@employee.state.nil? && @employee.state != ''
    @employee.errors.add(:zip, 'Please enter zip code.') unless !
@employee.zip.nil? && @employee.zip != ''
  end

  def validate_phones
    @employee.errors.clear
    @employee.errors.add(:phone, 'Please enter phone number.') unless !
@employee.phone.nil? && @employee.phone != ''
    @employee.errors.add(:cell, 'Please enter cell number.') unless !
@employee.cell.nil? && @employee.cell != ''
  end

end


On May 7, 1:17 am, "Ryan Bigg (Radar)" <radarliste...@gmail.com>
Posted by Andrew Skegg (askegg)
on 07.05.2008 22:28
pepe wrote:

>   def validate( action_name )
>     get_employee
>     if @employee.errors.empty?
>       update_employee
>       if action_name == 'name'
>         #@employee.validate_name
>         validate_name
>       elsif action_name == 'address'
>         #@employee.validate_address
>         validate_address
>       elsif action_name == 'phones'
>         #@employee.validate_phones
>         validate_phones
>       end
>       redirect_to :action => action_name.to_sym if !
> @employee.errors.empty?
>     end
> 
>  def update_employee
>    @employee.update_attributes(params[:employee])
>  end

Your issue here is the update_attributes method in your validations. 
According to the rails docs:
Updates all the attributes from the passed-in Hash and saves the record.

Andrew
Posted by Andrew Skegg (askegg)
on 07.05.2008 22:37
BTW - validations really belong in the model rather than the controller.
Posted by pepe (Guest)
on 08.05.2008 01:14
(Received via mailing list)
Thanks!

I guess I've been too busy trying to learn RoR and at the same time
make the code work. I didn't even think that the method would save the
data and just got it from a sample out of a book as a quick and easy
way to update all attributes from the form.

I owe you a beer. :)

On May 7, 4:28 pm, Andrew Skegg <rails-mailing-l...@andreas-s.net>
Posted by Andrew Skegg (askegg)
on 08.05.2008 03:20
pepe wrote:
> Thanks!
> 
> I guess I've been too busy trying to learn RoR and at the same time
> make the code work. I didn't even think that the method would save the
> data and just got it from a sample out of a book as a quick and easy
> way to update all attributes from the form.
> 
> I owe you a beer. :)
> 
> On May 7, 4:28 pm, Andrew Skegg <rails-mailing-l...@andreas-s.net>

You're welcome :)

If you wish to continue using your controllers to do the validations (I 
strongly suggest you don't), then you might want to investigate the 
merge and reverse_merge functions.

Oh - and I drink almost any beer :)
Posted by Andrew Skegg (askegg)
on 08.05.2008 03:25
pepe wrote:
> Thanks!
> 
> I guess I've been too busy trying to learn RoR and at the same time
> make the code work. I didn't even think that the method would save the
> data and just got it from a sample out of a book as a quick and easy
> way to update all attributes from the form.
> 
> I owe you a beer. :)
> 
> On May 7, 4:28 pm, Andrew Skegg <rails-mailing-l...@andreas-s.net>

I really should think about what I want to say before I start typing.  I 
meant to include some pointers on moving validations into the model.

Let's take your code:
def validate_address
    @employee.errors.clear
    @employee.errors.add(:street, 'Please enter street.') unless !
@employee.street.nil? && @employee.street != ''
    @employee.errors.add(:city, 'Please enter city.') unless !
@employee.city.nil? && @employee.city != ''
    @employee.errors.add(:state, 'Please enter state.') unless !
@employee.state.nil? && @employee.state != ''
    @employee.errors.add(:zip, 'Please enter zip code.') unless !
@employee.zip.nil? && @employee.zip != ''
  end

If we move this validation into the Employee model it might look like 
this:

class Employee < ActiveRecord::Base
  validates_presence_of :street, :city, state, :zip
end

See how much cleaner that is?  It has the added benefit of enforcing 
these validations for the employee no matter which controller is using 
them (in your current configuration you will be repeating yourself all 
over the place).

Andrew