This seems like it should have been asked numerous times already, but my Google-fu isn''t strong enough to find the answer. DHH advocates separating HABTM relationships into a join model, and I need to store some metadata about the join, so this makes sense. The problem is creation order and validations. Say, you have three models, like so: class Foo < AR::Base has_many :bars, :through => :quux has_many :quuxes end class Bar < AR::Base has_many :quuxes, :dependent => :destroy has_many :foos, :through => :quuxes end class Quux < AR::Base belongs_to :foo belongs_to :bar end Foo is valid without any Bars, and a Bar may belong to multiple Foos. However, a Bar should never exist without being associated with at least one Foo. So, how would you ensure that every time a Bar is created, the proper Quux is also created, without ever leaving an opportunity for a Bar to exist without a Foo? My initial thought is that a transaction is necessary, in this order: 1) Create Bar (rollback on fail) 2) Create Quux, referencing bar.id and foo.id (rollback on fail) How do I enforce this order and maintain database integrity in the model layer? This seems silly; if there''s an obvious answer/resource I''m missing, please let me know. Thanks. -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Brandon Mitchell wrote:> This seems like it should have been asked numerous times already, but my > Google-fu isn''t strong enough to find the answer. DHH advocates > separating HABTM relationships into a join model, and I need to store > some metadata about the join, so this makes sense. The problem is > creation order and validations. > > Say, you have three models, like so: > > class Foo < AR::Base > has_many :bars, :through => :quux > has_many :quuxes > end > > class Bar < AR::Base > has_many :quuxes, :dependent => :destroy > has_many :foos, :through => :quuxes > end > > class Quux < AR::Base > belongs_to :foo > belongs_to :bar > end > > Foo is valid without any Bars, and a Bar may belong to multiple Foos. > However, a Bar should never exist without being associated with at least > one Foo. > > So, how would you ensure that every time a Bar is created, the proper > Quux is also created, without ever leaving an opportunity for a Bar to > exist without a Foo? > > My initial thought is that a transaction is necessary, in this order: > 1) Create Bar (rollback on fail) > 2) Create Quux, referencing bar.id and foo.id (rollback on fail) > > How do I enforce this order and maintain database integrity in the model > layer? > > This seems silly; if there''s an obvious answer/resource I''m missing, > please let me know. Thanks. > -- > Posted via http://www.ruby-forum.com/.This is quite simple with validations. In your Bar model you will want the following: #Validate belongs to a foo validates_presence_of :foo_id #Validates foo exists - ONLY use this if the foo object is already saved. validates_associated :foos Rails will do all the work with Quux on your behalf. --------------------------------------------------------------------------------------------------- FYI, If you do not need to directly work with the Quux model itself, you may find it tidier to use a has_and_belongs_to_many association with a join table instead of your proposed has_many :through. Like so: class Foo < AR::Base has_and_belongs_to_many :bars, :join_table => :quuxes end class Bar < AR::Base has_and_belongs_to_many :foos, :join_table => :quuxes end and have a join table called quuxes (or maybe foo_bar depending on how you like to name your join tables) with columns foo_id and bar_id --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Matt wrote:> This is quite simple with validations. In your Bar model you will want > the following: > > #Validate belongs to a foo > validates_presence_of :foo_id > #Validates foo exists - ONLY use this if the foo object is already > saved. > validates_associated :foos > > Rails will do all the work with Quux on your behalf.This is, perhaps, what I would *like* to do, but Bar does not have a foo_id. At least, Rails 2.0.2 doesn''t seem to be proxying #foo_id on Bar to #foo_id on Quux, by default. This has to be one of the most used paradigms in Rails >= 1.1, but I can''t seem to find the "conventional" method for assuring that a Bar cannot be created without an associated Foo.> FYI, If you do not need to directly work with the Quux model itself, > you may find it tidier to use a has_and_belongs_to_many association > with a join table instead of your proposed has_many :through.I do need to use a join model, rather than a join table. I have other metadata I need to store in Quux. -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
> > #Validate belongs to a foo > > validates_presence_of :foo_id > This is, perhaps, what I would *like* to do, but Bar does not have a > foo_id. At least, Rails 2.0.2 doesn''t seem to be proxying #foo_id on Bar > to #foo_id on Quux, by default.Apologies, that should be :foo_ids (plural, as it is a has_many association) and it should be managed directly by the association. It is an array of the Foo id''s associated with Bar. Updating this should be updating the quuxes table according to the associations you have set up. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Hi
The following is one solution I got to my problem
class KnowledgeBase < ActiveRecord::Base
has_many :sd_knowledge_bases
has_many :sds, :through => :sd_knowledge_bases
# (...)
end
# app/models/sd.rb
class Sd < ActiveRecord::Base
has_many :sd_knowledge_bases
has_many :knowledge_bases, :through => :sd_knowledge_bases
# # (...)
end
# app/models/sd_knowledge_base.rb
class SdKnowledgeBase < ActiveRecord::Base
belongs_to :knowledge_base
belongs_to :sd
# (...)
end
# in controller action (assuming params[:id] is the ID of your SD)
@knowledge_bases = Sd.find(params[:id]).knowledge_bases
But I get the error
uninitialized constant SD::SDKnowledgeBasis
Note Basis
My table structure as below
1)knowledge_bases
id integer not null default
nextval(''public.knowledge_bases_id_seq''::text)
name character varying(200)
keyword text
url character varying(500)
summary text
details text
2)sd_knowledge_bases
id integer not null default
nextval(''public.service_desk_knowledge_bases_id_seq
''::text)
sd_id integer
knowledge_base_id integer
Pls help
Sijo
--
Posted via http://www.ruby-forum.com/.
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---
I have the 3 tables
1)service_desk_tickets
id integer not null default
nextval(''public.service_desk_tickets_id_seq'':
:text)
number character varying(15)
title character varying(100)
service_desk_status_id integer
etc.....
2)cis
id integer not null default
nextval(''public.cis_id_seq''::text)
citype character varying(30)
ci_number character varying(15)
content_id integer
etc....
3)service_desk_cis(This is a junction table)
id integer not null default nextval(''public.service_desk_cis_id_se
q''::text)
service_desk_ticket_id integer
ci_id integer
service_desk_ci_association_type_id integer
Associations as
In service_desk_ticket.rb
has_many :service_desk_cis
has_many :cis, :through => :service_desk_cis
In ci.rb
has_many :service_desk_cis
has_many :service_desk_tickets, :through => :service_desk_cis
in service_desk_cis.rb
belongs_to :service_desk_ticket
belongs_to :ci
In controller
@sd_cis=ServiceDeskTicket.find(params[:id]).cis (This is working)
MY PROBLEM IS HOW TO GET service_desk_ci_association_type_id
Please help
Sijo
--
Posted via http://www.ruby-forum.com/.
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---
Hi,
The implementation of has_many and belongs_to association is only not
enough to join two taIf u have implement two tables..And also u use the
following query
@sd_cis=ServiceDeskTicket.find(params[:id], :include
[:service_desk_cis])
and u retrieve the field of ServiceDeskTicket table as
@sd_cis.id
and u retrieve the field of Service_desk_cis table as
@sd_cis.service_desk_cis.service_desk_ci_association_type_id
On Feb 18, 2008 1:13 PM, Sijo Kg
<rails-mailing-list-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:
>
> I have the 3 tables
>
> 1)service_desk_tickets
>
> id integer not null default
> nextval(''public.service_desk_tickets_id_seq'':
> :text)
> number character varying(15)
> title character varying(100)
> service_desk_status_id integer
> etc.....
>
> 2)cis
>
> id integer not null default
nextval(''public.cis_id_seq''::text)
> citype character varying(30)
> ci_number character varying(15)
> content_id integer
> etc....
>
> 3)service_desk_cis(This is a junction table)
>
> id integer not null default
nextval(''public.service_desk_cis_id_se
> q''::text)
> service_desk_ticket_id integer
> ci_id integer
> service_desk_ci_association_type_id integer
>
> Associations as
> In service_desk_ticket.rb
>
> has_many :service_desk_cis
> has_many :cis, :through => :service_desk_cis
>
> In ci.rb
> has_many :service_desk_cis
> has_many :service_desk_tickets, :through => :service_desk_cis
>
> in service_desk_cis.rb
>
> belongs_to :service_desk_ticket
> belongs_to :ci
>
> In controller
> @sd_cis=ServiceDeskTicket.find(params[:id]).cis (This is working)
>
> MY PROBLEM IS HOW TO GET service_desk_ci_association_type_id
>
> Please help
> Sijo
> --
> Posted via http://www.ruby-forum.com/.
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---
I did
in controller
@sd_cis=ServiceDeskTicket.find(params[:id], :include =>
[:service_desk_cis]).cis
And in view
<% 0.upto(@sd_cis.length-1) do |loop_index| %>
<td><%=CiStatus.find(@sd_cis[loop_index].content.ci_status_id).name%></td>
<td><%=@sd_cis[loop_index].ci_number%></td>
<td><%=CiType.find(@sd_cis[loop_index].citype).name%></td>
<td><%=@sd_cis[loop_index].content.name%></td>
<td><%=CiClass.find(@sd_cis[loop_index].content.ci_class).name%></td>
<td><%=
@sd_cis[loop_index].service_desk_cis.service_desk_ci_association_type_id
%></td>
<% end %>
If I comment last line(@sd_cis[loop_index.....)No error everything
ok.But if uncomment it I get the error
undefined method `service_desk_ci_association_type_id'' for
ServiceDeskCi:Class
Sijo
--
Posted via http://www.ruby-forum.com/.
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---
Hi,
U may try this type of for loop tag to display the contents....
<% for sd_cis in @sd_cis %>
<%= sd_cis.service_desk_cis.service_desk_ci_association_type_id %>
<% end %>
I think i should helpful to u...
On Feb 18, 2008 3:34 PM, Sijo Kg
<rails-mailing-list-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:
>
> I did
> in controller
>
> @sd_cis=ServiceDeskTicket.find(params[:id], :include =>
> [:service_desk_cis]).cis
>
> And in view
>
> <% 0.upto(@sd_cis.length-1) do |loop_index| %>
>
> <td><%=CiStatus.find
> (@sd_cis[loop_index].content.ci_status_id).name%></td>
> <td><%=@sd_cis[loop_index].ci_number%></td>
>
<td><%=CiType.find(@sd_cis[loop_index].citype).name%></td>
> <td><%=@sd_cis[loop_index].content.name%></td>
>
<td><%=CiClass.find(@sd_cis[loop_index].content.ci_class).name%></td>
> <td><%>
@sd_cis[loop_index].service_desk_cis.service_desk_ci_association_type_id
> %></td>
>
>
> <% end %>
>
> If I comment last line(@sd_cis[loop_index.....)No error everything
> ok.But if uncomment it I get the error
> undefined method `service_desk_ci_association_type_id'' for
> ServiceDeskCi:Class
>
> Sijo
> --
> Posted via http://www.ruby-forum.com/.
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---
Did you create foreign key in your migration when you created service_desk_cis to its related table ? -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Migration file is
class CreateServiceDeskCis < ActiveRecord::Migration
def self.up
create_table :service_desk_cis do |t|
t.column :service_desk_ticket_id, :integer
t.column :ci_id, :integer
t.column :service_desk_ci_association_type_id, :integer
t.column :created_by, :integer
t.column :modified_by, :integer
t.column :created_on, :datetime, :null=>false
t.column :created_at, :datetime, :null=>false
t.column :updated_on, :datetime, :null=>false
t.column :updated_at, :datetime, :null=>false
end
end
def self.down
drop_table :service_desk_cis
end
end
--
Posted via http://www.ruby-forum.com/.
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---
I see your migration file. you dont have foreign key to link them in
database, you should add like this in your new migration :
execute ''ALTER TABLE service_desk_cis ADD CONSTRAINT
fk_service_desk_cis
FOREIGN KEY (service_desk_status_id) REFERENCES
service_desk_tickets(id)''
I hope it will works.
--
Posted via http://www.ruby-forum.com/.
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---
Sorry this is the correct one :
execute ''ALTER TABLE service_desk_cis ADD CONSTRAINT
fk_service_desk_cis
FOREIGN KEY (service_desk_ticket_id ) REFERENCES
service_desk_tickets(id)''
I hope it will work.
----
website: http://teapoci.blogspot.com
YM : booking2heaven
--
Posted via http://www.ruby-forum.com/.
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---
The servicedeskticket migration was
class CreateServiceDeskTickets < ActiveRecord::Migration
def self.up
create_table :service_desk_tickets do |t|
t.column :number, :string, :limit=>15
t.column :title, :string, :limit=>100
t.column :status, :integer
t.column :category, :integer
t.column :sub_category, :integer
t.column :primary_assignee_group, :string, :limit=>50
t.column :impact, :integer
t.column :urgency, :integer
t.column :priority, :integer
t.column :resolved, :boolean, :default=>false
t.column :description, :string, :limit=>100
end
end
def self.down
drop_table :service_desk_tickets
end
end
In the controller
@sd_ticket=ServiceDeskTicket.find(params[:id])
@sd_ticket.service_desk_cis.each do |t|
puts t.service_desk_ci_association_type_id
end
This worked..What may be the differnce?
--
Posted via http://www.ruby-forum.com/.
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---
sorry, my internet was down. the difference is : -- YOUR PROBLEM HERE --- @sd_cis=ServiceDeskTicket.find(params[:id], :include =>[:service_desk_cis]).cis -- YOUR WORKING TEST SCRIPT --- @sd_ticket=ServiceDeskTicket.find(params[:id]) it''s quite difference. Please run it : @testcis = Ci.find(params[:id]) @testcis.service_desk_cis.service_desk_ticket_id I need to know what it works or no. if it is not working, it means that your cis can not be linked to service_desk_cis, so you can try to add foreign key there. -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Thanks for your reply..It worked like @servicedesk_cis_join = @sd_ticket.service_desk_cis @sd_cis = @servicedesk_cis_join.map(&:ci) @sd_cis_association_type_ids = servicedesk_cis_join.map(&:service_desk_ci_association_type_id) And in view <%= @sd_cis_association_type_ids[loop_index] %> -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---