Trying to use multiple databases - getting ActiveRecord Connection Not Established - ruby

I'm trying to set up ActiveRecord so I can use multiple database connections in my application. I am not using Rails.
To do this, I set up an abstract class for each of my databases:
class BuoyDatabase < ActiveRecord::Base
self.abstract_class = true
establish_connection $database_config['buoy_database']
end
Then I inherit from the OneDatabase class:
class Buoy < BuoyDatabase
has_many :buoyDatas, :foreign_key => 'buoy_id'
end
class BuoyData < BuoyDatabase
belongs_to :buoy
end
I can successfully create and read instances of both Buoy and BuoyData, but I can't get any related records:
Buoy.find_by_id(...).buoyDatas # gives ActiveRecord::ConnectionNotEstablished
Details of the error:
ActiveRecord::ConnectionNotEstablished: ActiveRecord::ConnectionNotEstablished
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/connection_adapters/abstract/connection_pool.rb:409:in `retrieve_connection'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/connection_adapters/abstract/connection_specification.rb:107:in `retrieve_connection'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/connection_adapters/abstract/connection_specification.rb:89:in `connection'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/alias_tracker.rb:69:in `connection'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/alias_tracker.rb:54:in `initial_count_for'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/alias_tracker.rb:12:in `block in initialize'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/alias_tracker.rb:29:in `yield'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/alias_tracker.rb:29:in `default'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/alias_tracker.rb:29:in `aliased_name_for'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/alias_tracker.rb:17:in `aliased_table_for'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/join_helper.rb:15:in `block in construct_tables'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/join_helper.rb:14:in `each'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/join_helper.rb:14:in `construct_tables'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/association_scope.rb:53:in `add_constraints'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/association_scope.rb:33:in `scope'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/association.rb:99:in `association_scope'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/association.rb:88:in `scoped'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/collection_association.rb:367:in `find_target'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/collection_association.rb:324:in `load_target'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/collection_proxy.rb:51:in `load_target'
from /Users/admin/.rvm/rubies/ruby-1.9.3-head/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/associations/collection_proxy.rb:89:in `method_missing'

The workaround is to establish a connection on ActiveRecord::Base itself. It doesn't matter to which database the connection is made. This connection is only needed so that ActiveRecord can get the meta information necessary to handle associations and whatnot. You need not use the connection at all, once established.
This issue is a duplicate of ActiveRecord 3.1.0 multiple databases and the workaround is first described here: https://stackoverflow.com/a/7406374/29729

Related

null validation failed when attribute supplied rom-rb

I'm trying to get to grips with the rom-rb persistence library, using sqlite3.
I ran the following migration, which includes a NOT NULL constraint:
ROM::SQL.migration do
change do
create_table :users do
primary_key :id
column :name, String, null: false
column :age, Integer
column :is_admin, TrueClass
end
end
end
Here's my simple app.rb:
require 'rom'
rom = ROM.container(:sql, 'sqlite://db/my-db-file.db') do |config|
class Users < ROM::Relation[:sql]
schema(infer: true)
end
config.relation(:users)
end
users = rom.relations[:users]
puts users.to_a.inspect # => []
create_user = users.command(:create)
create_user.call( name: 'Rob', age: 30, is_admin: true )
puts users.to_a.inspect # never reached
Trying to run this script produced the following output:
Roberts-MacBook-Pro:my-rom-demo Rob$ ruby app.rb
[]
/Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:108:in `step': SQLite3::ConstraintException: NOT NULL constraint failed: users.name (ROM::SQL::NotNullConstraintError)
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:108:in `block in each'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `loop'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `each'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:156:in `to_a'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:156:in `block in execute'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:95:in `prepare'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:137:in `execute'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sequel-5.11.0/lib/sequel/adapters/sqlite.rb:189:in `block (2 levels) in _execute'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sequel-5.11.0/lib/sequel/database/logging.rb:38:in `log_connection_yield'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sequel-5.11.0/lib/sequel/adapters/sqlite.rb:189:in `block in _execute'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sequel-5.11.0/lib/sequel/database/connecting.rb:253:in `block in synchronize'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sequel-5.11.0/lib/sequel/connection_pool/threaded.rb:91:in `hold'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sequel-5.11.0/lib/sequel/database/connecting.rb:253:in `synchronize'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sequel-5.11.0/lib/sequel/adapters/sqlite.rb:180:in `_execute'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sequel-5.11.0/lib/sequel/adapters/sqlite.rb:146:in `execute_insert'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sequel-5.11.0/lib/sequel/dataset/actions.rb:1099:in `execute_insert'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/sequel-5.11.0/lib/sequel/dataset/actions.rb:399:in `insert'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/rom-sql-2.5.0/lib/rom/sql/relation/writing.rb:39:in `insert'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/rom-sql-2.5.0/lib/rom/sql/commands/create.rb:46:in `block in insert'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/rom-sql-2.5.0/lib/rom/sql/commands/create.rb:46:in `map'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/rom-sql-2.5.0/lib/rom/sql/commands/create.rb:46:in `insert'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/rom-sql-2.5.0/lib/rom/sql/commands/create.rb:31:in `execute'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/rom-core-4.2.1/lib/rom/command.rb:280:in `call'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/rom-sql-2.5.0/lib/rom/sql/commands/error_wrapper.rb:16:in `call'
from /Rob.rvm/gems/ruby-2.4.0#learn-rails/gems/rom-core-4.2.1/lib/rom/commands/composite.rb:17:in `call'
from app.rb:15:in `<main>'
Why does it think my name attribute is null when I'm providing it?
NOTE: I revised my answer after some testing and learning about ops gem versions
The reason you're getting a NULL CONSTRAINT error is because ROM does not
have a schema loaded for the the users table.
When you defined the container below
rom = ROM.container(:sql, 'sqlite://db/my-db-file.db') do |config|
class Users < ROM::Relation[:sql]
schema(infer: true)
end
config.relation(:users)
end
you defined two things, a relation class bound to a constant called Users and an auto generated relation with the same name but is actually registered inside the ROM container. Effectively the Users constant relation is being ignored. The reason this is important is because the auto generated relation isn't automatically inferring the schema from the database so when you go to write data out, the schema forces all of the unknown keys to be removed causing the error. All you're sending to the db is {}.
To fix the error just tell the relation to infer the schema - an example can be seen below.
require 'rom'
require 'rom/sql'
require 'sqlite3'
puts "ROM Version #{ROM::Core::VERSION}" # 4.2.1
puts "ROM Version #{ROM::SQL::VERSION}" # 2.5.0
puts "Sequel Version #{Sequel::VERSION}" # 5.11.0
puts "SQLite3 Gem Version #{SQLite3::VERSION}" # 1.3.13
opts = {
adapter: :sqlite,
database: 'c:/mydb.db'
}
rom = ROM.container(:sql, opts) do |c|
# Just another way to write the same users table
# c.gateways[:default].create_table(:users) do
# column :id, :integer, primary_key: true
# column :name, :string, null: false
# column :age, :integer
# column :is_admin, :bool
# end
c.gateways[:default].create_table :users do
primary_key :id
column :name, String, null: false
column :age, Integer
column :is_admin, TrueClass
end
c.relation(:users) do
schema(infer: true)
end
end
users = rom.relations[:users]
puts users.to_a.inspect # => []
create_user = users.command(:create)
create_user.call(name: 'Rob', age: 30, is_admin: true)
puts users.to_a.inspect # never reached
# Uncomment if you want to see the users schema
# puts users.dataset.db.schema(:users)
If you want to use standalone relation classes instead of the container config dsl then I suggest reading up on the Auto Registration system.
DATABASE CREATION ISSUE
There is a whole host of things that could be going on which could prevent a sqlite database from being created.
It could be a permissions issue
The directory structure might not exist
Sqlite might not be compiled to handle URI's (only matters if you are using file:// in your paths) [see sqlite docs]
My advice here is when working with sqlite and ROM, use the opts hash example from the script above and try and use a relative path from the current working directory. That seems to always work.

RSpec with FactoryGirl/Bot - undefined method 'user' on model that belongs to user through has_many :through

Trying to get into proper testing and figure out the ins and outs of basic RSpec with FactoryBot.
NOTE: The validation tests all passed previously and they're in the model files. I've just removed them for the sake of reducing clutter.
My models:
models/user.rb
has_many :fulfillments
has_many :milestones, through: :fulfillments
models/fulfillment.rb
has_many :milestones
belongs_to :user
models/milestone.rb
belongs_to :fulfillments
My Factories:
spec/factories/users.rb
require 'faker'
FactoryBot.define do
factory :user do
first_name Faker::Name.first_name
last_name Faker::Name.last_name
preferred_name Faker::Name.first_name
username Faker::Internet.user_name
email Faker::Internet.email
password 'password123'
password_confirmation 'password123'
factory :user_with_fulfillments do
transient do
fulfillments_count 3
end
after(:create) do |user, e|
create_list(:fulfillment_with_milestones, e.fulfillments_count, user: user)
end
end
end
end
spec/factories/fulfillments.rb
require 'faker'
FactoryBot.define do
factory :fulfillment do
title Faker::Lorem.words.join(' ')
description Faker::Lorem.sentences.join(' ')
promise Faker::Lorem.sentence
reason Faker::Lorem.sentence
association :user, factory: :user_with_fulfillments
trait :userless do
user nil
end
factory :fulfillment_with_milestones do
transient do
milestones_count 2
end
after(:create) do |fulfillment, e|
create_list(:milestone, e.milestones_count, fulfillment: fulfillment)
end
end
end
end
spec/factories/milestones.rb
require 'faker'
FactoryBot.define do
factory :milestone do
title Faker::Lorem.words.join(' ')
criteria Faker::Lorem.sentences.join("\n")
reason Faker::Lorem.sentence
deadline Faker::Date.forward(30)
association :fulfillment, factory: :fulfillment_with_milestones
end
end
One test that's giving me trouble (spec/models/milestone.rb)
require 'rails_helper'
RSpec.describe Milestone, type: :model do
it 'has a valid factory' do
expect(create(:milestone)).to be_valid
end
it 'validates attributes correctly' do
should validate_presence_of :fulfillment
should validate_presence_of :title
should validate_presence_of :criteria
end
end
Error I'm getting in ANY test that involves the milestones factory
Failures:
1) Fulfillment has a valid factory
Failure/Error: create_list(:milestone, e.milestones_count, fulfillment: fulfillment)
NoMethodError:
undefined method `user' for #<Milestone:0x00007f844d54f1b8>
# ./spec/factories/fulfillments.rb:22:in `block (4 levels) in <top (required)>'
# ./spec/factories/users.rb:19:in `block (4 levels) in <top (required)>'
# ./spec/models/fulfillment_spec.rb:6:in `block (2 levels) in <top (required)>'
2) Milestone has a valid factory
Failure/Error: expect(create(:milestone)).to be_valid
NoMethodError:
undefined method `user' for #<Milestone:0x00007f844d8d0b98>
# ./spec/models/milestone_spec.rb:6:in `block (2 levels) in <top (required)>'
3) Milestone validates attributes correctly
Failure/Error: should validate_presence_of :fulfillment
NoMethodError:
undefined method `user' for #<Milestone:0x00007f8450829700>
# ./spec/models/milestone_spec.rb:10:in `block (2 levels) in <top (required)>'
4) User can have fulfillments and milestones
Failure/Error: create_list(:milestone, e.milestones_count, fulfillment: fulfillment)
NoMethodError:
undefined method `user' for #<Milestone:0x00007f8450b7b9d0>
# ./spec/factories/fulfillments.rb:22:in `block (4 levels) in <top (required)>'
# ./spec/factories/users.rb:19:in `block (4 levels) in <top (required)>'
# ./spec/models/user_spec.rb:29:in `block (2 levels) in <top (required)>'
Finished in 0.26253 seconds (files took 5.19 seconds to load)
9 examples, 4 failures, 1 pending
Failed examples:
rspec ./spec/models/fulfillment_spec.rb:5 # Fulfillment has a valid factory
rspec ./spec/models/milestone_spec.rb:5 # Milestone has a valid factory
rspec ./spec/models/milestone_spec.rb:9 # Milestone validates attributes correctly
rspec ./spec/models/user_spec.rb:28 # User can have fulfillments and milestones
Mostly confused because I'm not sure where or why it's trying to call #user on an instance of Milestone. The factories create Fulfillments for a User, then Milestones for the Fulfillments.
PS: It's my first time posting to StackOverflow (I usually manage to find answers to my really simple questions) so feel free to let me know if there's anything I could do to make future questions clearer.
It turns out I'm an idiot. I had a
validates :user, :presence
on my Milestone model. No wonder why it was trying to call milestone.user
Forget this ever happened please. ]:
Try to define classes explicitly in your factories so that they are not guessed but known.
factory :user, class: User
and
factory :fulfillment, class: FulFillment

