I am experiencing strange problems with a HABTM relationship in my application.
The two models concerned are Role and RoleType. When attempting to set the RoleTypes on a Role within my controllers I receive an error with the attached stack trace (see bottom).
Unfortunately I am unable to reproduce this error with a unit test, or a functional test. I've even tried creating a new project to test the exact bit of code, and still had no success reproducing the error. I've also checked out the code on another computer and run up against the same problems. This leads me to believe that the problem lies somewhere I haven't considered (i.e. outside the models / controllers / migrations etc).
I'm basically looking for any pointers anyone might be able to offer me. I've spent two and a half days (and counting) banging my head against the wall on this one. I'm aware that this problem appears similar to the below link but since there is no response to that thread, and since the stack trace is quite different I thought I'd try a post of my own.
I've simplified the code to attempt to isolate the issue; the specific bit of code I'm trying to run is:
role = Role.find(1) role_type = RoleType.find(1) role.role_types = [role_type]
The exception is raised on the last line as I try to assign the list of RoleTypes to the Role.
I'm running Lighttpd under XP with Rails 1.1.6 and Ruby 1.8.5
Thanks in advance for any assistance!
Hugh
My Role model:
class Role < ActiveRecord::Base has_and_belongs_to_many :role_types has_and_belongs_to_many :users has_many :permissions
ROLE_TYPE_REVIEWER = 'reviewer' ROLE_TYPE_CONCLUSION_REVIEWER = 'conclusion_reviewer' ROLE_TYPE_COMMUNITY_REVIEWER = 'community_reviewer' ROLE_TYPE_INTEREST_TAG_REVIEWER = 'interest_tag_reviewer' ROLE_TYPE_BATCH_ADMINISTRATOR = 'batch_administrator' ROLE_TYPE_USER_ADMINISTRATOR = 'user_administrator' ROLE_TYPE_USER_GROUP_ADMINISTRATOR = 'user_group_administrator' ROLE_TYPE_CITIZEN_ADMINISTRATOR = 'citizen_administrator' ROLE_TYPE_INTEREST_TAG_ADMINISTRATOR = 'interest_tag_administrator' ROLE_TYPE_COMMUNITY_ADMINISTRATOR = 'community_administrator' ROLE_TYPE_ROLES_ADMINISTRATOR = 'role_administrator' ROLE_TYPE_QUESTIONS_ADMINISTRATOR = 'question_administrator'
ROLE_TYPE_INTEREST_TAG_PROPOSER = 'interest_tag_proposer' ROLE_TYPE_COMMUNITY_PROPOSER = 'community_proposer' ROLE_TYPE_QUESTIONS_PROPOSER = 'question_proposer'
ROLE_TYPES = { ROLE_TYPE_REVIEWER => 'Reviewer', ROLE_TYPE_CONCLUSION_REVIEWER => 'Conclusion Reviewer', ROLE_TYPE_COMMUNITY_REVIEWER => 'Community Reviewer', ROLE_TYPE_INTEREST_TAG_REVIEWER => 'Interest Tag Reviewer', ROLE_TYPE_BATCH_ADMINISTRATOR => 'Batch Administrator', ROLE_TYPE_USER_ADMINISTRATOR => 'User Administrator', ROLE_TYPE_USER_GROUP_ADMINISTRATOR => 'User Group Administrator', ROLE_TYPE_CITIZEN_ADMINISTRATOR => 'Citizen Administrator', ROLE_TYPE_INTEREST_TAG_ADMINISTRATOR => 'Interest Tag Administrator', ROLE_TYPE_COMMUNITY_ADMINISTRATOR => 'Community Administrator', ROLE_TYPE_ROLES_ADMINISTRATOR => 'Role Administrator', ROLE_TYPE_QUESTIONS_ADMINISTRATOR => 'Question Administrator', ROLE_TYPE_INTEREST_TAG_PROPOSER => 'Interest Tag Proposer', ROLE_TYPE_COMMUNITY_PROPOSER => 'Community Proposer', ROLE_TYPE_QUESTIONS_PROPOSER => 'Question Proposer' } ROLE_NAMES = [ ROLE_TYPE_REVIEWER, ROLE_TYPE_CONCLUSION_REVIEWER, ROLE_TYPE_COMMUNITY_REVIEWER, ROLE_TYPE_INTEREST_TAG_REVIEWER, ROLE_TYPE_BATCH_ADMINISTRATOR, ROLE_TYPE_USER_ADMINISTRATOR, ROLE_TYPE_USER_GROUP_ADMINISTRATOR, ROLE_TYPE_CITIZEN_ADMINISTRATOR, ROLE_TYPE_INTEREST_TAG_ADMINISTRATOR, ROLE_TYPE_COMMUNITY_ADMINISTRATOR, ROLE_TYPE_ROLES_ADMINISTRATOR, ROLE_TYPE_QUESTIONS_ADMINISTRATOR, ROLE_TYPE_INTEREST_TAG_PROPOSER, ROLE_TYPE_COMMUNITY_PROPOSER, ROLE_TYPE_QUESTIONS_PROPOSER ]
CONTROLLERS = { :batches => BatchesController.public_instance_methods(false), :citizens => CitizensController.public_instance_methods(false), :communities => CommunitiesController.public_instance_methods(false), :interest_tags => InterestTagsController.public_instance_methods(false), :login => LoginController.public_instance_methods(false), :questions => QuestionsController.public_instance_methods(false), :roles => RolesController.public_instance_methods(false), :user_groups => UserGroupsController.public_instance_methods(false), :users => UsersController.public_instance_methods(false), :welcome => WelcomeController.public_instance_methods(false) }
def alter_permissions(values) result = self if values # delete all current permissions and create new ones self.permissions.each { |permission| permission.destroy } values.each {|value| value_split = value.split('-') self.permissions << Permission.new(:controller => value_split[0], :page_action => value_split[1]) } result = self.save! end return result end end
My Role migration:
class CreateRoles < ActiveRecord::Migration def self.up create_table :roles do |t| t.column :name, :string t.column :restricted, :boolean, :null => false, :default => false end Role.create(:name => 'Role 1') end
def self.down drop_table :roles end end
My RoleType model:
class RoleType < ActiveRecord::Base has_and_belongs_to_many :roles end
My RoleType migration:
class CreateRoleTypes < ActiveRecord::Migration def self.up create_table :role_types do |t| t.column :name, :string end RoleType.create(:name => 'Role 1') end
def self.down drop_table :role_types end end
The exception's stack trace:
ActiveRecord::AssociationTypeMismatch (RoleType expected, got RoleType): h:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.1/lib/ active_record/associations/association_proxy.rb:148:in `raise_on_type_mismatch' h:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.1/lib/ active_record/associations/association_collection.rb:137:in `replace' h:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.1/lib/ active_record/associations/association_collection.rb:137:in `each' h:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.1/lib/ active_record/associations/association_collection.rb:137:in `replace' h:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.1/lib/ active_record/associations.rb:944:in `role_types=' h:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.1/lib/ active_record/associations.rb:954:in `send' h:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.1/lib/ active_record/associations.rb:954:in `role_type_ids=' /app/controllers/roles_controller.rb:50:in `update' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/base.rb:1095:in `send' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/base.rb:1095:in `perform_action_without_filters' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/filters.rb:632:in `call_filter' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/filters.rb:638:in `call_filter' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/filters.rb:438:in `call' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/filters.rb:637:in `call_filter' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/filters.rb:638:in `call_filter' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/filters.rb:438:in `call' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/filters.rb:637:in `call_filter' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/filters.rb:638:in `call_filter' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/filters.rb:438:in `call' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/filters.rb:637:in `call_filter' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/filters.rb:619:in `perform_action_without_benchmark' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/benchmarking.rb:66:in `perform_action_without_rescue' h:/ruby/lib/ruby/1.8/benchmark.rb:293:in `measure' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/benchmarking.rb:66:in `perform_action_without_rescue' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/rescue.rb:83:in `perform_action' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/base.rb:430:in `send' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/base.rb:430:in `process_without_filters' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/filters.rb:624:in `process_without_session_management_support' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/session_management.rb:114:in `process' h:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/ action_controller/base.rb:330:in `process' h:/ruby/lib/ruby/gems/1.8/gems/rails-1.2.1/lib/dispatcher.rb:41:in `dispatch' h:/ruby/lib/ruby/gems/1.8/gems/scgi_rails-0.4.3/bin/scgi_service: 23:in `process_request' h:/ruby/lib/ruby/1.8/thread.rb:135:in `synchronize' h:/ruby/lib/ruby/gems/1.8/gems/scgi_rails-0.4.3/bin/scgi_service: 21:in `process_request' h:/ruby/lib/ruby/gems/1.8/gems/scgi_rails-0.4.3/lib/scgi.rb:291:in `read_header' h:/ruby/lib/ruby/gems/1.8/gems/scgi_rails-0.4.3/lib/scgi.rb:253:in `handle_client' h:/ruby/lib/ruby/gems/1.8/gems/scgi_rails-0.4.3/lib/scgi.rb:234:in `initialize' h:/ruby/lib/ruby/gems/1.8/gems/scgi_rails-0.4.3/lib/scgi.rb:234:in `new' h:/ruby/lib/ruby/gems/1.8/gems/scgi_rails-0.4.3/lib/scgi.rb:234:in `handle_client' h:/ruby/lib/ruby/gems/1.8/gems/scgi_rails-0.4.3/lib/scgi.rb:188:in `listen' h:/ruby/lib/ruby/gems/1.8/gems/scgi_rails-0.4.3/lib/scgi.rb:186:in `initialize' h:/ruby/lib/ruby/gems/1.8/gems/scgi_rails-0.4.3/lib/scgi.rb:186:in `new' h:/ruby/lib/ruby/gems/1.8/gems/scgi_rails-0.4.3/lib/scgi.rb:186:in `listen' h:/ruby/lib/ruby/gems/1.8/gems/scgi_rails-0.4.3/lib/scgi.rb:412:in `run' h:/ruby/lib/ruby/gems/1.8/gems/scgi_rails-0.4.3/bin/scgi_service: 61 h:/ruby/bin/scgi_service:18:in `load' h:/ruby/bin/scgi_service:18