I have a many-to-many relation between Resumes and Educations which allows for the same education entry to appear on multiple resumes. When displaying Educations on a resume, I want the Educations to be ordered for that specific resume. To do this I set up a join table, Educations_Resumes, with the order information as a property.
However, when I try some like resume.educations I get the following error:
ActiveRecord::StatementInvalid: SQLite3::SQLException: near "order": syntax error:
SELECT "educations".* FROM "educations" INNER JOIN "educations_resumes" ON
"educations"."id" = "educations_resumes"."education_id" WHERE
"educations_resumes"."resume_id" = 2 ORDER BY educations_resumes.order
The models are setup as:
class Resume < ActiveRecord::Base
has_many :educations_resumes
has_many :educations, :through => :educations_resumes,
:order => 'educations_resumes.order'
end
class EducationsResume < ActiveRecord::Base
belongs_to :resume
belongs_to :education
end
class Education < ActiveRecord::Base
has_many :educations_resumes
has_many :resumes, :through => :educations_resumes
end
Any suggestions on how to correctly order resume.educations would be greatly appreciated
You are using a keyword as a column name:
http://www.sqlite.org/lang_keywords.html
Run a migration and change the column name:
rails g migration FixColumnName
This will give you a empty migration file that you should fill in with something like:
class FixColumnName < ActiveRecord::Migration
def change
rename_column :educations_resumes, :order, :ordering
end
end
Related
I have a Rails app with the following relationship:
region.rb
class Region < ActiveRecord::Base
has_many :facilities
end
facility.rb
class Facility < ActiveRecord::Base
belongs_to :region
end
I want to expand functionality a bit so that facilities can belong to more than one region at a time. I believe I can do this with a has_many_through relationship but I'm needing some guidance on converting the existing has_many into a has many through. I understand how to create and wire up the join table, but how would I take existing data and translate it?
So for instance. On a facility object there is region_id, since the facilities can belong to more than one region I'd probably need a region_ids field and shovel the collection of regions into that column which should then populate the other side of the association via the join table. I have this part pretty much figured out as far as moving forward and wiring up the association. But I'm unsure as to how to take existing data and translate it over so the app doesn't break when I change the model association.
Any advice would be greatly appreciated.
I suggest you to always use has_many :through instead of HBTM.
To establish this kind of relation you'll need the following set up:
# region.rb
class Region
has_many :facility_regions
has_many :facilities, through: :facility_regions
end
# facility.rb
class Facility
has_many :facility_regions
has_many :regions, through: :facility_regions
end
# facility_region.rb
class FacilityRegion
belongs_to :facility
belongs_to :region
end
Also, of course, you'll need to create a migration:
rails g migration create_facility_regions facility_id:integer region_id:integer
# in this migration create a uniq index:
add_index :facility_regions, %I(facility_id region_id), name: :facility_region
rake db:migrate
UPD
As to migration from one database state to another one.
I think it should not be a problem.
1) Do not delete the relations you had before (leave has_many :facilities and belongs_to :region in models).
2) When new table is created and new associations added to the classes (which I showed) create a new migration:
rails g migration migrate_database_state
3) Write the script, which will create new records in db (to reflect the current state of things):
ActiveRecord::Base.transaction do
Facility.where.not(region_id: nil).find_each do |facility|
next if FacilityRegion.find_by(falicity_id: facility.id, region_id: facility.region_id)
FacilityRegion.create!(facility_id: facility.id, region_id: facility.region_id)
end
end
4) Put this script into last created migration and run it (or in console without migration, effect would be the same).
5) After script is successfully run, create new migration in which you delete region_id from facilities table and remove these associations definitions (has_many :facilities and belongs_to :region) from models.
It must be it. I might have made some typos or so, make sure I did not miss anything and
You need to add another model, a "middle guy" called FacilityRegion.rb, like this:
facility.rb
class Facility < ActiveRecord::Base
has_many :falicity_regions
has_many :regions, through: falicity_regions
end
facility_region.rb
class FacilityRegion < ActiveRecord::Base
belongs_to :region
belongs_to :facility
end
region.rb
class Region < ActiveRecord::Base
has_many :falicity_regions
has_many :facilities, through: falicity_regions
end
If you want to use belongs_and_has_many relationship, you need to:
rails g migration CreateJoinTableRegionsFacilities regions facilities
Then,
rake db:migrate
Now, your relationships should be:
Region.rb:
class Region < ApplicationRecord
has_and_belongs_to_many :facilities
end
Facility.rb
class Facility < ApplicationRecord
has_and_belongs_to_many :regions
end
In order to populate the new join table, you will need to in your console:
Region.all.find_each do |r|
Facility.where(region_id: r.id).find_each do |f|
r.facilities << f
end
end
Now, you can either leave the columns region_id and facility_id in Facility and Region table, respectively, or you can create a migration to delete it.
I need to joins this two tables but I cant seems to get it right.
Model
class Registration < ActiveRecord::Base
has_many :region
end
class Region < ActiveRecord::Base
belongs_to :registration
end
what I have tried so far is this
`test = Region.joins(:registration)`
which will give me this result
[#<Region id: 1, name: "region1">, #<Region id: 1, name: "region1">]
It seem that i have certainly did join the two tables but my dilemma is I also need the index that belongs to Registration Model. the about results are only the index available in the Region Model.
I also tried it the other way around
test = Registration.joins(:region)
but it gives me a error
Unknown column 'regions.registration_id' in 'on clause': SELECTregistrations.* FROMregistrationsINNER JOINregionsONregions.registration_id=registrations.id``
and I do agree with this error cause i do not have a index registration_id
when you define belongs_to relationship in a table that table should have foreign_key of table to which it is belonging. So in your example if you have relation like Region belongs to registrations then regions should have registration_id. It looks like you have defined a wrong relationship.
So if you will define registration_id in Region and execute following query:
Region.joins(:registration)
You will see id of region table along with registration_id in the result
Hope this helps
Change the Registration model code
class Registration < ActiveRecord::Base
has_many :regions
end
Then you can use joins
test = Registration.joins(:region)
Hope it helps!
class Registration < ActiveRecord::Base
has_many :regions, inverse_of: :registration, dependent: :destroy
end
class Region < ActiveRecord::Base
belongs_to :registration, inverse_of: :regions
end
Then, make sure your Region table correctly shows its association to Registration with a registration_id column. If it doesn't contain the column, go ahead and create the following migration:
rails g migration add_registration_ref_to_regions registration:references
rake db:migrate
Now, you should be able to successfully query via:
Registration.joins(:regions) or Region.joins(:registration)
Cheers!
City model:
class City < ActiveRecord::Base
has_many :angels
def angel_count
angels.size
end
end
Angel model:
class Angel < ActiveRecord::Base
belongs_to :city, :counter_cache => true
attr_accessible :city_id
end
I able to access the angel_count method through the rails_admin list action, however it won't allow me to change the order direction like the other columns.
Looks like you are using counter_cache wrong way. Do you have angels_count column in cities table? If not, add the column and run migration. You should be able to sort by this column.
I'm getting stuck at trying to update an existing many to many record.
Project model:
class Project < ActiveRecord::Base
belongs_to :assignment
belongs_to :programmer
end
Programmer model:
class Programmer < ActiveRecord::Base
has_many :projects
has_many :assignments, :through => :projects
end
Assignment model:
class Assignment < ActiveRecord::Base
has_many :projects
has_many :programmers, :through => :projects
end
so I have data linked up like so:
p = Programmer.create(:name => "Mike")
p.assignments.create(:name => "homework4")
p.assignments[0] = Assignment.find_or_create_by_name("homework1")
p.save
so as you can see, I'm trying to update the association of Mike's first hw to "homework1". All the homework assignments are already in the assignments table so it shoud just find "homework1" and assign it to mike. unfortunately, when I type the third line there are no errors, but it doesn't update it. In memory, p.assignments == homework1, but in the DB it's still the same(even after p.save). The project's join table isn't changed at all.
the logs of mysql show this command being generated whenever I enter the 3rd line.
SELECT "assignments".* FROM "assignments" WHERE "assignments"."name" = 'homework1' LIMIT 1
there's no Update anywhere.... what am I doing wrong?
UPDATE
So I found out that I could just reference the join table directly to edit the links. Something along the lines of:
proj = p.projects.first
proj.assignment_id = 12
proj.save!
If you just want a reference to the object, then you need to edit your migration scripts (db/migrate). An example:
def self.up
create_table :configurations do |t|
t.string :name
t.references :project # This store just the id of the object.
t.timestamps
end
end
Don't forget to type:
rake db:migrate
I can't modify existing relations in RoR.
Db schema is users(id), books(id, title), ratings(user_id, book_id, rating)
Models are
class User < ActiveRecord::Base
has_many :ratings
end
class Rating < ActiveRecord::Base
belongs_to :user
belongs_to :book
end
class Book < ActiveRecord::Base
has_many :ratings
end
Creating new rating with book.ratings.build(:user_id => 1, :rating => 5); book.save works fine, but I can't modify existing rating with
r = book.ratings.where(:user_id => 1).first
r.rating = 5
book.save doesn't save corresponding rating and r.save raises error about column rating.id. Is there a way to make things work without modifying db schema?
The reason why you're getting the error is because your ratings table has data but doesn't have and id column.
Add and id column to your ratings table and save your change calling rating.save.