Rails + Postgres Relation Issue With Custom Foreign Key - mysql

I'm in the middle of a migration to Postgres from MySQL and i'v hit an issue that I just can't solve. I'm sure there is simple answer, but i'm stuck.
The Problem
I have a step model that belongs to a template model, but specifies a foreign key called template_uuid to match on the template tables uuid column.
This all worked fine on MySQL but now does not work on Postgres. Calling step.template would return the relevant template but now it returns nil
Both the uuid column on the template table and the template_uuid column on the step are UUID data types.
Example:
class Step < ActiveRecord::Base
belongs_to :template, :foreign_key => :template_uuid
So, I get nil when trying to call the association
step = Step.last
step.template => nil
But, I can query for the template using the template_uuid column, and it works just fine
Template.where(:uuid => step.template_uuid).first
So .. What am I missing here. The records and UUID's clearly line up so why does this relationship break now that i'm using Postgres. There is no physical foreign key on the database, but that's never mattered before.
Does anyone have any ideas?

I can't say why it worked before, but as long as you have also a custom primary_key on the associated model (other than :id), you have to provide that either
belongs_to :template, :primary_key => :uuid, :foreign_key => :template_uuid

Related

Rails Mysql2::Error Table doesn't exist When create new migration

I wrote a migration with the following (create new table named sources):
class CreateSources < ActiveRecord::Migration
def change
create_table :sources do |t|
t.string :name, null: false, default: ""
t.timestamps null: false
end
end
end
And then I modified my existing model :
class Property < ActiveRecord::Base
validates :source, allow_blank: true, inclusion: { in:
Source.all.map{ |source| source.name } }
I want to add validation to the property's source to only allow source from sources table.
And then when I run the migration, I got the following error:
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'sources' doesn't exist: SELECT `sources`.* FROM `sources`
The problem is query of source table is occured when it hasn't been initialized yet.
Any tips on how I can get the migration to run?
This is run on production level. so I might can't drop all the migration and rearrange it.
Rails version 4.2.5
SQL version 5.7
Keep in mind that your Source.all.map{ |source| source.name } is going to be executed when the Property class is being loaded. The Source class might not be properly initialized at that point and there might not be a proper database connection set up. Also, you'll only access Source.all once so you'd have to restart your app if you added a new Source.
Instead, validate by hand:
class Property < ActiveRecord::Base
validate :valid_source
private
def valid_source
return if(source.blank?)
return if(Source.where(name: source).exists?)
errors.add(:source, 'Unknown source') # Or whatever you want to say
end
end
That way you're checking the sources table at the right time.
Also, I wouldn't expect the error you're seeing to occur in a migration. Perhaps you're using a model inside a migration, that is to be avoided.
As an aside, is there particular reason that you don't have belongs_to :source instead? Copying the name around like that is very error prone, using a reference (hopefully backed by a foreign key in the database) would be much safer.
Have you defined Source model? I hope so.
Here the problem looks like the loading of Property class takes priority before
migration is run and hence the issue.

Need to change relation between DB tables

ok, so lets get the basics out of the way.
I'm running ruby 1.8.7, I'm using the sequel gem version '2.6.0'.
I have a table called Users and a table called Teams
Right now a user can have one team and as such it's relation is:
belongs_to :npt_team
However as part of a feature upgrade for teams I have to make it so Users can be apart of multiple teams.
What I want to know:
I can change it to one of the following:
:has_and_belongs_to_many
:many_to_many
:many_to_many_by_ids
which one is the best to use and why(because I like to know)?
Second of all what will happen to the DB in the tables when I change this?
Any thing else I should be wary of/know about?
I'm using the following mysql version:
mysql Ver 14.14 Distrib 5.6.29, for osx10.11 (x86_64) using EditLine
wrapper
EDIT:
Ooops forgot to mention a rather pertinent point.
I'm not using rails, I'm use an old frame work called Ramaze.
The answer to my question is:
to create the relationship I need to add the following to the Users table:
has_and_belongs_to_many(:npt_teams,
:join_table => :users_teams,
:class => 'NptTeam',
:left_key => :user_id,
:right_key => :npt_team_id)
many_to_many_by_ids :npt_teams, 'UsersTeams'
Create a new join table like so:
class UsersTeams < Sequel::Model
clear_all
set_schema {
primary_key :id
integer :user_id, :null => false, :default => 0
integer :npt_team_id, :null => false, :default => 0
}
create_table unless table_exists?
belongs_to :user
belongs_to :npt_team
end
and the relationship is created along with the join table.
I don't know if this is the best way to do it but It seems to work.
As for the second question, I don't know, the data currently in the DB seems to be unaffected.
Now I just need to move the current Team to the new table and that should be it.
As for what else I might need to know well I don't, becuase you know, those that do know have seen to know have not respond so I'm just going to have to wing it.
EDIT:
script to move data across:
User.all.each do |user|
join = UsersTeams.create(:user_id => user.id, :npt_team_id => user.npt_team_id)
puts join.inspect
join.save
puts user.npt_teams.to_a.map {|t|t.inspect}.to_s
end