Active Record Could not find table

I'm learning Active Record and have written a simple example below:
#!/usr/bin/ruby
require 'active_record'
require 'sqlite3'
ActiveRecord::Base.establish_connection(
adapter: 'sqlite3',
database: 'test.sqlite3',
)
class Network < ActiveRecord::Base
end
network = Network.create(name: "Network1")
puts Network.all
but this results in an error message:
/var/lib/gems/2.1.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/sqlite3_adapter.rb:511:in `table_structure': Could not find table 'networks' (ActiveRecord::StatementInvalid)
from /var/lib/gems/2.1.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/sqlite3_adapter.rb:385:in `columns'
from /var/lib/gems/2.1.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/schema_cache.rb:43:in `columns'
from /var/lib/gems/2.1.0/gems/activerecord-4.2.5/lib/active_record/attributes.rb:93:in `columns'
from /var/lib/gems/2.1.0/gems/activerecord-4.2.5/lib/active_record/attributes.rb:98:in `columns_hash'
from /var/lib/gems/2.1.0/gems/activerecord-4.2.5/lib/active_record/inheritance.rb:205:in `subclass_from_attributes?'
from /var/lib/gems/2.1.0/gems/activerecord-4.2.5/lib/active_record/inheritance.rb:54:in `new'
from /var/lib/gems/2.1.0/gems/activerecord-4.2.5/lib/active_record/persistence.rb:33:in `create'
from test.rb:14:in `<main>'
What am I doing wrong?
Your database doesn't have the networks table. Thus ActiveRecord will throw that error when trying to persist your data.
You should use create_table method in order to create your table.
create_table(:networks) do |t|
t.column :name, :string
end

Association for table less model

I've been trying to implement the association at FrontEnd but as currently the application in not having any database directly connected with the website, so as a result we can not use the ActiveRecord and only using the ActiveModel for supporting the validations and core features of a Model. Now as we need to use the nested attributes which we are going to send along with an object, the addresses which are associated with the User, so for this we need to first define the association on the corresponding model. But after defining the association it is throwing exception of undefined method "has_many" on User model. I'm currently searching the way to implement it in our website and implement the logic of nested attributes.
It would be great if you can suggest me anything related to this or if you have met with such issue in the past.
I've also tried the approach using the gem https://github.com/softace/activerecord-tableless but not working for me. Also I've added a tableless.rb
tableless.rb
class Tableless < ActiveRecord::Base
def self.column(name, sql_type = nil, default = nil, null = true)
columns << ActiveRecord::ConnectionAdapters::Column.new( name.to_s, default, sql_type.to_s, null )
end
def self.columns()
#columns ||= [];
end
def self.columns_hash
h = {}
for c in self.columns
h[c.name] = c
end
return h
end
def self.column_defaults
Hash[self.columns.map{ |col|
[col.name, col.default]
}]
end
def self.descends_from_active_record?
return true
end
def persisted?
return false
end
# override the save method to prevent exceptions
end
But getting the following exception Exception:
Console Error:
ActiveRecord::ConnectionNotEstablished: ActiveRecord::ConnectionNotEstablished
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/connection_pool.rb:546:in `retrieve_connection'
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/activerecord-4.0.0/lib/active_record/connection_handling.rb:79:in `retrieve_connection'
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/activerecord-4.0.0/lib/active_record/connection_handling.rb:53:in `connection'
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/activerecord-4.0.0/lib/active_record/model_schema.rb:203:in `table_exists?'
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/activerecord-4.0.0/lib/active_record/attribute_methods/primary_key.rb:92:in `get_primary_key'
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/activerecord-4.0.0/lib/active_record/attribute_methods/primary_key.rb:77:in `reset_primary_key'
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/activerecord-4.0.0/lib/active_record/attribute_methods/primary_key.rb:65:in `primary_key'
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/activerecord-4.0.0/lib/active_record/attribute_methods/primary_key.rb:79:in `reset_primary_key'
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/activerecord-4.0.0/lib/active_record/attribute_methods/primary_key.rb:65:in `primary_key'
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/activerecord-4.0.0/lib/active_record/attribute_methods/write.rb:32:in `write_attribute'
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/activerecord-4.0.0/lib/active_record/attribute_methods/dirty.rb:70:in `write_attribute'
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/activerecord-4.0.0/lib/active_record/attribute_methods/write.rb:19:in `__temp__9646='
from /home/cis/API_OTGJ/Tableless/app/models/book.rb:13:in `block in initialize'
from /home/cis/API_OTGJ/Tableless/app/models/book.rb:12:in `each'
from /home/cis/API_OTGJ/Tableless/app/models/book.rb:12:in `initialize'
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/activerecord-4.0.0/lib/active_record/inheritance.rb:27:in `new'
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/activerecord-4.0.0/lib/active_record/inheritance.rb:27:in `new'
from (irb):19
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/railties-4.0.0/lib/rails/commands/console.rb:90:in `start'
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/railties-4.0.0/lib/rails/commands/console.rb:9:in `start'
from /home/cis/.rvm/gems/ruby-2.0.0-p0#website/gems/railties-4.0.0/lib/rails/commands.rb:64:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
It seems that you forgot to call the method
has_no_table
On your model, as per https://github.com/softace/activerecord-tableless#usage. In their example:
class ContactMessage < ActiveRecord::Base
has_no_table
column :name, :string
column :email, :string
validates_presence_of :name, :email
end
Hope this helps. =)

