I'm having difficulty with bulding attributes within my model. I keep seeing this error
NoMethodError: undefined method `users' for #<ActiveRecord::ConnectionAdapters::SQLite3::TableDefinition:0x00007f9d9ad9df98>
I need attributes that look like this:
#group.rb
class Spree::Group < ActiveRecord::Base
has_many :users
end
#user_decorator.rb
Spree::User.class_eval do
belongs_to :group, class_name: "Spree::Group"
end
For group.rb I ran
rails g model Spree::Group
and I got:
class Spree::Group < ApplicationRecord
has_many :users
end
I'm confused on how to add 'has_many :users' without actually going into the
model and inputting it there.
For the user_decorator I'm not sure what that migration would look like. Any help would be fantastic!
You could call:
rails g model group user:references
which will generates an user_id column in the groups table and will modify the group.rb model to add a belongs_to :user relatonship. Please note, you must to put manually the has_many :groups or has_one :group relationship to the user.rb model.
If you already have the model generated, you could create a migration with the following:
rails g migration AddUserToGroup user:belongs_to
which will generate:
class AddUserToGroup < ActiveRecord::Migration
def change
add_reference :groups, :user, index: true
end
end
the only difference with this approach is, the belongs_to :user relationship in the group.rb model won't be created automatically, so you must create it for your own.
Related
I have two models. Users and Jobs. I have a join table to indicate a User's interest in a Job. I was using a has_and_belongs_to_many relationship for Users and Jobs. I now realize I need to be using a has_many :through relationship. Because of that, I need to have a model for my join table or I get undefined Constant errors. My join table is called jobs_users. What should I name the .rb file for the model and what should the class name be in order to get Rails magic to work? I have found SO questions that imply the class should be JobUser, but nothing on what the .rb file should be named.
Naming convention for Rails models based on existing tables
Model class names use CamelCase. These are singular, and will map automatically to the plural database table name.
> 'JobsUser'.underscore
=> "jobs_user"
This means your file should be named jobs_user.rb. And class will look like below
class JobsUser < ApplicationRecord
...........
end
For fresh migration, you can rollback and destroy current table migration e.g jobs_users and then run this command
rails g model UserJob user:references job:references
db/migrate/TIMESTAMP_create_user_jobs.rb file looks like below
class CreateUserJobs < ActiveRecord::Migration[5.1]
def change
create_table :user_jobs do |t|
t.references :user, foreign_key: true
t.references :job, foreign_key: true
t.timestamps
end
end
end
then migrate this and created model file name is user_job.rb
has_many :through relationship will looks like this
#user.rb
class User < ApplicationRecord
has_many :user_jobs, dependent: :destroy
has_many :jobs, through: :user_jobs
end
#job.rb
class Job < ApplicationRecord
has_many :user_jobs, dependent: :destroy
has_many :users, through: :user_jobs
end
#user_job.rb
class UserJob < ApplicationRecord
belongs_to :user
belongs_to :job
end
That's it
I'm not sure if I fully wrap my mind around this. I want to create a relationship between stores and documents.
In the document table I want a reference to the store and account that created it. To do this would I run this migration
rails g AddStoreToDocuments store:references
and then in the model, specify foreign_keys of account_id and store_id?
like this?
has_many :stores, foreign_key: "store_id"
What is the correct way?
I suggest you to read rails guide on migration.
You can generate the reference by using
rails g migration AddStoreRefToDocuments store:references
rake db:migrate
This will generate the migration. Your models should have association mentioned to make it work
Class Store < ActiveRecord::Base
has_many :documents
end
Class Document < ActiveRecord::Base
belongs_to :store
end
Your documents table should have reference to both tables.
rails g AddStoreToDocuments store:references account:references
relation should be store has_many documents and account has_many documents.
So in Document model :
belongs_to :store
belongs_to :account
in Store model :
has_many :documents
in Account model :
has_many :documents
In the document table I want a reference to the store and account
that created it.
Your relationship should be belongs_to instead of has_many:
belongs_to :store
belongs_to :account
Notice that, since you are following ActiveRecord conventions, you don't need to specify any foreign key (it will use store_id and account_id).
And has_many relationship should be used in both Store and Account models:
has_many :documents
You will also need to update your migration (or create a new one) to add account:references.
firstly, your migration would throw an error, it should be
rails g migration AddStoreToDocuments store:references
generated migration looks like
def change
add_reference :documents, :store, index: true, foreign_key: true
end
then do,
rake db:migrate
which will automatically create a column store_id in your documents table, so in your documents.rb
belongs_to :store
belongs_to :account #this you might already be having I suppose
I created a Model in a ruby on rails app rails g model subject_structure name:string abbreviation:string
I created the relations
class SubjectStructure < ActiveRecord::Base
has_many :subjects
end
class Subject< ActiveRecord::Base
belongs_to :subject_structure
end
When i run the app i get the error undefined method subject_structure for #<Subject:0x9d3aa78>
Im creating an app for an existing database that already has the tables with data in it.
Add a space after the belongs_to.
Should be
class Subject < ActiveRecord::Base
belongs_to :subject_structure
end
There's a space missing on the belongs_to:
class Subject< ActiveRecord::Base
belongs_to :subject_structure
end
Also, Subject must have a foreign_key for SubjectStructure. Run this migration to create it:
rails g migration AddSubjectStructureIdToSubject subject_structure_id:integer
Add a space like:
class Subject < ActiveRecord::Base
belongs_to :subject_structure
end
I recently started creating a site where users will be able to join groups and be able to interact with the group. So far I have used devise for the users but I'm now wondering what do I use to create user profiles and even the groups profile. This is my first rails application and I just need some guidance on where to go from here? What tools will I need? What is the best way of doing this?
Rails is the only tool you need. First you'll need to create the other models in your application. From your description I see a UserProfile and a Group. Rails' generator command will stub those out for you:
$ rails generate model UserProfile
$ rails generate model Group
$ rails generate model Membership
Now you will have user_profile.rb and group.rb in your app/models directory, as well as migrations in db/migrate/create.rb. Next you'll need to tell rails what fields to create in the database by editing the migration script. You are free to include whatever you wish here, but you will at least want foreign keys to relate your data.
def CreateUserProfiles < ActiveRecord::Migration
create_table :user_profiles do |t|
t.belongs_to :user
...
and
def CreateMemberships < ActiveRecord::Migration
create_table :memberships
t.belongs_to :user
t.belongs_to :group
...
Now you can execute your migrations to create the database tables for you:
$ rake db:migrate
And you can use ActiveRecord association class methods to define those relationships in code, so that Rails will take care of the SQL for you.
app/models/membership.rb
class Membership < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
app/models/user.rb
class User < ActiveRecord::Base
has_one :user_profile
has_many :memberships
has_many :groups, :through => :memberships
...
end
app/models/group.rb
class Group < ActiveRecord::Base
has_many :memberships
has_many :users, :through => :memberships
end
app/models/user_profile.rb
class UserProfile < ActiveRecord::Base
belongs_to :user
end
Now you have all the tools in place that you need to give users profiles:
UserProfile.create(:user => User.first, :attr => "value", ...)
Or to put a user in a group:
group = Group.create(:name => "Group 1")
group.users << User.first
Use tools when they save you time, but learn to use the tool on which they all depend first–Rails. Check out the Rails Guides, they are excellent.
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.