Associations in DataMapper - ruby

I am having trouble with associations in the following code.
The error I'm getting is a comment on the last line of code.
Edit: I simplified the code...
require 'rubygems'
require 'data_mapper' # requires all the gems listed above
require 'pp'
DataMapper.setup(:default, 'sqlite:///Users/chris/Dropbox/HawkEye-DB Test/store.sqlite')
class Manufacturer
include DataMapper::Resource
property :id, Serial
property :name, String
has n, :products
end
class Product
include DataMapper::Resource
property :id, Serial
property :name, String
belongs_to :manufacturer
has 1, :productoptionset
end
class Productoptionset
include DataMapper::Resource
property :id, Serial
property :name, String
belongs_to :product
end
DataMapper.auto_migrate!
# Make some manufactureres
gortex = Manufacturer.create(:name => 'Gortex')
garmin = Manufacturer.create(:name => 'Garmin')
gps = garmin.products.create(:name => 'GPS Unit')
samegps = Product.get(1)
pp samegps.productoptionset.create # undefined method `create' for nil:NilClass (NoMethodError)

create is a class method (kind of like a static method in Java) so it can't be called on instances (or non instances in this case) :)
You could create your objects like this
class Manufacturer
include DataMapper::Resource
property :id, Serial
property :name, String
has n, :products
end
class Product
include DataMapper::Resource
property :id, Serial
property :manufacturer_id, Integer
property :name, String
belongs_to :manufacturer
has 1, :productoptionset
end
class Productoptionset
include DataMapper::Resource
property :id, Serial
property :product_id, Integer
property :name, String
belongs_to :product
end
DataMapper.auto_migrate!
# Make some manufactureres
gortex = Manufacturer.create(:name => 'Gortex')
garmin = Manufacturer.create(:name => 'Garmin')
garmin.products << Product.create(:name => 'GPS Unit')
samegps = Product.get(1)
samegps.productoptionset = Productoptionset.create(:name => "MyProductoptionset")

The has 1 creates an accessor productoptionsetwhich is initially nil rather than a collection. That nil has no method create. The collection has.
You can create and associate the ProductOptionSet via
Productoptionset.create(:name => 'Foo', :product => gps)

Related

DataMapper Error in Sinatra - NameError: Cannot find the child_model

Using Sinatra and DataMapper. This is my first time trying to use more than two model classes. Not sure what is causing the error. Thanks.
The error:
NameError: Cannot find the child_model ContactNote for Contact in contact_notes
The models:
class Contact
include DataMapper::Resource
property :id, Serial
property :fullname, Text, :required => true
property :email, Text
property :phone, Text
has n, :contact_notes
has n, :projects
end
class Contact_Note
include DataMapper::Resource
property :id, Serial
property :contact_content, Text, :required => true
property :created_at, DateTime
property :updated_at, DateTime
belongs_to :contact
end
class Project
include DataMapper::Resource
property :id, Serial
property :project_name, Text, :required => true
property :created_at, DateTime
property :updated_at, DateTime
belongs_to :contact
has n, :project_notes
end
class Project_Note
include DataMapper::Resource
property :id, Serial
property :project_content, Text, :required => true
property :created_at, DateTime
property :updated_at, DateTime
belongs_to :project
end
Datamapper makes expectations on class names based on ruby conventions. It expects your contact notes to be in a ContactNote class, while you've named it Contact_Note, hence the error it can't find ContactNote.

Ruby/Sinatra/DataMapper Many-to-Many how creating an object

I have 2 classes called User and Gig and also a joining table Usergig.
class Usergig
include DataMapper::Resource
property :id, Serial
belongs_to :user
belongs_to :gig
end
class Gig
include DataMapper::Resource
property :id, Serial
property :gigname, String
property :gigtext, Text
has n, :usergigs
has n, :users, :through => :usergigs
end
class User
include DataMapper::Resource
property :id, Serial
property :username, String
property :realname, String
has n, :usergigs
has n, :gigs, :through => :usergigs
end
And when i try to run:
post '/gig/add' do
user = User.get(1)
gig = user.gigs.create(:gigname => params[:gig_gigname], :gigtext => params[:gig_gigtext])
end
I get the error:
NoMethodError at /gig/add
undefined method `include?' for nil:NilClass
I've googled for about two hours now and read the DataMapper documentation.
Anyone know what i'm doing wrong?
In Usergig try the following:
belongs_to :user, :key => true
belongs_to :gig, :key => true
You forgot to call DataMapper.finalize...this is what you need to call after all your models are loaded. Rails does this for you, in Sinatra you must call it manually.

datamapper many-to-many table name

I'm making blog service with datamapper and defined Article and Tag model like below.
class Article
include DataMapper::Resource
property :id, Serial
has n, :tags, :through => Resource
end
class Tag
include DataMapper::Resource
property :id, Serial
has n, :articles, :through => Resource
end
And these relationships defined in 'article_tags' table.
How is that table name defined?
Why not 'articles_tags'?
Can I change table name without create custom table model class?
sorry for my poor english.
class Tag
include DataMapper::Resource
property :id, Serial
has n, :articles, 'Article',:child_key => [:article_id]
end
See: Customizing Associations.

Cannot find the child_model (NameError)

I am unable to determine why I am getting a name error here. I'm new to DataMapper, but trying to associations down. Any help is appreciated.
User:
class User
include DataMapper::Resource
property :id, Serial, :key => true
property :first_name, String
property :last_name, String
property :company, String
property :city, String
property :country, String
property :mobile_number, Integer
property :email_address, String
property :shahash, String
property :isRegistered, Boolean
belongs_to :event, :required => true
end
DataMapper.auto_upgrade!
Event:
class Event
include DataMapper::Resource
property :id, Serial, :key => true
property :name, String
property :occuring, DateTime
has n, :user
end
DataMapper.auto_upgrade!
I think the problem is you're calling DataMapper.auto_upgrade! after each model definition. When you call it after just defining one model, there's no child model there. Instead, you should define and/or require all your models and then do:
DataMapper.finalize # set up all relationships properly
# and do a basic model sanity check
DataMapper.auto_upgrade! # create database table if it doesn't exist
Add an init file in your models directory and move all of your your DataMapper.finalize statements to it (i.e. remove the finalize statement from your individual model files)
app/models/init.rb
require_relative 'file_name'
require_relative 'another_model_file_name'
DataMapper.finalize
Then in your application file require the init file
require_relative 'models/init'

Datamapper update enum

My model looks like this:
class Project
include DataMapper::Resource
property :id, Serial
property :title, String
property :slug, String
property :status, Enum[:open, :closed ], :default => :open
has n, :issues
end
How do I use Project.update() to change the status of the enum to closed?
Just like that:
Project.update(:status => :closed)

Resources