Rails 4 ActiveRecord - how to see how is interpreted a database query?

I have these models:
teacher
class Teacher < ActiveRecord::Base
has_many :days
end
day
class Day < ActiveRecord::Base
belongs_to :teacher
end
And running these query:
active_teachers = Teacher.joins(:days).where("teacher.id" => found_teachers.pluck(:teacher_id).uniq, "days.day_name" => selected_day)
What the query (should) does: found_teachers is an array of all teachers with duplications, remove the duplicity and chose only those teachers that have classes on a respective day (selected_day contains a string, Monday for example).
Because the amount of data in the variable active_teachers is so big that I can't manually go record by record (and I am not sure that I built this query properly and it does exactly what I need), I am trying to find out how is this query translated to SQL from ActiveRecord.
Usually I see everything in the terminal where is running server for the Rails app, but as of now, I don't see there this query stated.
So the question is, how can I see how the ActiveRecord query is translated to SQL?
Thank you in advance.
To get details from a query you're typing, you can do:
query.to_sql
query.explain
You can use
ActiveRecord::Base.logger = Logger.new STDOUT
and run your query in rails console. So it prints out the sql queries in the console

What is the easiest way to insert data in MySQL using a ruby script

I did a ruby script that parses a lot of files in ruby data structures, like hashes for example.
I need to insert all this data in a MySQL database.
What I found:
mysql2
tmtm
dbi
Is there some native way to do this?
Thanks for any help
EDIT
Lets say that I have a hash with 100 entries like this:
hash = {"a" => 1, "b" => 2 ..., "c" => 100}
I would like to create a table at mysql with all this columns. I am afraid of Active Record is gonna be hard to do that.
PS: Im not using Rails, just a simple ruby script
If I were you, I would prefer ActiveRecord, because I don't have to clutter my code with lots of SQL statements. Besides activerecord makes life easier.
Set it up like this
require 'active_record'
ActiveRecord::Base.establish_connection(
:adapter => "mysql2",
:host => "host",
:username=>"user",
:password=>"user",
:database => "your_db"
)
Then use tables like this
class SingularTableName < ActiveRecord::Base
has_many :table_relationship
end
Then query like this
SingularTableName.all #=> all records
SingularTableName.first #=> first record
SingularTableName.where("query")
SingularTableName.create("...) #=> create a record/row
You can find more methods here => http://api.rubyonrails.org/classes/ActiveRecord/Base.html
Update:
To overcome plural table names and default primary key, you can use
class AnyName < ActiveRecord::Base
self.table_name = 'your table name'
self.primary_key = 'your primary key'
...
end

Thinking Sphinx "no field found in schema" error

I am pretty new to Sphinx.
Trying to find user with name "bob" and company_id "14".
Controller:
#users = User.search 'bob', :conditions => { :company_id => '14'}
Model:
define_index do
indexes :name
indexes :company_id
end
Error:
index user_core: query error: no field 'company_id' found in schema
I have the 'company_id' in table & I re-indexed everything several times.
When I am just searching for the 'name' everything works properly.
Just as another helpful hint: turns out I had to change the way I called Model.search(), since my field was listed as an attribute (i.e. using has), I needed to call the search method with :with instead of :conditions (for fields).
Attributes should be declared as:
has company_id
So, in you case:
Model:
define_index do
indexes :name
has :company_id
end
And one more helpful hint, if you happen to be an idiot like me:
If you are getting this error and you are correctly using attributes and fields, it may be that you forgot to restart your dev server after adding a new field to the index.