An element can be associated with different models through the polymorphic association elementable. Because I want to use nested forms, I have to make associations for the different models explicit (association element_recommendation).
The following code works as intended:
class Element < ActiveRecord::Base
belongs_to :elementable, :polymorphic => true, :dependent => :destroy
belongs_to :element_recommendation, ->(element) {
if element.elementable_type == 'ElementRecommendation'
where('true = true')
else
none
end }, :class_name => "ElementRecommendation", :foreign_key => "elementable_id"
[..]
But I'm unhappy with the lambda in the element_recommendation association. It's an all or nothing association. The none-part is cognizable, but the take it as it is-part is not obvious. How can I make where('true = true') recognizable?
I've found the solution while I was writing the question:
belongs_to :element_recommendation, ->(element) {
if element.elementable_type == 'ElementRecommendation'
self
else
none
end }, :class_name => "ElementRecommendation", :foreign_key => "elementable_id"
Related
This is a rather simple Rails 4 situation. Model Intranet has_many activities. Activities exists with sufficient records for several intranets. Current_intranet.activities.size returns 69 records. However, whenever I try to access any of the records, I receive "output error: <ArgumentError: wrong number of arguments (1 for 0)" even though I'm not passing any arguments. All of the following fail with that error.
Current_intranet.activities.first
Activity.where(intranet_id: 1).first
Activity.where(:intranet_id => 1).first
Activity.where{intranet_id.eq 1}.first
All of the above with [0] instead of first
There is no problem with any other models
I'd appreciate any suggestions. Thanks in advance.
There are no defined scopes. The code is:
class Activity < ActiveRecord::Base
acts_as_capitalized
# activities created during intranet creation.
DEFAULT_ACTIVITIES = { 'Document Preparation' => 'general income', 'No Charge' => 'general income'}
# static activity names that can not be deleted.
STATIC_ACTIVITY_NAMES = [ 'Document Preparation','No Charge']
before_destroy :check_if_used
before_destroy :cannot_delete_static_activities
belongs_to :created_by_user, :class_name => "User", :foreign_key => "created_by"
belongs_to :updated_by_user, :class_name => "User", :foreign_key => "updated_by"
belongs_to :intranet
belongs_to :chart_of_account
has_many :activity_rates, :dependent => :destroy
has_many :event_type
has_many :billings do
def find_by_name(name)
(find :all, :conditions => ["activity.name = ?",name])
end
end
has_many :document_templates, :foreign_key => "billing_activity_id"
validates_presence_of :intranet_id, :name, :chart_of_account_id
validates_uniqueness_of :name, :scope => :intranet_id
How would I go about getting a JSON object with
[
{
Property.field_1,
Property.field_n,
PropAssignmConsumer.field_1,
PropAssignmConsumer.field_n
},
{
Property.field_1,
Property.field_n,
PropAssignmConsumer.field_1,
PropAssignmConsumer.field_n
},
...,
{
Property.field_1,
Property.field_n,
PropAssignmConsumer.field_1,
PropAssignmConsumer.field_n
}
]
sorted by some key (can be a field in either Property or PropAssignmConsumer) for a given user_entity object? i.e. get all properties linked to a given consumer/user_entity, extracting fields from both properties and prop_assignm_consumers, sorting by a field in the properties or prop_assignm_consumer table.
These are my models:
class Property < ActiveRecord::Base
has_many :prop_assignm_consumers, :dependent => :restrict
end
class PropAssignmConsumer < ActiveRecord::Base
belongs_to :consumer
belongs_to :property
end
class Consumer < UserEntity
has_many :prop_assignm_consumers, :dependent => :destroy
has_many :properties, :through => :prop_assignm_consumers
end
I am currently doing
properties = user_entity.properties.find(:all, :order => "#{sort_key} #{sort_ord}")
properties.each do |p|
a = p.prop_assignm_consumers.find_by_consumer_id(current_user.user_entity.id)
... do something with a and p....
end
but this seems inefficient....
Any help would be appreciated.
Maybe I'm missing something. Why doesn't your property also reference consumers? You have many to many, you just didn't complete it. Just adding has_many :consumers, :through => :prop_assignm_consumer would then let you do
properties = user_entity_properties.all(:include => :consumers)
properties.each do |p|
p.consumers.where(:id => current_user.user_entity.id)
end
Though now that we write that, and given that you're doing find_by and not find_all_by, it's pretty clear there's going to be only 1. So you can go the other way.
consumer = Consumer.where(:id => current_user.user_entity.id).includes(:properties).first
consumer.properties.each do |p|
... do something with p and consumer
end
ref
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
I have these models simplified:
class Game::Champ < ActiveRecord::Base
has_one :contract, :class_name => "Game::ChampTeamContract", :dependent => :destroy
has_one :team, :through => :contract
# Attributes: :avg => integer
end
#
class Game::Team < ActiveRecord::Base
has_many :contracts, :class_name => "Game::ChampTeamContract", :dependent => :destroy
has_many :champs, :through => :contracts
end
#
class Game::ChampTeamContract < ActiveRecord::Base
belongs_to :champ
belongs_to :team
# Attributes: :expired => bool, :under_negotiation => bool
end
#
So what I want to do here is to find all Game::Champs that have no Game::ChampTeamContract whatsoever OR has, but (is not :under_negociation OR is :expired ), sorted by Champ.avg ASC
I am kinda stuck at using two queries, concating the result and sorting it. I wish there were a better way to to it more "Railish"
UPDATE: Just added a constraint about :expired
Try something like:
Game::Champs.
joins("left outer join game_champ_team_contracts on game_champ_team_contracts.champ_id = game_champs.id").
where("game_champ_team_contracts.id is null or (game_champ_team_contracts.state != ? or game_champ_team_contracts.state = ?)", :under_negotiation, :expired).
order("game_champs.avg ASC")
This is a fairly nasty line if left as-is, so if you use this, it needs tidying up. Use scopes or methods to split it up as much as possible!
I just tested with a super simple query:
#bars1 = Bar.where(:something => 1)
#bars2 = Bar.where(:something => 2)
#bars = #bars1 + #bars2
Not sure if it's right, but it works...
I have a table with entries, and each entries can have different account-types. I'm trying to define and return the account based on the value of cindof
Each account type has one table, account_site and account_page. So a regular belongs_to won't do.
So is there any way to return something like:
belongs_to :account, :class_name => "AccountSite", :foreign_key => "account_id" if cindof = 1
belongs_to :account, :class_name => "AccountPage", :foreign_key => "account_id" if cindof = 2
Have tried to do that in a method allso, but no luck. Really want to have just one accountand not different belongs_to names.
Anyone that can figure out what I want? Hard to explain in English.
Terw
You should be able to do what you want with a polymorphic association. This won't switch on cindof by default, but that may not be a problem.
class ObjectWithAccount < ActiveRecord::Base
belongs_to :account, :polymorphic => true
end
class AccountSite < ActiveRecord::Base
has_many :objects_with_accounts,
:as => :account,
:class_name => 'ObjectWithAccount'
end
class AccountPage < ActiveRecord::Base
has_many :objects_with_accounts,
:as => :account,
:class_name => 'ObjectWithAccount'
end
You will need both an account_id column and a account_type column. The type of the account object is then stored in the extra type column.
This will let you do:
obj.account = AccountPage.new
or
obj.account = AccountSite.new
I would look into Single Table Inheritance. Not 100% sure, but I think it would solve your problem http://code.alexreisner.com/articles/single-table-inheritance-in-rails.html
If that isn't good, this isn't too hard to implement yourself.
def account
case self.cindof
when 1 then AccountSite.find self.account_id
when 2 then AccountPage.find self.account_id
end
end
Hi i have these classes:
class Core < ActiveRecord::Base
belongs_to :resource, :polymorphic => true
belongs_to :image, :class_name => 'Multimedia', :foreign_key => 'image_id'
end
class Place < ActiveRecord::Base
has_one :core, :as => :resource
end
If i try do launch this:
a = Place.find(5)
a.name ="a"
a.core.image_id = 24
a.save
name is saved. image_id no
i want save automatically all changes in records in relationship with place class at a.save command. is possible?
thanks
Use :autosave => true
See section titled One-to-many Example for ActiveRecord::AutosaveAssociation.
You'll want something like:
class Place
has_one :core, :as => :resource, :autosave => true
end
Disclaimer:
The :autosave => true should be used on the "parent" Object. It works great with has_one and has_many, but I've run into great difficulty attempting to use it on a belongs_to. relationship.
I think that you can use the build_association method to do that. For example,
a = Place.find(5)
a.name = "a"
a.build_core(:image_id => 24)
a.save
But it might only work if the place object was created before hand.