Cannot create has_one association, throws undefined method new error - ruby-on-rails

I'm trying to build a one to one association in Rails 5, basically, I just want users to connect to only one user.
So I want to be able to do this in my rails console:
User.first.relationship.new(:partner_id => 2)
To be able to set and retrieve the partner of a particular user.
I'm using a join model, called Relationship.
class Relationship < ApplicationRecord
belongs_to :user
belongs_to :partner, :class_name => "User"
end
And a User model.
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable
has_one :relationship
has_one :partner, :through => :relationship
validates_presence_of :first_name, :last_name
end
I generated the Relationship model like this: rails g model Relationship user:references partner_id:integer.
When I do a User.first.relationship.new() it throws a NoMethodError: undefined method new for nil:NilClass in the rails console.
However, when I change the User model from has_one to has_many:
has_many :relationships
has_many :partners, :through => :relationships
It works, but I want to have only a one to one relationship using a self-referential association.
What am I doing wrong? Thanks!

Try User.first.create_relationship(relationship_params) ?

Related

Rails best way (or best practices)

I have a model which I don't know how to focus the following issue:
I have been reading the following posts
before_create in rails model
before_create in user model -- set integer based on email (RAILS)
Access current_user in model
I have a project where I want to manage some properties (Assets).
I have Property, Owner, Company and Users.
The House and the Owner are linked in the DB with a FK so 1 Company has N Owners and 1 Company has N Properties.
The model User is linked to Company, so 1 Company has N users.
How can I access the company_id in the model Users in order to store this ID in the Properties and in the Owner model when the Property and Owner is created?
Do I have to do it in the controller and model?
Owner Class
class Owner < ApplicationRecord
acts_as_paranoid
has_many :property_owners
has_many :properties, :through => :property_owners
belongs_to :company
belongs_to :country
accepts_nested_attributes_for :properties
Property Class
class Property < ApplicationRecord
acts_as_paranoid
has_many :property_owners has_many :owners, :through =>
:property_owners
belongs_to :company belongs_to :country
This is the Company
Class Company < ApplicationRecord
has_many :properties
has_many :owners
And the last one is Users
class User < ApplicationRecord
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
before_create :set_default_role, only: :create
belongs_to :country
belongs_to :company
belongs_to :user_role
accepts_nested_attributes_for :company
Considering you have your associations right, in your controller, when a user creates, for example, a house entry:
def create
#property = current_user.company.properties.new(property_params)
....
end
Where current_user can be replaced by the variable containing the user currently logged on and property_params are the strong params, sent to the controller from your form.
Likewise for owner

Audited-activerecord gem not working properly for polymorphic associations

I want to make audits for nested associations like I have
User has_many addresses i.e either
HomeAddress or OfficeAddress
Now if I have just one table Address and I have used type and id for differentiating them.In this case if I use associated_audits for User then it will make just one audit record and whenever I update the record again ,its just replacing the previous audit with the last one.
Here is the models association:
class Patient < ActiveRecord::Base
devise :database_authenticatable, :registerable, :recoverable, :rememberable,
:trackable, :validatable, :confirmable, request_keys: [:subdomain]
has_one :home_address,-> { where(addr_type: 'home') },class_name: 'Address'
has_one :office_address,-> { where(addr_type: 'office') }, class_name: 'Address'
has_associated_audits
accepts_nested_attributes_for :home_address, allow_destroy: true
accepts_nested_attributes_for :office_address, allow_destroy: true
end
class Address < ActiveRecord::Base
belongs_to :patient
audited
end
class Address < ActiveRecord::Base
belongs_to :patient
audited associated_with: :patient
end
class Patient < ActiveRecord::Base
has_many :addresses
has_associated_audits
end

Obtaining records where a certain condition is satisfied with two has_many :through

