belongs_to with :conditions in Rails 4 - ruby-on-rails-3

I have two models, Users and Accounts:
class User < ActiveRecord::Base
belongs_to :account, :conditions=>proc{" company_account = #{self.company_user} "}
end
class Account < ActiveRecord::Base
has_many :users
end
In Rails 3 belongs_to and :conditions=> works fine, but in Rails 4 I read this options is not valid.
I tried belongs_to :account, -> {where company_account: self.company_user} but I get error undefined methodcompany_user
How can I solve this in Rails 4?

I solved my problem, by using a composed primary key in my Account model.
For this, I used this gem

Try something like:
belongs_to :account, -> { where("company_account_id = ?", self.send(:company_user).id) }

Related

has_many :condition multiple models how to use join here?

I have the following model structure:
Model Visitor
class Visitor < ActiveRecord::Base
has_many: triggers
end
Model Trigger
class Trigger < ActiveRecord::Base
belongs_to :visitor, :inverse_of => :triggers
belongs_to :event, :inverse_of => :triggers
end
Model Event
class Event < ActiveRecord::Base
has_many: triggers
end
I am trying to setup a custom association in Visitor model like so:
has_many: triggers_that_pass_some_condition ,:class_name => "Trigger",
:conditions => ["triggers.some_column >= events.some_column"]
The problem is that it doesn't work .. I am guessing I have to do some kind of join to compare columns of two separate models (that are associated with each other)
I have tried
triggers.some_column >= triggers.event.some_column
That does not work either. Anyone has any suggestions? thanks!
Try the following code..
class Trigger < ActiveRecord::Base
belongs_to :event
belongs_to :visitor
end
# Visitors.rb
has_many :triggers_with_condition, -> { includes(:event).where(some_trigger_column >= event.some_event_column)}, class_name: "Trigger"
Make sure you first add the correct association between Visitor and Trigger in your model setup. From there, you can add a custom association as follows:
class Visitor < ActiveRecord::Base
has_many :approved_triggers, -> { includes(:events).where("events.something = ?", true).references(:events) }, class_name: 'Trigger', inverse_of: :visitor
end
class Trigger < ActiveRecord::Base
belongs_to :visitor, inverse_of :triggers
end
Right now your Trigger class holds no association to a Visitor.
Thanks to the clue from Darpa, I eventually settled on this:
has_many :custom_trigger, {:class_name => "Trigger", :include => :event,
:conditions => ["triggers.some_column >= events.another_column"]}

How to forbid deletion if association present

I have a many to many relationship between two models as follows:
#users.rb
has_many :users_to_roles
has_many :roles, through: :users_to_roles
#users_to_roles.rb
belongs_to :user
belongs_to :role
#roles.rb
has_many :users_to_roles
has_many :users, through: :users_to_roles
I want to disable the deletion of roles if there are users who are "in this role". Here I have found two options who should do the work:
:restrict_with_exception causes an exception to be raised if there are
any associated records :restrict_with_error causes an error to be
added to the owner if there are any associated objects
but there is no example with the syntax of this and how it should work.
Could you help to make this valid:
#roles.rb
has_many :users_to_roles
has_many :users, through: :users_to_roles, dependent: restrict_with_exception
Such operations can be easily do using Callbacks. In my case, I have added the following method in my model:
# callbacks
before_destroy :check_for_users_in_this_role
def check_for_users_in_this_role
status = true
if self.security_users.count > 0
self.errors[:deletion_status] = 'Cannot delete security role with active users in it.'
status = false
else
self.errors[:deletion_status] = 'OK.'
end
status
end
Alternatively, you can rescue the exception in your controller. In this example, a contact may own interest, i.e.
class Interest < ActiveRecord::Base
belongs_to :contact
end
class Contact < ActiveRecord::Base
has_many :interests, :dependent => :restrict
end
Then in the controller:
def destroy
#contact = Contact.find(params[:id])
begin
#contact.destroy
rescue
flash[:msg] = "Can't delete - owns interest"
end
respond_to do |format|
format.html { redirect_to(:back) }
format.xml { head :ok }
end
end
The flash message will be displayed in the calling page.
The correct rails way is to do the following:
users.rb:
has_many :users_to_roles, dependant: :destroy # don't keep the join table entry if the user is gone
has_many :roles, through: :users_to_roles
Make sure that your join does not have redundant entries (in which either column is null or orphaned).
users_to_roles.rb:
belongs_to :user
belongs_to :role
# add validations presence of both user and role
# in both model and database.
Bonus, from rails 4.2 you can add forigen_key: true in your migration for referential integrity
Now in your role (I am assuming you name your models singularly and made a typo in the question), you add this:
role.rb:
has_many :users_to_roles, dependant: :restrict_with_error
has_many :users, through: :users_to_roles
I made it with my classes like this:
app/models/guest_chat_token.rb
class GuestChatToken < ApplicationRecord
has_many :chat_messages, as: :sendable, dependent: :restrict_with_exception
end
app/controllers/admin/application_controller.rb
class Admin::ApplicationController < ApplicationController
....
rescue_from ActiveRecord::DeleteRestrictionError do |exception|
redirect_to :back, notice:
"Be aware: #{exception.message}."
end
end

