I'm running an import script which imports a CSV dump of a database into a local sqlite database using DataMapper.
My models look like this:
class Staff
include DataMapper::Resource
property :staff_id, String, :key => true
property :full_name, String
end
class Project
include DataMapper::Resource
property :project_id, Integer, :key => true
property :title, String
property :status, String
belongs_to :staff
end
The CSV contains the primary key so when I'm do the import I'm using that as it's key. Next time I run the import I clear the tables and start again, however datamapper moans because the primary keys have already been taken.
Is there a way to stop datamapper moaning about this or should I just delete the .db file and re-create an empty .db file just before the import runs? If so what's the easiest way to do this.
You can use DataMapper.auto_migrate! to blow away the tables, and then recreate them matching the current model state. The new tables will be empty of any data from previous runs.
So just after you define your models, but before you begin importing the data do something like the following:
DataMapper.finalize.auto_migrate!
If you create the complete DB from the import, I'd really recommend nuking the database completely to avoid any spill-over from earlier runs. This also keeps your build-db code path well tested.
Related
I am using Cequel as ORM for Cassandra without rails.
I have a problem when trying to create a simple list of projects.
First I defined the model with three columns which should belong to a compound key.
class Project
include Cequel::Record
key :client, :text, { partition: true }
key :type, :text, { partition: true }
key :dep, :text, { partition: true }
end
Later when I try to create the Project via
project = Project.create!({client: "test", type: "test", dep: "test"})
I get an error that the table does not exist.
The tables are not created automatically with Project.create! but I have to create the table manually first:
connection.schema.create_table(:projects) do
partition_key :client, :text
partition_key :type, :text
partition_key :dept, :text
end
But this syntax is different from the documented Record definition and I only found it by sifting through the source code. But this creates two problems.
Code overhead
I don't know the syntax for has_many and belongs_to so I cannot create the table correctly if the Record includes this
Am I overlooking a method to create the table automatically from the Project class definition?
The tables can be created by calling the method synchronize_schema on the class. So, in your case, you should execute Project.synchronize_schema before actually attempting to read/write into it.
Given that you are building a broader project, you can consider using Rake tasks for it. You also need to migrate so that the tables are actually created in Cassandra. You can use rake cequel:migrate for that. There are more tasks which you can see via rake --tasks.
If you are creating your custom project with custom places for models, you probably need to hack the rake migration task a little. This is an implementation that I did for my project https://github.com/octoai/gems/blob/master/octo-core/Rakefile#L75. Also take a look at how models are defined https://github.com/octoai/gems/tree/master/octo-core/lib/octocore/models
Hope this helps.
Is it possible with datamapper to generate the models from an existing database schema? So, to do the inverse of a migration, which takes the models and generate the sql. What I want is given a database schema generate the models.
try to check https://github.com/yogo/dm-reflection or any of its forks ..
At last, I found that till now the best solution is to use dm-is-reflective plugin: https://github.com/godfat/dm-is-reflective.
It doesn't generate the code for DataMapper models reflecting an existing database schema, but its properties access methods are automatically available (as long as you keep using this plugin, of course).
Here is an example of use:
require 'data_mapper'
require 'dm-is-reflective'
DataMapper.setup(:default, "postgres://user:pwd#localhost/db")
class Table
include DataMapper::Resource
is :reflective #activate dm-is-reflective
reflect #reflects eeach property. You can be more specific (look at plugin documentation)
end
DataMapper.finalize
#Even if no field is defined, all of them are accessible
entry = Table.first(nil, {:id => 469})
print entry.anotherField
If I am using DataMapper, and I have two databases, is there any way using migration.rb to copy a table for example table person from database 1 to database 2? (same schema and table values).
Referring this:https://github.com/datamapper/dm-migrations/blob/master/examples/sample_migration.rb
It only tells me how to add/modify/drop tables.
Thanks for help.
I don't think that's the intention of dm-migrations. I believe the easiest way would be something like this:
DataMapper.setup(:default, db1_config)
DataMapper.setup(:new, db2_config)
class Foo
include DataMapper::Resource
property :id, Serial
property :name, String
...
end
DataMapper.finalize
Foo.each do |foo|
DataMapper.repository(:new) do
# It may not let you set the "id" attribute here...
Foo.create(foo.attributes)
end
end
Edit
In hindsight, I'm not sure if you were asking how to to copy table structure as to opposed to table data. This is obviously copying table data.
I am working on a sinatra app with datamapper connected to a mysql database and am having problems retrieving/finding records from only one specific table. I can insert into it with datamapper find but when I try to do #sleepEntries = Sleep_Log.all I get the following error: ArgumentError: argument out of range. When I load everything into irb I get the same error. I also turned on the ability to see the queries and I get back SELECT id, start_time, length, timestamp FROM sleep_logs ORDER BY id when I call Sleep_Log.all. When I connect to the mysql database through the mysql command line tool I can confirm that there are entries in that table. When I run the query that datamapper is erroring out on I have no problem getting the results. Here is my datamapper model info for Sleep_Log
class Sleep_Log
include DataMapper::Resource
property :id, Serial
property :start_time, Time, :required => true
property :length, Integer, :required => true
property :timestamp, DateTime, :writer => :private
belongs_to :user
end
This is what the table looks like in the database accessed through describe sleep_logs;
What is weird is that retrieve results from all other tables.
The backtrace from irb
If you try Sleep_Log.first, do you get the error? If so, could you paste in the record, or one which also shows the error?
How was the table constructed? Are you using DM to inspect already entered records? Or are you entering them through DM too?
We just encountered the exact same problem. In our case it turned out that you have to use DateTime. Mysql doesn't have a Time database type and saves as DateTime. However, DataMapper doesn't get it and blows up. If you switch your model to use DateTime DM will get it.
I am working with a database that is already in place and used by other applications.
The people who designed the database did not use pluralized table names, so DataMapper chooses the wrong table name when following associations.
For instance:
class Foo
has n :components # => the table name here should be COMPONENT, but datamapper uses COMPONENTS
end
How do I change this behavior?
Change the name on the model itself.
class Component
# ...
storage_names[:default] = 'component'
end