Let's say I have 3 models in my Rails app... Establishment, WasteType and EstablishmentWaste... My problem is that I want to get all establishments associated with a certain wastetype. This normally would be done with Establishment.where(waste_type_id: some_number), the problem is that Establishment has many WasteType and vice versa, and the association is made through a third party...
Any help?
Classes and data model below
Establishment
class Establishment < ActiveRecord::Base
# Include default devise modules.
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
has_many :containers
has_many :establishment_wastes
has_many :waste_types, through: :establishment_wastes, :foreign_key => 'establishment_id'
include DeviseTokenAuth::Concerns::User
end
WasteType
class WasteType < ActiveRecord::Base
has_many :containers
has_many :establishment_wastes
has_many :establishments, through: :establishment_wastes, :foreign_key => 'waste_type_id'
end
EstablishmentWaste
class EstablishmentWaste < ActiveRecord::Base
belongs_to :establishment, :foreign_key => 'establishment_id'
belongs_to :waste_type, :foreign_key => 'waste_type_id'
end
So the data model would be like these
EstablishmentWaste is a join table in this case so the query should be.
Establishment
.joins(:establishment_wastes)
.where('establishment_wastes.waste_type_id = ?', some_number)
Quick tip! You do not need to assign :foreign_key => 'establishment_id' since it is default Rails behavior to assign a foreign key to model_id.

How to use owner_id (instead of user_id) as foreign key?

I'm building an app where a user creates an arbitrary number of groups. When the group is created, the owner_id (in the group table) is set to that of the current_user.id.
I'm having some trouble showing the groups owned by a particular user though. Note that there is a many-to-many relationship between users and groups through the GroupMembers table.
Based on this question, I modified my group.rb model like such:
class Group < ActiveRecord::Base
has_many :group_members, :dependent => :destroy
has_many :users, :through => :group_members
belongs_to :owner, class_name: User, foreign_key: :owner_id
end
Adding just the last line to ("owner") to the model. The problem is that when I display the groups belonging to the user in my view:
<h3>User</h3>
<p>User: <%= #user.name %></p>
<p>Email: <%= #user.email if #user.email %></p>
<p>Groups:
<% #user.groups.each do |group|%>
<%= group.name %>
<% end %>
</p>
None of the groups show up. It seems that maybe I need to explicitly join to the groups table from inside the UsersController for this to work? But I'm not sure. I don't want to go too far down the rabbit hole here so I'm looking for some advice.
UPDATE:
Here is my User model:
class User < ActiveRecord::Base
has_many :group_members, :dependent => :destroy
has_many :groups, :through => :group_members
rolify
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :invitable, :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable
end
When you fetch #user.groups, you're using the :groups association on the User model, which is independent of the has_one :user association on the Group model. So the code you've provided above isn't the relevant bit. What you need is:
class User < ActiveRecord::Base
has_many :groups, foreign_key: :owner_id
end
Update: since you've already got a has_many :groups relation, you'll need to name this something else. e.g.,
class User < ActiveRecord::Base
has_many :owned_groups, foreign_key: :owner_id, class_name: Group
end
Then you'll need to update your view code to do #user.owned_groups instead of #user.groups, or you'll be fetching the wrong collection.
(p.s., the inverse relation on the Group model should be belongs_to :owner, class_name: User, foreign_key: :owner_id, not has_one. The difference is that a model that belongs_to another model is expected to hold the foreign key that defines the relationship, whereas a has_one relationship expects the foreign key to be on the associated table.)
You can do something like
# user.rb
has_many :owned_groups, foreign_key: 'owner_id', class_name: "Group"
That will distinguish between groups that the user owns vs groups that the user is in.

Many to Many, Through Relationship for Users

On Rails 4, I am using devise for my users and I have a scaffold for exercises.
Each user is to have many exercises, and each exercises have many users, this is done through a model called schedule.
I want to build a form, so that when a new exercise is created then it can be assigned to the Users. I am little lost on how to allow the schedule table to accept both the exercise_id and user_id when I create a new exercise. Any help is appreciated!
/user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :schedules
has_many :exercises, :through => :schedules
/exercise.rb
class Exercise < ActiveRecord::Base
validates :description, presence: true
has_many :schedules
has_many :users, :through => :schedules
/schedules.rb
class Schedule < ActiveRecord::Base
belongs_to :exercise
belongs_to :user
Exercise Controller
def exercise_params
params.require(:exercise).permit(:description, :notes, :video, {:users=>[]})
end
edit
I am lost as what to do next in order to get the Schedule table to populate with Exercise_ids and User_ids.
Schema:
USERS
id
email
name
(standard columns from devise)
EXERCISES
id
description
created_at
updated_at
tag
notes
video_file_name
video_content_type
video_file_size
video_updated_at
SCHEDULE
id
exercise_id
user_id
position
created_at
updated_at

Resources