Rails 2.1 belongs_to primary key - ruby-on-rails

I have a basic database with a structure like this.
products
------------------
id
serial
order
------------------
id
product_serial
Unfortunately, I cannot change structure of the DB. I looked at the docs for Rails 2.1 and it said I could setup a relationship like this.
belongs_to :product,
:class_name => 'Product',
:foreign_key => 'product_serial',
:primary_key => 'serial'
However, that gives me this error.
Unknown key: primary_key
Without the primary key it produces this SQL
SELECT * FROM `products` WHERE (`products`.`id` = #{serial})
How do I setup a belongs_to relationship on this?
EDIT For the record, I am working in Rails 2.1. (I know, don't tell me).

If you check the available options for the belongs_to association for the Rails 2 branch, you'll see that :primary_key is not one of them.
It should be enough, in your case, to simply state the foreign key as you did in the previous line.

Your order model does not have a field (and thus method) which is called serial. You don't need to specify it, then it defaults to id (which you do have).

Related

Does a model have to be linked to another model or can it be linked to a table based on the same model?

I am trying to debug a big application running on RoR. In my model Text I have this relation :
has_many :copies, :foreign_key => :original_id
does this mean that there must be another model in my app called Copie (should be Copy...) to which it is linked through the foreign_key or could it be just a link to another table which uses the same model Text?
In most cases, yes. There would be a Copy model. You can point it to a different model though, by using the class_name option
Usually, if it has a reference to a different table, the class_name keyword would have been used. For example: has_many :copies, :class_name => 'YourOtherModel', :foreign_key => :original_id
By convention, Rails assumes that the column used to hold the foreign key on the other model is the name of this model with the suffix _id added.
Rails does provide you with the ability to set the :foreign_key option directly:
See documentation here
You can also design a data model to have to relation to itself:
See documentation here
I hope this provide you with some insight to further investigate

Rails 3 - acts_as_tenant with custom tenant ID column

Has anyone successfully used the Rails acts_as_tenant gem for multitenancy, where the tenant ID column is not named xxx_id?
my model is something like
has_one :tenant, :foreign_key => "tenant_code"
acts_as_tenant :tenant
Then I get my query select * from [table] where tenant_id = xxx ignoring the overridden foreign_key spec.
Is there any way to fix this? or am I doing something else obviously wrong?
Thanks!!
Just as an update to this issue for future reference:
From gem version 0.3.3 onwards it is now possible to explicitly set the foreign key.
acts_as_tenant(:account, :foreign_key => 'accountID')
Perhaps this helps someone who finds this question.
ActsAsTenant sets it's own foreign key in the gem itself as (pseudocode) #{tenant_klass}_id:
def self.fkey
"#{##tenant_klass.to_s}_id"
end
https://github.com/ErwinM/acts_as_tenant/blob/master/lib/acts_as_tenant/model_extensions.rb#L12-L14
Unfortunately, I don't believe you can set your own foreign key for anything other than activerecord model relationships (with your code, you could still theoretically call model.tenant; however, that doesn't help you).

has_many :through - sql statement using NULL id

We recently upgraded our rails app from version 3.0.3 to 3.1.0. The application runs successfully for the most part as it did before with one major exception. We have a many-to-many relationship between two models, SurveyDatum and SubGroup, joined via a model called SubGroupSurveyDatum. Here is the code for each:
class SurveyDatum < ActiveRecord::Base
has_many :sub_group_survey_data
has_many :sub_groups, :through => :sub_group_survey_data
end
class SubGroup < ActiveRecord::Base
has_many :sub_group_survey_data
has_many :survey_data, :through => :sub_group_survey_data
end
And as you might expect:
class SubGroupSurveyDatum < ActiveRecord::Base
belongs_to :survey_datum
belongs_to :sub_group
end
If I have a SurveyDatum object that I retrieved previously from the database (lets call it 'sd'), and I invoke the sub_groups method (sd.sub_groups), this is the resulting sql query generated by active record:
SELECT `sub_groups`.* FROM `sub_groups` INNER JOIN `sub_group_survey_data` ON `sub_groups`.`id` = `sub_group_survey_data`.`sub_group_id` WHERE `sub_group_survey_data`.`survey_datum_id` IS NULL
The "IS NULL" part is obviously where the id of my survey data object is supposed to go, however active record fails to use it. The object does indeed have an id, since as mentioned it was persisted and retrieved from the database. This problem only cropped up after we moved to rails 3.1, so I assume there's something I've not done properly in accordance with the new version, but I have no idea. Any ideas? Thank you in advance for your help!
Hmm I used rails 3.1.0 and tried to replicate but all was well. The only case was when I manually set id = nil on the record retrieved from the db. Then I got:
SELECT "authors".* FROM "authors" INNER JOIN "relations" ON "authors"."id" = "relations"."author_id" WHERE "relations"."post_id" IS NULL
What database are you using? I was trying this with sqlite3. Also watch out for certain gems especially those that work with ActiveRecord. I had trouble with this in the past.
We discovered the issue. I had forgotten that the survey_data table has a composite primary key. When we upped to version 3.2.3, and added in the SurveyDatum model the following:
set_primary_key :id
The query finally built and executed properly.

Custom keys for Mongoid association

I need to associate two models with a simple has_many. The problem is that I don't want to use the id (_id) as the primary key for the association. I still want the model to keep using the default ObjectIds for everything else.
(This is running on Rails3.1 + Mongoid)
So basically I want:
class Message
...
field :message_id, :default => proc { "fail-#{Time.now.to_f.to_s}" }
...
has_many :message_reports, primary_key: :message_id, foreign_key: :message_id
...
end
class MessageReport
...
field :message_id, :default => proc { "fail-#{Time.now.to_f.to_s}" }
...
has_many :message, primary_key: :message_id, foreign_key: :message_id
...
end
This would only work for ActiveRecord. Mongoid don't support the primary_key option.
So how do I get the same results for Mongoid collections?
Before you say: don't do that...
The reason I really really need to kay on this field and not the proper id is that these are messages... and the message_ids are unique ids returned by the API I call to send a message. Later the same id is received in callbacks from the other side.
I could just do queries and stick it in a method to find the "associated" reports from a message and vice versa... I'd rather have them be actual associations, if possible.
I could force the report-recieving process to search for and match up the objects for the association... but I'd rather not put that responsibility there when it is kind-of superfluous and it has nothing more to do with this data besides validating and saving it.
In short: I'd prefer an association :)
This feature doesn't exist on Mongoid actually even on Master and it's not planned in Mongoid 3.0
Do some feature request. The Mongoid community is really open to add some new feature if it's a good idea. To me It's a good idea.

has_many and a legacy scheme

I'm looking for advice here:
I have two tables in legacy scheme, A and B, joined on A.somename = B.othername. Both of those columns are strings. So how do I set up relations between them in rails (v2.1.0)? Given that A has many B's, what would be the best practice:
use :finder_sql and just write a SQL select,
configure the relation through other parameters (how? I know I can set :foreign_key = 'othername', but that will just try to set up a A.id = B.othername relation - what can I do to set up the correct one?),
something else that has not crossed my mind.
So, what would you suggest?
If you're stuck with Rails 2.1 for some reason, the best option seems to be using set_primary_key, like this:
class A
set_primary_key 'somename'
has_many :bs, :foreign_key => 'othername'
end
There is also an alias that lets you use attribution-like syntax for that (self.primary_key = 'somename').
By the way, if you're able to upgrade to 2.3, you can use the primary_key option directly with has_many, like this:
has_many :debitos, :primary_key => 'somename', :foreign_key => 'othername'
If you choose to use this, you won't need to declare the primary key for the class using set_primary_key.

Resources