petehamilton / citier

CITIER (Class Inheritance & Table Inheritance Embeddings for Rails) is a solution for simple Multiple Class Inheritance in Rails.
88 stars 24 forks source link

parent.save failing #8

Closed ghost closed 13 years ago

ghost commented 13 years ago

Not sure what's going on here... I have a simple Patient < User setup. Could be handled by STI, but I wanted to get acquainted with MTI. After correctly implementing citier (I'm pretty sure), nothing happens--the save fails. When creating a new Patient in rails c, I tried using p.save! to get a full error report:

p.save! ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'view_patients.email' in 'where clause': SELECT 1 FROM users WHERE (view_patients.email = BINARY 'hello@soup.com') LIMIT 1

This occurs on line 19 of file 'child_instance_methods.rb' of the plugin in citier-0.1.11/lib/citier. When it tries to save the parent part of the instance into the Users table it tries to look at the view_patients file within the query. I can't pinpoint where the SQL is being generated in the plug in, and I doubt I could change it if I knew. Unfortunately there is no support forum for citer outside of these 4 Issues on the github page, so I'm coming here to try and figure out what's going on.

This may be an issue with mysql2 in particular--in browsing the resolved issues I noticed you hadn't dealt with it much.

petehamilton commented 13 years ago

Hi,

There isn't currently a forum but maybe I should make one, At the moment it is really just me developing this and and so I don't know what the participation would be like? The github issues is just an easier way to manage problems for me right now. Can you please post your models and migrations code please? It looks like you are right and it is mixing up the tables and their columns but I need to be able to replicate. Anonymise any confidential or private code information or variables.

ghost commented 13 years ago

Of course!

#Models
##################
class User < ActiveRecord::Base
  acts_as_citier

  attr_accessible :email, :password, :password_confirmation, :about, :activate_token, :created_at, :password_hash, :password_salt, :updated_at

  attr_accessor :password

  def self.authenticate(email, password)
    user = find_by_email(email)
   if user && BCrypt::Password.new(user.password_hash) == password
      user
    else
      nil
    end
  end
end
##################
class Patient < User
  acts_as_citier
end
##################

#Migrations
##################
class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      t.string :type
      t.string :email
      t.string :password_hash
      t.string :password_salt
      t.boolean :activated
      t.string :activate_token

      t.timestamps
    end
  end

  def self.down
    drop_table :users
  end
end
##################
class CreatePatients < ActiveRecord::Migration
  def self.up
    create_table :patients do |t|
      t.boolean :is_checked_in
      t.datetime :check_in_time
      t.datetime :check_out_time

      #t.timestamps
    end
    create_citier_view(Patient)
  end

  def self.down
    drop_citier_view(Patient)
    drop_table :patients
  end
end
##################
ghost commented 13 years ago

I've pinpointed this down to the attr functions in the model, it now generates the same issues in both mysql2 and sqlite3:

p.save! ActiveRecord::StatementInvalid: Mysql2::Error: Can not modify more than one base table through a join view 'development.view_patients': INSERT INTO view_patients (type, email, password_hash, password_salt, activated, activate_token, name, avatar, dob, about, created_at, updated_at, is_checked_in, check_in_time, check_out_time, hospital_id, condition_id, blog_id) VALUES ('Patient', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2011-05-21 18:29:22', '2011-05-21 18:29:22', NULL, NULL, NULL, NULL, NULL, NULL)

I don't know anything about view tables, so I'm lost.

petehamilton commented 13 years ago

Hi,

What is the code you run before? To set up and save the model?

Also which versions of Ruby & Rails are you running? About to have a look at this in depth.

petehamilton commented 13 years ago

Ok, so it appears this is because I have implemented 'save' but not 'save!' I need to add it, if you run mypatient.save it should work fine And also mypatient.valid? also works as does mypatient.errors

It's only when you do mypatient.save!

petehamilton commented 13 years ago

Have done a simple fix which does a vlidation check and if that succeeds it continues to save correctly, otherwise it throws an RecordInvalid exception. Update to v0.1.12

ghost commented 13 years ago

Hmm, some strange stuff is still afoot with patient.save. The company repo is private but I threw what I've got up right now into my dropbox at http://dl.dropbox.com/u/24677548/Heartwaves.zip. Bout to hit up lunch.

petehamilton commented 13 years ago

What code are you running? As in what are you trying to actually save? Just an empty object?

ghost commented 13 years ago

Both null and full.

petehamilton commented 13 years ago

Hmmm I can't replicate, I just get this:

ruby-1.9.2-p180 :001 > u = Patient.new(:email=>"a@b.c")
citier -> Root Class
citier -> table_name -> users
citier -> Non Root Class
citier -> table_name -> patients
citier -> tablename (view) -> view_patients
 => #<Patient id: nil, type: "Patient", email: "a@b.c", password_hash: nil, password_salt: nil, activated: nil, activate_token: nil, created_at: nil, updated_at: nil, is_checked
_in: nil, check_in_time: nil, check_out_time: nil> 
ruby-1.9.2-p180 :002 > u.save!
citier -> Attributes for Patient: {"check_in_time"=>nil, "check_out_time"=>nil, "is_checked_in"=>nil}
citier -> UPDATE users SET type = 'User' WHERE id = 4
citier -> SQL : UPDATE users SET type = 'Patient' WHERE id = 4
 => true 
ghost commented 13 years ago

No, it works now--sshing into my server over lunch was misleading. Thank you for developing this awesome and powerful plugin, and for being so responsive!

petehamilton commented 13 years ago

No worries! Keep me updated on any other issues, I am about to start two large projects and this will be a core component so there will no doubt be a lot more development over the next few days/weeks

mbessieres commented 12 years ago

I'm still getting this error and I'm really not sure why. I've done all of your standard setup, but when I do save or save! it still causes:

Can not modify more than one base table through a join view

I'm on the latest rails, cities, mysql2

mbessieres commented 12 years ago

And I'll add that in postgre it complains as well:

ERROR: cannot update a view HINT: You need an unconditional ON UPDATE DO INSTEAD rule. : UPDATE "view_writing_assignments" SET "id" = 12, "heading" = 'This is a new writing assignment', "type" = 'WritingAssignment', "prompt" = 'Will it work? please please please?' WHERE "view_writing_assignments"."type" IN ('WritingAssignment') AND "view_writing_assignments"."id" = 12