Cannot get data from related models in Rails - ruby-on-rails

I have 2 models in different namespace.
class Admin::Membership < ActiveRecord::Base
has_many :authorization_roles
end
class AuthorizationRole < ActiveRecord::Base
belongs_to :membership
end
The Membership model is in different folder with AuthorizationRole model (I don't know what is called)
When run Admin::Membership.find(:all), the data from AuthorizationRole model is not included. I've create membership_id field on authorization_roles table, but I still can't get both models related. Is something wrong in this code? Sorry if I'm missing something basic here.

Try this
class Admin::Membership < ActiveRecord::Base
has_many :authorization_roles, :class_name => '::AuthorizationRole'
end
class AuthorizationRole < ActiveRecord::Base
belongs_to :membership, :class_name => 'Admin::Membership'
end

I've never used namespaced models and I don't think you need to... but maybe you'll have to specify the class name in AuthorizationRole, something like:
belongs_to :membership, :class_name => 'Admin::Membership'
UPDATE:
Assuming you have:
class Membership < ActiveRecord::Base
has_many :authorization_roles
end
class AuthorizationRole < ActiveRecord::Base
belongs_to :membership
end
You have added an integer column called membership_id to authorization_roles and you've run the migrations. Now you should be able to create authorization_roles like this #membership.authorization_roles.create( ... ) and fetch them #membership.authorization_roles

Check to see if you are setting the table name prefix. The Rails model generator adds a file like this for namespaced models:
# /app/models/admin.rb
module Admin
def self.table_name_prefix
'admin_'
end
end
Note: this is Rails version 3.0.1 -- not sure about earlier versions.

Related

Creating the reverse of an association within a concern

I have a concern that creates an association:
# concerns/product.rb
module Product
extend ActiveSupport::Concern
included do
has_many :products, class_name: "Product", foreign_key: :owner_id
end
end
And an example model:
# models/user.rb
class User < ApplicationRecord
include Product
end
If I do: User.products.last it works fine. I also want to be able to do Product.last.owner but it won't work without the association being defined. I can't define it in the Product model since I have no clue to what models will include the concern that creates the association.
I have tried creating the association using inverse_of:
class Product < ApplicationRecord
belongs_to :owner, inverse_of: :products
end
... but it won't work, apparently it needs a class name.
I've also tried reflecting on which classes the concern gets included within but it raises some strange errors when the concern gets included into several different models.
How do I create the inverse of an association from within the concern?
As pointed out by #engineersmnky you can't actually setup an association that points to a bunch of different classes without using polymorphism:
# you can't have a class and a module with the same name in Ruby
# reopening the class/module will cause a TypeError
module ProductOwner
extend ActiveSupport::Concern
included do
has_many :products, as: :owner
end
end
class Product < ApplicationRecord
belongs_to :owner,
inverse_of: :products,
polymorphic: true
end
class User < ApplicationRecord
include ProductOwner
end
The information about what you're actually joining has to be stored somewhere on the products table. If you don't use polymorphism you just have an integer (or UUID) which will always refer to a single table.

What is 'as' in ruby on rails model?

What is 'as' in ruby on rails model? and how does it work?
e.g.
has_many :something, as: :reasonable
Is it polymorphic?
Yes, this is a polymorphic association which allows a model to belong to multiple models. There should be
class Something < ApplicationRecord
belongs_to :reasonable, polymorphic: true
end
And then any model can have many of these as reasonable without adding another column to Something.
class Thing < ApplicationRecord
has_many :somethings, as: :reasonable
end
class Stuff < ApplicationRecord
has_many :somethings, as: :reasonable
end
Something stores both the class and ID of what its associated with allowing it to be polymorphic.

ActiveRecord won't build the right class using STI

I'm using single table inheritance in my application and running into problems building inherited users from an ancestor. For instance, with the following setup:
class School < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
attr_accessible :type #etc...
belongs_to :school
end
Class Instructor < User
attr_accessible :terms_of_service
validates :terms_of_service, :acceptance => true
end
Class Student < User
end
How can I build either a instructor or student record from an instance of School? Attempting something like School.first.instructors.build(....) gives me a new User instance only and I won't have access to instructor specific fields such as terms_of_service causing errors later down the rode when generating instructor-specific forms, building from console will give me an mass-assignment error (as it's trying to create a User record rather than an Instructor record as specified). I gave the example of School, but there are a few other associations that I would like to inherit from the User table so I don't have to repeat code or fields in the database. Am I having this problem because associations can not be shared in an STI setup?
You should specify instructors explicitly
class School < ActiveRecord::Base
has_many :users
has_many :instructors,:class_name => 'Instructor', :foreign_key => 'user_id'
end
And what else:
class School < ActiveRecord::Base
has_many :users
has_many :instructors
end
class Instructor < User
attr_accessible :terms_of_service # let it be at the first place. :)
validates :terms_of_service, :acceptance => true
end
OK it seems part of the problem stemmed from having the old users association inside of my School model. Removing that and adding the associations for students and instructors individually worked.
Updated School.rb:
class School < ActiveRecord::Base
#removed:
#has_many :users this line was causing problems
#added
has_many :instructors
has_many :students
end

How does ActiveRecord link records together?

So this has been surprisingly difficult to locate a quick answer to. I'm using ActiveRecord in a pure console app, and I have my classes set up like so:
class Owner < ActiveRecord::Base
has_many :profiles
end
class Profile < ActiveRecord::Base
has_many :lines
belongs_to :owner
end
class Line < ActiveRecord::Base
belongs_to :profiles
end
Now normally i'd do something like..
Profile.create( :thing => "thing", :otherthing => "otherthing" )
How does AR know to link this instance of profile to an owner? What about a specific owner already in the database? How do I tell it? How would I do all of the links at once? (line, to profile, to owner)?
Read this to understand the basics. http://guides.rubyonrails.org/association_basics.html.

Creating models with two words

I have two models one is named BusinessUser and the other is named BusinessPlace.
The BusinessUser can have many BusinessPlaces
class BusinessUser < ActiveRecord::Base
has_many :BusinessPlaces
end
class BusinessPlace < ActiveRecord::Base
belongs_to :BusinessUser
end
When i'm trying to access #business_user.BusinessPlaces.count the sql that get build and run on DB is
SELECT COUNT(*) FROM "business_places" WHERE "business_places"."business_user_id" = 1
but in the migration and in the database the column for business user id is BusinessUser_id which makes the query to fail. Why the sql gets to be build wrong ? I've used the console to create the models.
You just need to set the foreign_key the association will be using for :business_user:
class BusinessUser < ActiveRecord::Base
has_many :business_places
end
class BusinessPlace < ActiveRecord::Base
belongs_to :business_user, :foreign_key => 'BusinessUser_id'
end
You're using the wrong wording for the keys. Your models should look like so:
class BusinessUser < ActiveRecord::Base
has_many :business_places
end
class BusinessPlace < ActiveRecord::Base
belongs_to :business_user
end
so basically use :business_places instead of :BusinessPlaces
if you use migrations to set up your databases you should not need to modify the foreign keys

Resources