has n of Strings in DataMapper

I'm writing a client for a web service, and part of their model is a list of strings belonging to a user containing previous usernames the user went by. I'm trying to use DataMapper for my client gem, and my first thought was to use DataMapper's has n syntax, but I can't seem to apply this to Strings. Is there a better way of doing this perhaps?
My current code:
class User
include DataMapper::Resource
# Some Properties here
has n, :also_known_as, 'String'
end
The error this generates is this:
irb(main):001:0> require 'cloudsdale'
NoMethodError: undefined method `relationships' for String:Class
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/associations/one_to_many.rb:109:in `finalize'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/model.rb:782:in `block in finalize_relationships'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/support/subject_set.rb:210:in `block in each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/support/ordered_set.rb:319:in `block in each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/support/ordered_set.rb:319:in `each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/support/ordered_set.rb:319:in `each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/support/subject_set.rb:210:in `each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/model.rb:782:in `finalize_relationships'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/model.rb:137:in `finalize'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core.rb:281:in `block in finalize'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/support/descendant_set.rb:64:in `block in each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/support/subject_set.rb:210:in `block in each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/support/ordered_set.rb:319:in `block in each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/support/ordered_set.rb:319:in `each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/support/ordered_set.rb:319:in `each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/support/subject_set.rb:210:in `each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/support/descendant_set.rb:63:in `each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core.rb:281:in `finalize'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/cloudsdale-0.0.1/lib/cloudsdale.rb:19:in `<top (required)>'
from C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:60:in `require'
from C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:60:in `rescue in require'
from C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:35:in `require'
from (irb):1
from C:/Ruby193/bin/irb:12:in `<main>'irb(main):002:0>
The file that the error spawns from is this:
# Load in DataMapper
# Change the setup to meet your DB needs
require 'data_mapper'
DataMapper.setup(:default, 'abstract::')
# API objects
require 'cloudsdale/version'
require 'cloudsdale/api/api'
require 'cloudsdale/client'
# Models
require 'cloudsdale/models/user'
require 'cloudsdale/models/cloud'
require 'cloudsdale/models/avatar'
require 'cloudsdale/models/ban'
require 'cloudsdale/models/chat'
# Finalize DataMapper so the models Load
DataMapper.finalize
why do you use 'String' here?
has n, :also_known_as, 'String'
it make no sense, remove it:
has n, :also_known_as
if you want to set model, use :model option:
has n, :also_known_as, :model => ModelName
and i'm not sure you want to use String as model name.
most likely you need an extra model to keep user's previous names:
class UserAlias
include DataMapper::Resource
# ...
end
class User
include DataMapper::Resource
# ...
has n, :also_known_as, :model => UserAlias
end
If you want to be able to search for older usernames via the datamapper 1.x query DSL you need to define an additional model.
class User
include DataMapper::Resource
# ...
has n, :also_known_as, :model => UserNameHistory
end
class UsernameHistory
include DataMapper::Resource
property :id, Serial
property :name
belongs_to :user
end
If you do not need to query via the old usernames you can use a serialized large object. As a suggestion you could use the DataMapper::Property::YAML from dm-types like this:
class User
include DataMapper::Resource
# ...
property :also_known_as, YAML
end

Resources