Rails has_one per scope - ruby-on-rails

I have three models as follows:
class User < ActiveRecord::Base
...
has_many :feeds
...
end
class Project < ActiceRecord::Base
...
has_many :feeds
has_many :users, through: :feeds
...
end
class Feed < ActiveRecord::Base
...
belongs_to :user
belongs_to :project
...
end
I want to model the situation where a user can have a maximum of one feed per project. I know that I can do this check in a custom validator within the Feed class, but is there a way to model this using only ActiveRecord associations?

You can do that on Feed.rb:
validates :user_id, :uniqueness => {:scope => :project_id}

Related

An equivalent to first_or_create on a nested attribute in Rails 4

I'm using a has many through pattern with these 3 models
class User < ActiveRecord::Base
has_many :user_topics
has_many :topics, through: :user_topics
end
class Topic < ActiveRecord::Base
validates_presence_of :name
validates :name, :uniqueness => true
end
class UserTopic < ActiveRecord::Base
belongs_to :user
belongs_to :topic
accepts_nested_attributes_for :topic
end
At the moment a new topic model is trying to be created every time a new user_topic is created. I'd like to create a new topic model only if the topic name doesn't already exist, otherwise if it does, use the existing topic_id.
So something like:
class UserTopic < ActiveRecord::Base
belongs_to :user
belongs_to :topic
accepts_nested_attributes_for :topic, :first_or_create(:name)
end
Is it possible to do something similar to this?

Rails getting data from nested attributes

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

Rails Accessing Polymorphic Data from a Relation

I have following models in a Rails application.
class Address < ActiveRecord::Base
belongs_to :addressable, :polymorphic => true
end
class Client < ActiveRecord::Base
has_one :address, :as => :addressable, dependent: :destroy
accepts_nested_attributes_for :address, :allow_destroy => true
has_many :invoices
end
class Invoice < ActiveRecord::Base
belongs_to :client
end
While I am able to retrieve the client name using
#invoice.client.name
I am not able to retrieve the address information in the similar manner.
How do I retrieve the address attributes in the view for invoice?
#invoice.client.address that is the aswer. But i recommend you follow the Law of Demeter using the method delegate
http://en.wikipedia.org/wiki/Law_of_Demeter
http://api.rubyonrails.org/classes/Module.html#method-i-delegate
Basically the idea is that you can do this: #invoice.client.address_street o better #invoice.client_address_street

:conditions deprecated in Rails 4, need new Polymorphic syntax for accessing parent

I have a fairly normal class structure, using a polymorphic association:
class Contact < ActiveRecord::Base
has_many :opportunities, :as => :has_opportunities, dependent: :destroy
end
class Company < ActiveRecord::Base
has_many :opportunities, :as => :has_opportunities, dependent: :destroy
end
class Opportunity < ActiveRecord::Base
belongs_to :has_opportunities, polymorphic: true
belongs_to :contact, foreign_key: 'has_opportunities_id', conditions: "opportunities.has_opportunities_type = 'Contact'"
belongs_to :company, foreign_key: 'has_opportunities_id', conditions: "opportunities.has_opportunities_type = 'Company'"
end
In Rails 4 using :conditions has been deprecated, but I can't figure out the "new" syntax required to allow access to the parent object from the child.
Edit: Yes, you can do opportunity.has_opportunities which will return you a Contact or a Company, but it is often "nicer" in code to use opportunity.contact or opportunity.company
Can't you simply set it up as a regular polymorphic association?
class Opportunity < ActiveRecord::Base
belongs_to :has_opportunities, polymorphic: true
end

Accessing rails attributes through deep associations

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

Resources