I am new to DataMapper and Ruby, and have been struggling to work out a way to format the expression which will give me what I am after. Let me explain. I have two Models in my project:
Class Manufacturer
include DataMapper::Resource
property :id, Serial
property :name, String
...<snip>...
has n, :items
end
Class Item
include DataMapper::Resource
property :id, Serial
property :name, String
...<snip>...
belongs_to :manufacturers
end
What I am trying to get is a collection which will give me the list of all manufacturers, plus a count of all items that they have produced. e.g.:
"Acme Industries", 32
"Bart Enterprises", 12
"Coco Mondo", 0
"XYZ Corp.", 55
That is, the :name from the Manufacturer model, and the count(:id) from the Item model. I've got as far as:
Manufacturer.all.items.aggregate(:manufacturer_id, :all.count)
which gives me the :manufacturer_id property and the correct count of items. Close, but no banana.
How can I get the manufacturer name rather that the id property in this case?
I tried to learn how to use DataMapper a month ago and I could find very limited support in stackoverflow and in the internet. It turns out that the project is not supported any more and the team behind is now developing another orm called ROM.
Since you are in the beginning I would recommend you to use another orm with better support(sequel,ActiveRecords etc)
Related
I am using plain Ruby. I have a "Restaurant" class that needs to be associated with at least 10 instances of a "Dish" class.
class Restaurant<ActiveRecord::Base
has_many :dishes
validates :dishes, :length=>{:minimum=>10}
end
requires a dish to have a minimum of 10 characters, rather than an array of associated dishes to have a length of at least 10.
I have two models that are associated via a has_many relationship. E.g.
class Newspaper < ActiveRecord::Base
has_many :articles
end
class Article < ActiveRecord::Base
belongs_to :newspaper
validates :uid, presence: true,
uniqueness: { case_sensitive: true }
end
A newspaper is updated several times a day but we only want to construct and add articles to the association that do not already exist. The following code was my first cut of achieving this.
new_articles.each do |article|
unless newspaper.articles.exists? uid: article.uid
newspaper.articles.build(uid: article.uid)
end
end
The newspaper object is either new and unsaved, or retrieved with existing relationships at this point.
My tests indicate that I am able to add two articles to the newspaper that have the same UID using the code above and this is obviously not want I want.
I appears to me that my current code will result in a validation failure upon being saved as the validation looks at uniqueness across the entire articles table and not the association.
What I'm struggling to understand is how the exists? method behaves in this scenario (and why it's not saving my bacon as I planned). I'm using FactoryGirl to build a newspaper, add an article and then simulate an update containing an article with the same uid as the article I've already added. If the code works I should get only one associated article but instead I get two. Using either build or create makes no difference, thus whether the article record is already present in the database does not appear to change the outcome.
Can anyone shed some light on how I can achieve the desired result or why the exists? method is not doing what I expect?
Thanks
The association exists? actually creates a scoped query, as per the association. This is why your existing articles filter doesn't work.
unless newspaper.articles.exists? uid: article.uid
# `articles.exists?` here will produce this if the newspaper is new
# ... WHERE "articles"."newspaper_id" IS NULL AND "articles.uid" = '<your uid>'
# and this, if the newspaper is persisted (with an id of 1)
# ... WHERE "articles"."newspaper_id" = 1 AND "articles.uid" = '<your uid>'
The case of the new newspaper is clearly wrong, as it would only return articles with a nil newspaper ID. But the persisted case is probably undesirable as well, as it still unnecessarily filters against newspaper ID, when you real concern here is that the UID is unique.
Rather, you probably want simply against Article, rather than scoping the exists? through the association, like:
unless Article.exists? uid: article.uid
Concerning your other problem:
this appears to be a FactoryGirl problem where the create method isn't creating db entries in the same way I can in the irb.
FactoryGirl.create should still abide by validations. It might help to see your test.
I need pages to be attached to layouts only when users opting for this.
I mean when users editing pages, there are a dropdown to select layout from.
It works well if some layout selected.
However if user selecting <option value='0'> None option,
DataMapper throw an error saying layout_id should be greater than zero.
I think this should not happen cause i set required: false on belongs_to :layout association.
Here are my models:
class Layout
include DataMapper::Resource
property :id, Serial
property :name, String
end
class Page
include DataMapper::Resource
property :id, Serial
property :name, String
belongs_to :layout, required: false
end
You right about "under-the-hood" validation.
It is automatically added by belong_to association.
And you can get rid of it by redefining layout_id property.
In Page model simply add:
property :layout_id, Integer, index: true
This will keep the association but will redefine layout_id property
so it wont have automatically added validations on it.
However note that this will work only after Page.auto_migrate!
Or you can manually remove foreign key from your pages table.
Also, make sure layout_id is a index, otherwise you'll have performance issues.
Whatever columns/types/relations i'm using within my DataMapper models i'm always get same fatal error:
undefined method `include?' for nil:NilClass
a sample model:
class Book
include DataMapper::Resource
property :id, Serial
property :name, String
end
Even with this trivial model i get that weird error.
Latest datamapper, reinstalled to be sure it is no broken somehow.
Ruby 1.9.3
Mysql 5
Sequel works just well on same environment.
did you call DataMapper.finalize after defining your models?
try:
class Book
include DataMapper::Resource
property :id, Serial
property :name, String
end
DataMapper.finalize # this is required on any scenario
Official docs:
http://datamapper.org/getting-started.html
See Finalize Models at the bottom
I have a Box, with many toys of various types:
class Box
embeds_many :toys
end
class Toy
field :name
embedded_in :box
end
class Car < Toy
end
class Doll < Toy
end
If I have found the specific box object I want, how do I query it to find just the cars?
my_box.toys.where(??? Car ??? )
Obviously I could iterate over each toy and extract the ones where toy.is_a? Car, but I'm looking for a solution, if one exists, that just uses the built in mongoid criteria/finders.
Thats a good question. luckily Mongoid used to store _type meta attribute in the document to handle these kind of scenarios
so you can find the cars in the box by
Box.where('toys._type'=>'Car')
Thats all