I have three models:
data_set.rb
class DataSet < ActiveRecord::Base
has_many :browse_options
accepts_nested_attributes_for :browse_options, allow_destroy: true
end
browse_option.rb
class BrowseOption < ActiveRecord::Base
belongs_to :data_set
has_many :browse_option_datas
accepts_nested_attributes_for :browse_option_datas, allow_destroy: true
end
browse_option_data.rb
class BrowseOptionData < ActiveRecord::Base
belongs_to :browse_options
has_one :tradesman
end
I want to be able to display all the tradesman associated with a data set in the data set view with no duplicates. Is there a way I can use the joins method to do this in the controller? Thanks!
You can actually achieve this by setting up has_many through relationships between your models. There are great docs on this topic.
class DataSet
has_many :browse_options
has_many :browse_option_datas, :through => :browse_options
has_many :tradesmen, :through => :browse_option_datas
end
class BrowseOption
belongs_to :data_set
has_many :browse_option_datas
end
class BrowseOptionData
belongs_to :browse_options
belongs_to :tradesman
end
class Tradesman
has_many :browse_options_data
end
Edit: After some discussion in chat we also realised the relationships between Tradesman & BrowseOptionData needed some fixing.
Now, in your controller, you can call:
#data_set = DataSet.first
#tradesmen = #data_set.tradesmen # .uniq if you don't want any duplicates
Related
I have a parent model called Quote. which has an attribute called final_quote and has a child model called QuoteBoms, which has attributes called quote_final_quote and quantity and total_quote (=quote_final_quote * quantity)
class Quote < ActiveRecord::Base
has_many :quote_boms, dependent: :destroy
accepts_nested_attributes_for :quote_boms, :reject_if => :all_blank, :allow_destroy => true
class QuoteBom < ActiveRecord::Base
belongs_to :quote
has_many :quotes
end
Now in the nested model, I am selecting the quote with the association "belongs_to :quote" but has_many :quotes does not work as I have only one quote_id column (I suppose this is the problem). I see that i need to define a third class as quotebom_quote_id but cannot figure out how exactly!
Any help will be greatly appreciated!
class Image < ActiveRecord::Base
belongs_to :imageable, :polymorphic => true
end
class Profile < ActiveRecord::Base
has_many :images, :as => :imageable
end
class Article < ActiveRecord::Base
has_many :images, :as => :imageable
end
This is how we have made a single Image model and it is accessed by one or more than one model
Please refer this
Link
From what I can tell, you wish to create a database structure containing the models Quote and QuoteBom where a Quote has many QuoteBom and QuoteBom belongs to many Quotes.
That being the case, you will want to use a has_and_belongs_to_many association.
This will require adding to your models
class Quote < ActiveRecord::Base
has_and_belongs_to_many :quote_boms
end
class QuoteBom < ActiveRecord::Base
has_and_belongs_to_many :quotes
end
...and the following migration (assuming Quote and QuoteBom already exist)
class CreateQuotesAndQuoteBoms < ActiveRecord::Migration
def change
create_table :quote_quote_boms, id: false do |t|
t.belongs_to :quote, index: true
t.belongs_to :quote_bom, index: true
end
end
end
By having the associations above in the model and this table in your database, rails will automagically handle the associations between quote and quote_doms. As a result, you will also be able to access quote_dom.quotes which you said you weren't able to do in your question.
This is NOT a polymorphic association. A polymorphic association allows a model to belong to more than one type of other model in a single association.
I am trying to associate a polymorphic model (in this case Product) to a dynamic class name (either StoreOnePurchase or StoreTwoPurchase) based on the store_type polymorphic reference column on the products table.
class Product < ActiveRecord::Base
belongs_to :store, polymorphic: true
has_many :purchases, class_name: (StoreOnePurchase|StoreTwoPurchase)
end
class StoreOne < ActiveRecord::Base
has_many :products, as: :store
has_many :purchases, through: :products
end
class StoreOnePurchase < ActiveRecord::Base
belongs_to :product
end
class StoreTwo < ActiveRecord::Base
has_many :products, as: :store
has_many :purchases, through: :products
end
class StoreTwoPurchase < ActiveRecord::Base
belongs_to :product
end
StoreOnePurchase and StoreTwoPurchase have to be separate models because they contain very different table structure, as does StoreOne and StoreTwo.
I am aware that introducing a HABTM relationship could solve this like this:
class ProductPurchase < ActiveRecord::Base
belongs_to :product
belongs_to :purchase, polymorphic: true
end
class Product < ActiveRecord::Base
belongs_to :store, polymorphic: true
has_many :product_purchases
end
class StoreOnePurchase < ActiveRecord::Base
has_one :product_purchase, as: :purchase
delegate :product, to: :product_purchase
end
However I am interested to see if it is possible without an extra table?
Very interesting question. But, unfortunately, it is impossible without an extra table, because there is no polymorphic has_many association. Rails won't be able to determine type of the Product.purchases (has_many) dynamically the same way it does it for Product.store (belongs_to). Because there's no purchases_type column in Product and no support of any dynamically-resolved association types in has_many. You can do some trick like the following:
class Product < ActiveRecord::Base
class DynamicStoreClass
def to_s
#return 'StoreOnePurchase' or 'StoreTwoPurchase'
end
end
belongs_to :store, polymorphic: true
has_many :purchases, class_name: DynamicStoreClass
end
It will not throw an error, but it is useless, since it will call DynamicStoreClass.to_s only once, before instantiating the products.
You can also override ActiveRecord::Associations::association to support polymorphic types in your class, but it is reinventing the Rails.
I would rather change the database schema.
I have three models
poll
class Poll < ActiveRecord::Base
has_many :options
end
option
class Option < ActiveRecord::Base
belongs_to :poll
has_many :votes
end
vote
class Vote < ActiveRecord::Base
belongs_to :option
end
How can I get all the votes for all the options of the poll like
Poll.find(params[:id]).votes
Thanks
You should be able to use a has_many :through assocation on Poll:
class Poll
belongs_to :poll
has_many :votes, through: :options
end
More information: http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association
Try to add this to Poll model
has_many :votes, through: :options
Add into your Poll model:
has_many :votes, through: :options
A has_many :through association is often used to set up a many-to-many connection with another model. This association indicates that the declaring model can be matched with zero or more instances of another model by proceeding through a third model.
so the standard way to use a has_many :through association would be to use the Physician-Appointment-Patient model from the Active Record Association Guide, right? It's basically a more verbose HABTM, with two models having a has_many :through and the connector model having two belongs_to. Now, in my current project I have a model structure like this:
class Cart < ActiveRecord::Base
has_many :line_items, through: line_item_groups
has_many :line_item_groups
end
class LineItemGroup < ActiveRecord::Base
belongs_to :cart
has_many :line_items
end
class LineItem < ActiveRecord::Base
belongs_to :line_item_group
has_one :cart, through: line_item_group
end
Works fine. But now I want a line_item_count on Cart and can't figure out where I should add the counter_cache attribute.
Any help is appreciated :-)
First add line_item_count field in carts table, then in LineItem model add
class LineItem < ActiveRecord::Base
before_create :increment_counter
before_destroy :decrement_counter
def increment_counter
Cart.increment_counter(:line_item_count, cart.id)
end
def decrement_counter
Cart.decrement_counter(:line_item_count, cart.id)
end
end
I didn't tried it, but I think it will solve your problem.
Here are my relevant models:
class ListItem < ActiveRecord::Base
belongs_to :inventory_item
belongs_to :shopping_list
belongs_to :item
end
class ShoppingList < ActiveRecord::Base
has_many :list_items
belongs_to :user, :foreign_key => :user_id
end
class InventoryItem < ActiveRecord::Base
belongs_to :item, :foreign_key => :item_id
belongs_to :vendor
has_many :list_items
end
I'm trying to access attributes of InventoryItem in my view. Here's what I currently have in my ShoppingListController.
def show
#list_items = ShoppingList.find(params[:id]).list_items
end
Can I do something like #inventory_items = #list_items.inventory_items? That code and variants of it that I've tried haven't worked. What am i missing here? Any tips for accessing attributes through multiple models like this? Thanks in advance!
The most straight forward approach would be to use has_many through on the ShoppingList class:
has_many :inventory_items, through: :list_items