Appending a record to a table

Hi

I'm not too sure how best to explain this but here goes!

I am trying to write an appointment system. I have, through example,
just about got the dynamics correct. Even tried to play with some
table joins (and excuse me if I've used the incorrect terminlogy). But
no matter what I try I can't seem to get the following code to work.

I have a cart filled with Treatment id's. I have a LineItem model set
up as follows:

class LineItem < ActiveRecord::Base
  belongs_to :appointment
  belongs_to :customer
  belongs_to :therapist
  belongs_to :treatment
end

I have worked out enough to be able to create a new LineItem record.
I have populated it with appointment, customer and therapist data. But
I cannot seem to get the treatment information from the cart into the
LineItem record.

Any ideas?

My code is as follows. I keep coming across this idea of using << but
none of the literature I'm reading makes a huge deal of sense.

    @cart = find_treat
    l = LineItem.new

    c = Customer.find(session[:currentcustID])
    t = Therapist.find(params[:appt_therapist])

    a = Appointment.new
    a.appdate = params[:appt_date]
    a.apptime = params[:appt_time]
    a.applength = @cart.total_time
    a.customer = c

    l.appointment = a
    l.customer = c
    l.therapist = t

    tr = Treatment.new

    @cart.items.each do |item|
      tr = Treatment.find(item.id)
      logger.warn("Currently Dealing with: #{tr.desclong}")
      l.treatment << tr
    end

    #l.save

I keep getting variations of the following error message:

NoMethodError (You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.<<):

Thanks in advance for any help you might be able to give.

Darren

Could you post your Treatment model here? It may clarify the
situation.
LineItem belongs_to :treatment - I guess, something is wrong here.
Maybe it should be
LineItem has_many :treatments?
Because you are trying to assign multiple treatments to one LineItem.

tr = Treatment.new

There is no need for this line. You create new objects with find. If nothing is found, nil is returned

    @cart.items.each do |item|
      tr = Treatment.find(item.id)
      logger.warn("Currently Dealing with: #{tr.desclong}")
      l.treatment << tr
    end

tr is nil somehow. I'll code this as:

@cart.items.each do |item|
   if Treatment.find(item.id)
      logger.warn("Currently Dealing with: #{tr.desclong}")
      l.treatment << tr
   end
end

However, you are assigning multiple tr to l, and you declared a belongs_to relationship.

Hope it helps.

Regards,
Jorge Corona.

On Sep 2, 2:27 pm, "Ruby on Rails: Talk" <dazzaroo...@gmail.com>
wrote:

The value for l.treatment is what is nil, and if does not respond to
the << operator. And that appears to be caused by some confusion in
your data model.

In your LineItem class, you say:
  belongs_to :treatment

So you need to use treatment the same way you are using appointment,
customer and therapist (which also use the belong_to relationship):
  l.treatment = tr
And you can only store one treatment at a time in the database. Each
assignment overwrites the previous one, so you need to create a new
LineItem for every Treatment you want to save.

On the other, if what you really want is to have multiple treatments
per line item, then you need to say this in your LineItem class:
  has_many :treatments
And this in your Treatment class:
  belongs_to :line_item

and then you can use the append operation in your loop, though you
will need to use the plural form:
  l.treatments << tr

First you have to decide what the correct database table relationships
are. There might be good reasons to do it either way.

On Sep 2, 12:27 pm, "Ruby on Rails: Talk" <dazzaroo...@gmail.com>
wrote:

Hi again

OK. I've decided my fundamental problem here is a lack of
understanding about models. I have enough to get my started by getting
lost quickly.

So, following all your advice I have redone my models as such:

class Appointment < ActiveRecord::Base
  has_many :line_items
  belongs_to :customer
end

class Customer < ActiveRecord::Base
  has_many :line_items
  has_many :appointment
end

class LineItem < ActiveRecord::Base
  belongs_to :appointment
  belongs_to :customer
  belongs_to :therapist
  has_many :treatlines
end

class Therapist < ActiveRecord::Base
  has_many :line_items
end

class Treatment < ActiveRecord::Base
  has_many :treatlines
end

class Treatline < ActiveRecord::Base
  belongs_to :line_item
  belongs_to :treatment
end

I have updated my code to try and save the information I need to the
following:

  def book_appointment
    # Need to write this to take in the date from the date and time
boxes and then put it with all the rest of the information
    # to make the appointment
    # Create new appointment
    @cart = find_treat
    # Setup data column for the appointment
    l = LineItem.new

    c = Customer.find(session[:currentcustID])
    t = Therapist.find(params[:appt_therapist])
    # Add a new appointment
    a = Appointment.new
    a.appdate = params[:appt_date]
    a.apptime = params[:appt_time]
    a.applength = @cart.total_time
    a.customer = c

    l.appointment = a
    l.customer = c
    l.therapist = t
    # Need to work out how to add treatments to this massive list!
Refer back to book!
    @cart.items.each do |item|
       if Treatment.find(item.id)
         tr = Treatline.new
         tr.treatment = Treatment.find(item.id)
         logger.warn("Treatment desclong is:
#{tr.treatment.desclong}")
         l.treatlines << tr
       end
    end
    l.save

  end

But I'm now getting the following error message:

ActiveRecord::StatementInvalid (Mysql::Error: Column 'treatline_id'
cannot be null: INSERT INTO `line_items` (`updated_at`,
`therapist_id`, `treatline_id`, `customer_id`, `appointment_id`,
`created_at`) VALUES('2008-09-03 15:00:06', 2, NULL, 2, 8, '2008-09-03
15:00:06')):

I felt it would be better to, for each line item, keep the treatments
that each customer has in a seperate table. Hence I've now created a
table called treatline. This table would, in turn, reference the
master treatments table which holds all the treatments on offer. But I
have no idea who to get the line_items table to hold the id for all
the treatlines I am associating with an order. If that makes sense
(and it sure doesn't seem to be making much sense to me at the
moment!).

It's like being sat with a present. I think I have the tools to get
inside the wrapping, but I just can't find the scissors. I know my
misunderstanding of models is at fault here so any help in clearing
the fog and getting this to save an appointment would be great. I hate
only having half the knowledge! It's driving me to drink!

Thanks in advance

Darren

Thought it might also be important to put the LineItems model set up
in as well?

class CreateLineItems < ActiveRecord::Migration
  def self.up
    create_table :line_items do |t|
      t.column :treatline_id, :integer, :null => false
      t.column :customer_id, :integer, :null => false
      t.column :therapist_id, :integer, :null => false
      t.column :appointment_id, :integer, :null => false
      t.timestamps
    end

    execute "alter table line_items add constraint
fk_line_item_treatlines foreign key (treatline_id) references
treatlines(id)"
    execute "alter table line_items add constraint
fk_line_item_customers foreign key (customer_id) references
customers(id)"
    execute "alter table line_items add constraint
fk_line_item_therapists foreign key (therapist_id) references
therapists(id)"
    execute "alter table line_items add constraint
fk_line_item_appointments foreign key (appointment_id) references
appointments(id)"
    execute "alter table treatlines add constraint
fk_treatline_line_items foreign key (line_item_id) references
line_items(id)"
  end

  def self.down
    drop_table :line_items
  end
end

And treatlines?

class CreateTreatlines < ActiveRecord::Migration
  def self.up
    create_table :treatlines do |t|
      t.column :treatment_id, :integer, :null => false
      t.column :line_item_id, :integer, :null => false
      t.timestamps
    end
    execute "alter table treatlines add constraint
fk_treatline_treatments foreign key (treatment_id) references
treatments(id)"

  end

  def self.down
    drop_table :treatlines
  end
end

Thanks

Darren

On Sep 3, 3:04 pm, "Ruby on Rails: Talk" <dazzaroo...@gmail.com>
wrote: