Has_many through form - ruby

I am hoping for some help with constructing a form a has_many :through relationship.
I have three classes:
order.rb
has_many :selections
has_many :items, :through =>:selections;
item.rb
has_many :selections
has_many :orders, :through => :selections
selection.rb
belongs_to :order
belongs_to :item
Selections has an extra property on it to capture the quantity of the selected item.
What I'm trying to do is create a form that allows a user check a box indicating the type of item they want and supply a quantity.
_X_ Food1 _6_
___ Food2 __
_X_ Food3 _1_
My problem is that I don't have any idea how to name the form elements so that they make it into the controller. I can't use
<%= collection_check_boxes(:order, :item_ids, #course.items.all, :id, :name, {:item_wrapper_class => 'checkbox_container'}) %>
because that will just print the food with checkboxes and I need to capture the quantity for each selected item.
What I could use help with is how to create the _form.html.erb as well as special gotcha's that I might need to have in my controller.

First off, item.rb should read,
has_many :selections
has_many :orders, :through => :selections
Secondly, why are you using a check box? Why not just forms that if empty default to zero or nil? That is, if you have more than one, you can use it as a truthy value in lieu of a check being checked or not.

Related

database schema for like entities that can be combined pairwise (ActiveRecord)

I am designing a database of woodwind instrument sounds, and would like to create a table that joins pairs of sounds that a performer can combine into, for example, a trill. Such relations are transitive: if sound A has a 'Sound Relation' with sound B, then sound B has that same 'Sound Relation' with sound A.
I am familiar with join tables, but I've never seen them used to join 'like' objects, only to join 'unlike' objects, such as tags and posts, so I'm wary of going that direction.
I realize the example below looks extremely dubious, but it gives an idea of what I'm after. What is a better way of doing it? (Using ActiveRecord syntax)
Models
class Sound < ActiveRecord::Base
has_many :linked_sounds, through: :sound_relations, class_name: "Sound", foreign_key: ???
end
class Sound_Relation < ActiveRecord::Base
has_many :sounds
end
Migration
class CreateSoundRelations < ActiveRecord::Migration
def change
create_table :sound_relations do |t|
t.integer first_sound_id # This cannot possibly be right.
t.integer second_sound_id # Surely the transitivity of the
# relationship should be more evident?
end
end
end
You might try something like:
class Set < ActiveRecord::Base
has_many :sound_sets
has_many :sounds, :through => :sound_sets
end
class SoundSet < ActiveRecord::Base
belongs_to :sound
belongs_to :set
end
class Sound < ActiveRecord::Base
has_many :sound_sets
has_many :sets , :through => :sound_sets
has_many :set_sound_sets, :through => :sets , :source => :sound_sets
has_many :set_sounds , :through => :set_sound_sets, :source => :sound
end
So, no more "sound_1" and "sound_2" ... they are both just sounds. For every sound you can also use the set_sounds method to retrieve all of the sounds associated with it.
This would also allow more than two sounds in a relation, and you might like to put a "type" on the sets model.
Edit: If you look at the query generated, you'll find that sound_sets is mentioned in there twice, once with a different alias. The key to eliminating "self" joins is to include a clause in the association along the lines of:
has_many :set_sounds ,
{where("sound_sets.sound_id != set_sound_sets_sound_set_sounds.sound_id")},
:through => :set_sound_sets,
:source => :sound
... where "sound_set_sounds" is the table alias. If you can post the query in the comments I can update this with the actual alias.

How to properly handle multiple model associations to different keys in Rails 4.0.8

I'm having the following problem while trying to model my application, it's basically a functionality to handle bills with multiple people, like sharing the rent or any other similar stuff, the deal is:
I have a user model and a billing model but can't find out how to build the associations.
A user has_many billings and billings belongs_to user but, also the billing has_many users, e.g. Tom registers a bill that is meant to be shared by Tom himself, Betty and Bob.
So that makes Tom the creditor and the other two become debtors in the billing.
I'm kinda lost at this point, how to consolidate these associations, dunno if any more information is needed or if it's clear enough, but will appreciate any help and update with any other information needed.
Thanks in advance,
---EDIT---
I've come to the following approach:
Class User < ActiveRecord::Base
has_many :billings, foreign_key: "creditor_id", dependent: :destroy
end
Class Billing < ActiveRecord::Base
belongs_to :creditor, class_name: "User"
has_many :debts, dependent: :destroy
end
Class Debt < ActiveRecord::Base
belongs_to :billing
has_one :user
end
I also tried to graphically model it for better understanding here: imgur
Would that all be correct?
Don't be afraid to use the options available to you in ActiveRecord. If your model naming is getting cluttered (Billing belongs to a User and has_many Users) then be more specific with the association labels and sort the links with options. The Rails Associations Guide is easy to Google and covers pretty much everything.
class User < ActiveRecord::Base
has_many :billings, :foreign_key => 'creditor_id'
has_many :debts, :through => :debtor_users, :source => :billing
end
class Billing < ActiveRecord::Base
belongs_to :creditor, :class_name => 'User'
has_many :debtors, :through => :debtor_users, :source => :user
end
class DebtorUser < ActiveRecord::Base
belongs_to :billing
belongs_to :user
end
You can extend the Billing model to have multiple creditors also simply by converting the belongs_to association into a has_many :through association following the same pattern as debtors just with a different join model (say CreditorUser).

has_many with two or more tables.

I'm trying to add multiple has_many relationships to my model:
class Program < ActiveRecord::Base
has_many :courses, :program_offers
belongs_to :university
attr_accessible :end_date, :name, :period, :start_date, :symbol, :year, :university_id, :description, :titles, :profile, :price
end
But I get:
hash expected error.
How can I reference two has many tables?
You can't do that because it is association method which takes only one association name as argument:
has_many(name, options = {}, &extension)
So specify each association in single line.
has_many :courses
has_many :program_offers
If you specify like that it considers that you are specifying some condition or block. See the API doc http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_many

Ordering by complex structure in Rails

I have a model called Event that has many EventRegistrations, which belongs to a person.
Also the EventRegistration has many EventAtendees, which belongs to a person too.
I want to order in Rails all the people related to a event, which means:
- Person associated to an event registration
- Person associated to an event atendee which is associated to a registration..
Any help?
As I understand it, you have the following models and associations:
Event
has_many :event_registrations
EventAttendee
belongs_to :event_registration
belongs_to :person
Person
has_many :event_registrations
has_many :event_attendees
EventRegistration
belongs_to :person
belongs_to :event
Now, as to your actual question. You say you want to 'order all the people related to an event'
I don't actually see how 'ordering' (a.k.a sorting) enters into this.
To get all users associated with an event, I recommend adding some :through associations:
Event
has_many :event_attendees, :through => :event_registrations
has_many :people, :through => :event_attendees
Then, when you have an event object, you can simply call .people on it, and it'll just work.
Here is how you would order by the person's last name, assuming you have all your ActiveRecord associations set up correctly.
event_registrations = EventRegistrations.find(:all)
ordered_event_registrations = event_registrations.sort{|registration_a,registration_b|registration_a.people.lastname<=>registration_b.people.lastname}

Rails 3.1 has_many, :through => not working (joined model returns nil)

Update: This was all due to a stupid error: previously, I had defined a method with the same name as one of the methods ActiveRecord creates, which was masking the proper behaviour and breaking everything. I can't answer/close the question for a few more hours, apologies to anyone who looked into this!
I have an infuriating problem with a has_many, :through => relationship in my Rails 3.1 app.
It is infuriating because as far as I can see it is identical to two similar relationships which both work.
The owner of these relationships declares them like this:
has_many :user_skills, :dependent => :destroy
has_many :skills, :through => :user_skills
has_many :user_roles, :dependent => :destroy
has_many :roles, :through => :user_roles
has_many :conversation_users
has_many :conversations, :through => :conversation_users
(I am aware I have not followed standard nomenclature for join tables here - I only read about the convention of both-plural, names-alphabetical after setting this up, and I will refactor later)
The first two pairs of relationships (skills and roles) work just fine.
The final relationship (conversations) does not work fully. user.conversation_users returns the expected array, but user.conversations returns nil. Not an empty array, nil.
I may well be doing something stupid here, so I would be very grateful to anyone who can spot something wrong with the ConversationUser or Conversation models below.
conversation_user.rb
class ConversationUser < ActiveRecord::Base
belongs_to :user, :inverse_of => :conversation_users
belongs_to :conversation, :inverse_of => :conversation_users
validates_presence_of :user
validates_presence_of :conversation
end
conversation.rb
class Conversation < ActiveRecord::Base
has_many :messages, :dependent => :destroy
has_many :conversation_users, :dependent => :destroy
has_many :users, :through => :conversation_users
validates_presence_of :unique_id
end
(I am also aware that these are not really complex enough to justify has_many, :through => over has_and_belongs_to_many, but planned additional functionality will require join models.)
Answering to close question:
This was all due to a stupid error: previously, I had defined a method with the same name as one of the methods ActiveRecord creates, which was masking the proper behaviour and breaking everything.

Resources