I am building an app to allow clients to create a project and fill out a survey. There are also contractors and hiring_managers associated with the project. Below are the models: class User < ActiveRecord::Base has_many :projects_as_client, :class_name=> ''Project'', :foreign_key => ''client_id'' has_many :projects_as_contractor, :class_name=> ''Project'', :foreign_key => ''contractor_id'' has_many :projects_as_hiring_manager, :class_name=> ''Project'', :foreign_key => ''hiring_manager_id'' end class Project < ActiveRecord::Base belongs_to :client, :class_name => ''User'', :foreign_key => ''client_id'' belongs_to :contractor, :class_name => ''User'', :foreign_key => ''contractor_id'' belongs_to :hiring_manager, :class_name => ''User'', :foreign_key => ''hiring_manager_id'' When I create the project, I may also be creating a contractor and hiring_manager, etc. What is the best way to handle this? I read about using something like this: @project=Project.new(params[:user]) @project.contractor = @project.contractor.build(params[:user]) Unfortunately, that also gives me an Unknown Method error. A friend suggested using a transaction block so that if there is an error, all saves/updates would be rolled back. Thanks in advance from a newbie! --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Dcjgoose wrote:> class User < ActiveRecord::Base > has_many :projects_as_client, :class_name=> > ''Project'', :foreign_key => ''client_id'' > has_many :projects_as_contractor, :class_name=> > ''Project'', :foreign_key => ''contractor_id'' > has_many :projects_as_hiring_manager, :class_name=> > ''Project'', :foreign_key => ''hiring_manager_id'' > end > > class Project < ActiveRecord::Base > belongs_to :client, :class_name => ''User'', :foreign_key => > ''client_id'' > belongs_to :contractor, :class_name => ''User'', :foreign_key => > ''contractor_id'' > belongs_to :hiring_manager, :class_name => ''User'', :foreign_key > => ''hiring_manager_id'' > > > When I create the project, I may also be creating a contractor and > hiring_manager, etc. What is the best way to handle this? I read about > using something like this: > > @project=Project.new(params[:user]) > @project.contractor = @project.contractor.build(params[:user]) > > Unfortunately, that also gives me an Unknown Method error. A friend > suggested using a transaction block so that if there is an error, all > saves/updates would be rolled back.It''s best not to rely on rollback, both for efficiency and in case the DB doesn''t support transactions or suitable transaction isolation. Correct way to write the above line is @project.contractor = @project.build_contractor(params[:user]) Just ensure everything is validated before anything is saved. -- We develop, watch us RoR, in numbers too big to ignore. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On 8/17/07, Mark Reginald James <mrj@bigpond.net.au> wrote:> > Dcjgoose wrote: > > > [...] A friend > > suggested using a transaction block so that if there is an error, all > > saves/updates would be rolled back. > > It's best not to rely on rollback, both for efficiency and in case > the DB doesn't support transactions or suitable transaction isolation. >I'm sorry, but this is shitty advice. Transactions are the only way to avoid partial updates. They also make your program flow a lot simpler than trying to without them (which doesn't really work anyway). Any db worth using supports transactions, and performance tends to be worse in auto-commit mode, when every single statement is run as a separate transaction, instead of bulking all writes into a single commit. Granted, the most popular 'database', mysql, takes a bit of know-how and reconfiguration to support transactions andact somewhat well-behaved. I recommend PostgreSQL instead; not only is it superior in every respect, but also easier to get started with..! Isak --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk@googlegroups.com To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Just to reiterate the point I wrote a lot of code for MySQL before it hadd InnoDB support that looked like the following psuedo code: exec_sql "Insert into table1 values (''a'', ''b'', ''c'') my_id = exec_sql "select last_id from db" exec_sql "Insert into table2 values (my_id, 1, 2, 3) next_id = exec_sql "select last_id from db" if $previous_query_error exec_sql("Delete from table1 where id = $my_id") else exec_sql insert into table3 values (next_id, ''done'') if $previous_query_error exec_sql("Delete from table2 where id = $next_id") exec_sql("Delete from table1 where id = $my_id") end end This is what you are forced to do without transactions. That kind of code adds no value to your application. And it works assuming that there isn''t a problem executing the clean-up code and orphaned child records are left around. In addition transactions can improve performance. If you are inserting/updating multiple records the writing to the database is essentially (at the 30,000 foot level) postponed until the end of the transaction. That''s why tools like Oracle data loader allow you to specify transaction batch sizes, to optimize the speed of the load against the space/memory available for transactions. MySQL PostgreSQL SQL Server Oracle Sybase All support transactions, and they cover the vast majority of the DB market. The difficulty comes when you''re using something that doesn''t support rollback, like a LDAP server. In which case you are still required to write clean-up code. On Aug 17, 2007, at 8:28 AM, Isak Hansen wrote:> On 8/17/07, Mark Reginald James <mrj-bzGI/hKkdgQnC9Muvcwxkw@public.gmane.org> wrote: >> >> Dcjgoose wrote: >> >>> [...] A friend >>> suggested using a transaction block so that if there is an error, >>> all >>> saves/updates would be rolled back. >> >> It''s best not to rely on rollback, both for efficiency and in case >> the DB doesn''t support transactions or suitable transaction >> isolation. >> > > I''m sorry, but this is shitty advice. > > Transactions are the only way to avoid partial updates. They also make > your program flow a lot simpler than trying to without them (which > doesn''t really work anyway). > > Any db worth using supports transactions, and performance tends to be > worse in auto-commit mode, when every single statement is run as a > separate transaction, instead of bulking all writes into a single > commit. > > Granted, the most popular ''database'', mysql, takes a bit of know-how > and reconfiguration to support transactions and act somewhat > well-behaved. > I recommend PostgreSQL instead; not only is it superior in every > respect, but also easier to get started with..! > > > Isak > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Isak Hansen wrote:> Transactions are the only way to avoid partial updates. They also make > your program flow a lot simpler than trying to without them (which > doesn''t really work anyway).A transaction block should always be used when an action saves multiple objects so that save errors unrelated to validation do not result in partial inserts/updates on DBs that support transactions. Indeed Rails automatically wraps saves of associated objects in transactions. But it''s not that hard to validate everything before saving anything, avoiding the latency of all those useless database calls, reducing server load and returning error messages to the user much faster. -- We develop, watch us RoR, in numbers too big to ignore. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---