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: