Reputation: 150
I have a question about rails and how its relationships query builder, specifically how camel case is converted for the related calls.
Relevant Code
class CustomerPlan < ActiveRecord::Base
attr_accessible :customer_id, :plan_id, :startDate, :user_id
has_many :planActions
end
class PlanAction < ActiveRecord::Base
attr_accessible :actionType_id, :customerPlan_id, :notes, :timeSpent
belongs_to :customerPlan
belongs_to :actionType
end
The getters and setters work just fine, such as plan_action.actionType.name
will correctly pull from the related model. However customer_plan.planActions.each
returns the error:
SQLite3::SQLException: no such column: plan_actions.customer_plan_id:
SELECT "plan_actions".*
FROM "plan_actions"
WHERE "plan_actions"."customer_plan_id" = 1
The column is defined in the database as customerPlan_id
, was I just wrong to use this? It works for every other call, all my other relationships work fine. Even PlanAction -> CustomerPlan.
I ran through all the docs, and searched about every other source I know of. It would be simple enough to change my columns, I just want to know what's going on here.
Thank you for your time!
A quick fix for this is to just explicitly set the foreign_key.
has_many :planActions, :foreign_key => "customerPlan_id", :class_name => "PlanAction"
Still, I think I am missing some model naming convention somewhere, just can't seem to figure out what.
Upvotes: 2
Views: 139
Reputation: 6006
The Rails convention for DB column names is to use lowercase letters with words separated by an underscore (e.g. author_id
, comments_count
, updated_at
, etc).
I would highly recommend that you stick to the Rails conventions. This would make your life much easier. To change it to the rails convention, simply create a migration to rename the column to the appropriate style.
However, if you do want to use a custom style for the column name, rails provides the :foreign_key
option in the has_many relationship to specify the expected foreign column name:
class CustomerPlan < ActiveRecord::Base
has_many :plan_actions, :foreign_key => 'customerPlan_id'
end
You can also use the alias_attribute
macro to alias the column name, if you'd like to use a different model attribute name than the actual DB column name. But as I mentioned, I would recommend sticking to the rails convention as much as possible. You'll thank me later.
Upvotes: 1
Reputation: 17647
Rails has 3 basic naming schemes.
One is for constants, and it is ALL_UPPERCASE_SEPARATED_BY_UNDERSCORES
.
One is for Classes and it is AllCamelCaseWithNoUnderscores
.
One is for variables and method names, and is all_lowercase_separated_by_underscores
.
The reason that it is this way is not just for consistency, but also because it freely converts between them using these methods.
So, to make your posted code more rails-y:
class CustomerPlan < ActiveRecord::Base
attr_accessible :customer_id, :plan_id, :start_date, :user_id
has_many :plan_actions
end
class PlanAction < ActiveRecord::Base
attr_accessible :action_type_id, :customer_plan_id, :notes, :time_spent
belongs_to :customer_plan
belongs_to :action_type
end
Upvotes: 0