Rails server disregards default_repository_name on model?

63 views
Skip to first unread message

Bence

unread,
Jun 28, 2011, 7:48:44 AM6/28/11
to DataMapper
Hi,

I'm new to DataMapper and run into a confusing issue to which I didn't
find any answers.

I have two repositories (:default and :external).
Model "ext_model" is persisted in :external by setting the
default_repository_name in the model. The model works: the unit tests
are green and I can manipulate the model in the console without
problems.
When I run the unit tests on controller ext_model_controller#index, it
is green: retrieves all from ext_model, as it should.
But when I launch the webserver and browse to /ext_model_controller/
index, I get an error message, and I see that it is looking for
ext_model in the :default repository (instead of :external).
Shouldn't both the console and the server retrieve the model the same
way? Am I missing something? How do I set explicitly the repository on
the model so that the webserver uses that?
If I wrap the code inside ext_model_controller#index action in
DataMapper.repository(:external) {...} then it works, but shouldn't
this be unnecessary since I already explicitly assigned a repository
to the model?

Thanks in advance!

//Bence

Rails 3.0.9, dm 1.1.0

Chris Corbyn

unread,
Jun 28, 2011, 9:39:15 PM6/28/11
to datam...@googlegroups.com
I have a feeling this relates to the identity map solution in Rails, where all calls are wrapped inside a DataMapper.repository(:default) { ... } block. From DataMapper's perspective, you're inside such a block, and therefore it doesn't check default_repository_name. Is it possible to completely override #repository to return the one you want?

The problem, if this is the case, is that you lose the benefits of the IM, when working with multiple repositories.

> --
> You received this message because you are subscribed to the Google Groups "DataMapper" group.
> To post to this group, send email to datam...@googlegroups.com.
> To unsubscribe from this group, send email to datamapper+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/datamapper?hl=en.
>

Chris Corbyn

unread,
Jun 28, 2011, 9:41:08 PM6/28/11
to datam...@googlegroups.com
Note that you can disable that "everything is wrapped in a repository block" behaviour by removing this line from ApplicationController:

use Rails::DataMapper::Middleware::IdentityMap

You won't have an identity-map per-request if you do this though.


On 28/06/2011, at 21:48, Bence wrote:

kristian

unread,
Jun 29, 2011, 12:56:50 AM6/29/11
to DataMapper
what I do on almost all my projects (datamapper makes it to easy to
use morethen one repo) is that I am using nested IdentityMaps one for
the default and one for the :external repository

use 'Rails::DataMapper::IdentityMaps', :external
use 'Rails::DataMapper::IdentityMaps'

in order to "dispatch" the models onto the right repository I am
overwrite this method

def self.repository(name = nil, &block)
super(:external, &block)
end

so basically I bind the model to the :external repository in static
way. the same thing I do for transactions !

maybe that helps.

- Kristian

Bence

unread,
Jun 30, 2011, 6:26:46 AM6/30/11
to DataMapper
Thanks for the tip: it has solved the problem!

You mentioned completely overwriting the #repository - how do I do
that? The only solution I have seen so far was defining the
default_repository_name on the model. Again: I'm a beginner... :P

//B

Bence

unread,
Jun 30, 2011, 6:56:59 AM6/30/11
to DataMapper
Thanks!

I overrode the #repository as you described, and it seems to have done
the trick. I did this in the model - I guess this is what you meant by
"binding in a static way"?

Where do the "use 'Rails::...'" lines go? Are they required? I'm not
using them right now at all, and the repository seems to be the right
one on my external model.

//B

kristian

unread,
Jun 30, 2011, 11:30:16 PM6/30/11
to DataMapper
yes, the method I was talking about was in model.

now you are using no IdentiyMaps for the external repo and you can add
it by adding
"use Rails::..." in the ApplicationController. but make sure the order
is correct or use these #repository trick for ALL models.

- Kristian

Bence

unread,
Jul 1, 2011, 8:59:22 AM7/1/11
to DataMapper
Thanks, Kristian!

I meant the
use 'Rails::DataMapper::IdentityMaps', :external
use 'Rails::DataMapper::IdentityMaps'
lines you wrote. Where do the go? They don't seem to work in
ApplicationController just like that. I'm not certain how to set up
nested identity maps, and have not found examples...

/B

Chris Corbyn

unread,
Jul 1, 2011, 9:07:01 AM7/1/11
to datam...@googlegroups.com
They go inside ApplicationController, right inside the class body.

class ApplicationController < ActionController::Base


use 'Rails::DataMapper::IdentityMaps', :external
use 'Rails::DataMapper::IdentityMaps'

... rest of controller here ...
end

They're not essential, but that's what provides your identity map, so that when you fetch the same resource multiple times, you don't query the database repeatedly, and when that resource is changed, everybody sees the changes.

I have "use Rails::DataMapper::Middleware::IdentityMap" (singular) in my controller... I assume there is a pluralized version for when you're using multiple identity maps. This is just what the dm-rails template configures though.

Bence

unread,
Jul 1, 2011, 10:41:40 AM7/1/11
to DataMapper
I tested Kristian's two lines, but it broke the ApplicationController
with "uninitialized constant Rails::DataMapper::IdentityMaps" error.
Maybe I'm doing something wrong...

The standard "user Rails::DataMapper::Middleware:IdentityMap" and
enforcing the :external repo through self.respository in the model
works - I can access the model from the controller. I'm not certain,
though, whether the IM is used in this case?

Thanks again for your tips, guys! You helped me get over a frustrating
bump!

kristian

unread,
Jul 1, 2011, 11:46:12 PM7/1/11
to DataMapper
sorry for the late replies of my side - bad setup of the group for
me.

IdentityMaps is wrong - my mistake.

nesting happens if you stack two or more of the IM over each other.

if IM works is a matter of trust ;-) as Chris said they are not
essentlial but nice to have.

- Kristian

Chris Corbyn

unread,
Jul 4, 2011, 7:41:28 AM7/4/11
to datam...@googlegroups.com
I'm trying to integrate this now.  How would that actually work, with the nested IMs?

This is the source of that middleware:


I don't see how it processes that :external argument, but maybe I'm misunderstanding how "use" works.

Chris Corbyn

unread,
Jul 4, 2011, 8:02:02 AM7/4/11
to datam...@googlegroups.com
Ok, using

use Rails::DataMapper::Middleware::IdentityMap, :other

It definitely doesn't work, at least in Rails 3.0.9. You can't pass multiple arguments like that. I'm curious to know how to get this working though.

If I just use the default, I definitely don't have an IM for my :commerce repository... it's easily observed if it's working or not ;)


On 02/07/2011, at 13:46, kristian wrote:

kristian

unread,
Jul 4, 2011, 11:32:33 PM7/4/11
to DataMapper
hups, I am using the identitymap from https://github.com/mkristian/datamapper4rails

since a year or so, I have a patch for dm-rails on my local fork and
never push it and ask for a pull. just pushed it right now and asked
for the pull. see https://github.com/mkristian/dm-rails/blob/master/lib/dm-rails/middleware/identity_map.rb

- Kristian
Reply all
Reply to author
Forward
0 new messages