Datamapper Many-To-Many relation - datamapper

Article has many authors, editors, translaters, etc. All of class Person.
Is it possible to generate join model? Or, in this case, solution is to create each join models manually.
class Article
include DataMapper::Resource
property :id, Serial
property :published_date, Date
property :status, Enum[ :pending, :accepted, :declined, :modified, :new ], :default => :new
property :visible, Boolean, :default => false
timestamps :at
has n, :authors, 'Person', :through => Resource
end
class Person
include DataMapper::Resource
property :id, Serial
property :name, String
property :about, Text
property :gender, Enum[ :male, :female ]
property :birthday, Date
timestamps :at
has n, :articles, :through => Resource
end

looks like it impossible. Only manual model creation.

Related

storing values into a integer variable

I have a question about storing a value into a integer variable. Is it possible to store different id into the same variable ?
This is my problem, I would like to use a collection_select to save many id's.
My code is actually working for one variable, like this :
My code :
User model :
has_many :pins
scope :artist, -> { where(artist: true) }
Pin model :
belongs_to :user
Pin controller:
def new
#pin = Pin.new
#users = User.all.artist
end
def create
#pin = current_user.pins.build(pin_params)
if #pin.save
redirect_to #pin, notice: "successfully created!"
else
render 'new'
end
end
Pin/new(views):
<div class="form-group">
<%= f.collection_select(:pin_maker, #users, :id, :pseudo) %>
</div>
I would like something like that for my new views :
<div class="form-group">
<%= f.collection_select(:pin_maker, #users, :id, :pseudo, { }, {:multiple => true}) %>
</div>
But the variables are not saving in my sql table.
So my question is : That's possible to store many id in the same variable (:pin_maker) which is an integer ? Or should I create a new table for that ?
pin_maker is user ? if so:
(IMO): you need a n-to-n associations and a table users_pins.
Logic:
One user has many pins
One pin may be made by many users
On Rails:
Model User:
has_many pins, :through => :users_pins
Model Pin:
has_many users, :through => :users_pins
Try has_many :users to involve your associations

Multiple models accessing same table

I am new to Datamapper and Ruby on Rails. I have an en existing model A, now I want to create another version of model A, v2_A. The difference between A and V2_A is that I have changed a few belongs_to from A to v2_A by changing :required => true to :required => false like following.
class A
include DataMapper::Resource
property :p1, ...
...
belongs_to :b, :required =>true
end
class v2_A
include DataMapper::Resource
property :p1, ...
...
belongs_to :b, :required =>false
end
So basically all column names in resulting tables will be same. Whenever I am doing rake db:autoupgrade a new table v2_A is being created which is not desired. I am asking is it possible both of the models access the same table A i.e. I don't want v2_A to create another table just because of that.
i am not sure about DataMapper::Resource
But i guess in your model you can write
self.table_name = "name_of_your_table"
In both of the model.

How to set a foreign key in rails?

I'm trying to save a object that has a foreign key attribute. I do not understand why it's not working. The foreign key is defined as not null in the database.
class Store < ActiveRecord::Base
attr_accessible :latitude, :longitude, :description
validates :store_group, :presence => true
validates :description, :presence => true, :length => {:maximum => 500}
validates :latitude, :presence => true
validates :longitude, :presence => true
belongs_to :store_group
end
class StoreGroup < ActiveRecord::Base
attr_accessible :name, :description, :image
validates :name, :presence => { :message => "Store group can not be empty" }
end
So, I'm trying to save a store:
group = StoreGroup.new(:name=>"name",:description=>"description",:image=>"image")
store = Store.new(:store_group=>group,:latitude=>1,:longitude=>1,:description=>"description")
store.save
However, MySQL raises an exception:
Mysql2::Error: Column 'store_group' cannot be null: INSERT INTO `stores` (`created_at`, `store_group`, `description`, `latitude`, `longitude`, `updated_at`) VALUES ('2013-02-17 04:09:15', NULL, 'description', 1.0, 1.0, '2013-02-17 04:09:15')
Why?
Thanks in advance :)
You are trying to create/save store_group object through store. Thus use:
accepts_nested_attributes_for :store_group
in your Store model
Read here about accepts_nested_attributes_for
First off, it may be easier in the long run if you add a has_many :stores to StoreGroup, for instance if you ever want to retrieve all of the stores that belong to a particular StoreGroup. Secondly, you should add the store via its StoreGroup, and since you already have an association there it's fairly straightforward (note the change to Store.create):
group = StoreGroup.create(name: "name", description: "description", image: "image")
group.stores << Store.create(lat: 1, long: 1, desc: "description")
This method will automatically set :store_group_id and save the new Store instance as a "child" of its StoreGroup. Note that you'll also want to change your code to account for existing StoreGroups, so that you can add stores to existing StoreGroups later. Using .first_or_create with a .where(...) clause is idiomatic for rails 3.2.x, though there are dynamic finders with create powers in previous versions of Rails (find_or_create_by_name_and_store_group_id, as an example).
Lastly, remove validates :store_group because association validations don't work that way. If you really must, use validates :store_group_id.

How do you use a row from one table as a property in another table using Datamapper?

The specific instance I am referring to is here. I want to use a row from the Grid table to be the value of the Grid property in the Driver table. But I cannot get updates in the Grid table to persist through to the Grid property on the Driver table
I want to use a row from the Race table to be the value of the Race property in the Driver table.
Here is the code for the datamapper stuff.
require "rubygems"
require "json"
require "sinatra"
require "sinatra/reloader"
require "sqlite3"
require "data_mapper"
DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/season.db")
class Driver
include DataMapper::Resource
property :id, String, :key => true
property :ptd, Integer
property :races, Integer
property :grid, Object
property :race, Object
property :hcScore, Integer
property :domScore, Integer
end
class Grid
include DataMapper::Resource
property :id, String, :key => true
property :AUS_Q, Integer
property :MAL_Q, Integer
property :CHI_Q, Integer
property :BAH_Q, Integer
end
class Race
include DataMapper::Resource
property :id, String, :key => true
property :AUS_R, Integer
property :MAL_R, Integer
property :CHI_R, Integer
property :BAH_R, Integer
end
class Team
include DataMapper::Resource
property :id, String, :key => true
property :domScore, Integer
property :drivers, Object
end
DataMapper.finalize.auto_migrate!
In irb I will do something like
irb(main):001:0> require "./season.rb"
=> true
irb(main):002:0> v = Driver.create id: "VET"
=> #<Driver #id="VET" #ptd=nil #races=nil #grid=nil #race=nil #hcScore=nil #domScore=nil>
irb(main):003:0> g = Grid.create id: "VET"
=> #<Grid #id="VET" #AUS_Q=nil #MAL_Q=nil #CHI_Q=nil #BAH_Q=nil>
irb(main):004:0> v.grid = Grid.get "VET"
=> #<Grid #id="VET" #AUS_Q=nil #MAL_Q=nil #CHI_Q=nil #BAH_Q=nil>
irb(main):005:0> v.save
=> true
irb(main):006:0> g.update(:AUS_Q => 6)
=> true
irb(main):007:0> v
=> #<Driver #id="VET" #ptd=nil #races=nil #grid=#<Grid #id="VET" #AUS_Q=nil #MAL_Q=nil #CHI_Q=nil #BAH_Q=nil> #race=nil #hcScore=nil #domScore=nil>
irb(main):008:0> Grid.get "VET"
=> #<Grid #id="VET" #AUS_Q=6 #MAL_Q=nil #CHI_Q=nil #BAH_Q=nil>
irb(main):009:0> AUS_Q = 6 in the Grid table but in the Driver table it continues to be nil!
As you can see - AUS_Q in the Driver table continues to be nil even though I set it to be 6 in the Grid table.
Chances are I am doing it wrong and there is an easier way to do this. I encourage all corrections and smackdowns.
I would suggest that you use belongs_to to create association between resources, and that you use an identity map, like this:
require "sqlite3"
require "data_mapper"
class Driver
include DataMapper::Resource
property :id, String, :key => true
belongs_to :grid, :required => false
end
class Grid
include DataMapper::Resource
property :id, String, :key => true
property :AUS_Q, Integer
end
DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/season.db")
DataMapper.finalize.auto_migrate!
DataMapper.repository(:default) do
v = Driver.create id: "VET"
g = Grid.create id: "VET"
v.grid = Grid.get "VET"
v.save
g.update(:AUS_Q => 6)
puts v.grid.AUS_Q
puts Grid.get("VET").AUS_Q
end
Everything you do within the block initiated by DataMapper.repository(:default) do will use an identity map. Thus, identical objects in the database will result in identical objects in memory.

DataMapper association

I'm trying to design a schema for an email solution so that I could access the incoming and sent messages on the User object using DataMapper. The associations "inbox" and "sent" don't do what's intended. What am I doing wrong? Thanks in advance!
I've the following so far (after reading a bit and copying the friends example from DM website) --
class User
include DataMapper::Resource
property :id, Serial
property :name, String, :required=>true
property :email, String, :required=>true, :unique=>true
property :password, String, :required=>true
has n, :messages, :child_key=>[:source_id, :target_id]
has n, :inbox, 'Message', :through=>:messages, :via=>:target
has n, :sent, 'Message', :through=>:messages, :via=>:source
end
class Message
include DataMapper::Resource
property :id, Serial
property :subject, String, :required=>true
property :body, String
belongs_to :source, 'User', :key=>true
belongs_to :target, 'User', :key=>true
end
I'm answering my own question -- hope it helps someone
The following change fixes the problem I've been having --
class User
...
has n, :inbox, 'Message', :child_key=>[:target_id]
has n, :sent, 'Message', :child_key=>[:source_id]
end
Everything else, remains the same...