Rails Association (belongs_to) dilemma

I have a User model:
class User < ActiveRecord::Base
has_many :cards
end
and a Card model:
class Card< ActiveRecord::Base
belongs_to :user, :foreign_key => "owner_id"
end
the card model also has an attribute called "owner_id", which I'd like to use in way like this:
Card.first.owner which will retrieve the User which owns that card
my problem as that, I know that rails will automagically connect the id's in the association but that doesnt happen.
in the CardController, rails get stuck in the create action on the line
#card=current_user.cards.new(params[:card])
and says unknown attribute: user_id
I've done db:migrate and it still won't work.
must I do as follows for it to work?
#card = Card.new(params[:card])
#card.owner_id=current_user.id
or am I missing something?
First of all, you don't need a owner_id column for this. All you need is
class User
has_many :cards
end
This will give you #user.cards
class Card
belongs_to :owner, :class_name => "User", :foreign_key => "user_id"
end
This will give you #card.owner

What's the rails way to include a field in a join model when listing an association?

So if I have the following relationship
class Item < ActiveRecord::Base
has_many :item_user_relationships
has_many :users, :through => :item_user_relationships
end
class User < ActiveRecord::Base
has_many :item_user_relationships
has_many :items, :through => :item_user_relationships
end
class ItemUserRelationship < ActiveRecord::Base
belongs_to :item
belongs_to :user
attr_accessible :role
end
What's the rails way to include the role attribute when listing all the Users of an Item?
#users = #item.users # I want to include the role as part of a user
Thanks!
UPDATE: I'm still having trouble with this. My goal is to get an array of User models that have their role included in the attributes.
I'm note sure if I understand you correctly, but maybe this is what you want?
#users = #item.users
#users.each do |user|
puts user.item_user_relationships.first.role
end

Rails 3 - model issue, foreign key

I have two models, Like and Photo.
class Like < ActiveRecord::Base
belongs_to :photo, :class_name => "DataLike", :foreign_key => "photo_id"
end
class Photo < ActiveRecord::Base
has_many :likes
end
And now I try to execute this query:
query = Like.select(:photo_id).joins(:photo).count
But I am still getting this error:
uninitialized constant Like::DataLike
Could anyone help me, please, what I am doing wrong?
Thank you so much
You don't seem to have a DataLike model, my best guess is that you want to link to the Photo model:
class Like < ActiveRecord::Base
belongs_to :photo, :foreign_key => "photo_id"
end
class Photo < ActiveRecord::Base
has_many :likes
end
If you leave out the :class_name option, the Photo model is inferred. It's used to specify the class of the linked model, in case it is different from the association name.