DataMapper Redis: can't find child from parent, only parent from child - ruby

I'm using DataMapper with the redis adapter in a Ruby library.
I have these classes defined:
class Zone
include DataMapper::Resource
property :id, String, :key => true, :unique_index => true, :default => lambda { |x,y| UUID.new.generate }
property :preview_mode, Boolean, :default => false
timestamps :at
has 1, :campaign
end
and
class Campaign
include DataMapper::Resource
property :id, String, :key => true, :unique_index => true, :default => lambda { |x,y| UUID.new.generate }
property :name, String
timestamps :at
belongs_to :zone
has n, :rules
validates_presence_of :name
end
I'm able to do Campaign.first.zone but not Zone.first.campaign.
I would like to be able to do the lookups in both directions.

#lightyrs I responded to your github issue, but for reference here, I think this issue has been fixed in versions > 0.8 that have better support for non-serial primary keys.
Cheers! - whoahbot

Related

Mongo, Mongoid join data from different models in Ruby on Rails

I'm adapting a Ruby on Rails application to work with MongoDB instead of PostgreSQL. I have this 2 class:
module Cms
class Content
include Mongoid::Document
include Mongoid::Orderable
field :title, type: String
field :position, type: String
field :text_body, type: String
field :expiration_date, type: Date
field :active, type: Boolean, default: false
validates :title, :text_body, presence: true
orderable base: 0
belongs_to :cms_content_category, class_name: 'Cms::ContentCategory'
scope :ordered, ->() { order(position: :asc) }
scope :not_expired, ->() { any_of({ expiration_date: nil }, { :expiration_date.gte => Date.today }) }
end
end
module Cms
class Submenu
include Mongoid::Document
include Mongoid::Orderable
field :title, type: String
field :position, type: String
field :external_url, type: String
field :open_as, type: String, default: '_self'
field :active, type: Boolean, default: false
delegate :url_helpers, to: :'Rails.application.routes'
validates :title, presence: true
validates :external_url, presence: true, if: Proc.new { |obj| obj.cms_content_id.nil? }
validates :cms_content_id, presence: true, if: Proc.new { |obj| obj.external_url.blank? }
orderable base: 0
belongs_to :cms_content, class_name: 'Cms::Content'
belongs_to :cms_menu, class_name: 'Cms::Menu'
scope :ordered, ->() { order(position: :asc) }
def url
self.external_url.present? ? self.external_url : url_helpers.content_show_path(self.cms_content_id)
end
end
end
The problem is that I don't know how to adapt the following SQL query to work with MongoDB.
scope :active, joins("FULL JOIN contents ON contents.id = cms_submenus.content_id")
.where("cms_submenus.active IS TRUE AND (
(cms_submenus.content_id IS NOT NULL AND ((contents.expiration_date >= :today OR expiration_date IS NULL) AND contents.archived IS NOT TRUE)) OR
(cms_submenus.external_url IS NOT NULL AND cms_submenus.external_url <> '')
)", today: Date.today)
This scope has to be called from Submenu model.
Someone has an idea on how to solve this problem?
I'm using Rails 4.2.0 with Ruby 2.2.0 and Mongoid 4.0.2 with MongoDB 2.6.8.
thank you

Mongomapper :minimum & :maximum vs. :length

I try to validate in MongoMapper a string with:
key :title, String, :require => true, :length => 4..30
And I got always the error "title is too short (minimum is 4 characters)" also when the string was longer than 4 chars.
If I try it with
key :title, String, :require => true, :minimum => 4, :maximum => 30
and it work as excepted. Can someone explain why this happen or why the first thing is wrong?
MongoMapper uses Activerecord validations. From their documentation: validates :password, :length => { :in => 6..20 } So you have to use :in to denote you are using a range. See http://guides.rubyonrails.org/active_record_validations_callbacks.html#length

Rails -- before_save not working?

I am following Michael Hartl's RoR tutorial, and it is covering the basics of password encryption. This is the User model as it currently stands:
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :name, :email,: password, :password_confirmation
email_regex = /^[A-Za-z0-9._+-]+#[A-Za-z0-9._-]+\.[A-Za-z0-9._-]+[A-Za-z]$/
#tests for valid email addresses.
validates :name, :presence => true,
:length => {:maximum => 50}
validates :email, :presence => true,
:format => {:with => email_regex},
:uniqueness => {:case_sensitive => false}
validates :password, :presence => true,
:length => {:maximum => 20, :minimum => 6},
:confirmation => true
before_save :encrypt_password
private
def encrypt_password
#encrypted_password = encrypt(password)
end
def encrypt(string)
string
end
end
(Obviously this isn't doing any encrypting because the encrypt method isn't really implemented but that's not my question)
I then wrote the following Spec (according to the tutorial):
require 'spec_helper'
describe User do
before(:each) do
#attr = { :name => "Example User", :email => "user#example.com",
:password => "abc123", :password_confirmation => "abc123"}
end
describe "password encryption" do
before(:each) do
#user = User.create!(#attr) # we are going to need a valid user in order
# for these tests to run.
end
it "should have an encrypted password attribute" do
#user.should respond_to(:encrypted_password)
end
it "should set the encrypted password upon user creation" do
#user.encrypted_password.should_not be_blank
end
end
end
The first of these tests passes, but since #user.encrypted_password is nil, the second test fails. But I don't understand why it's nil since the encrypt_password method should be being called by before_save. I know I must be missing something -- can someone please explain?
The encrypt_password method is incorrect, it should read:
def encrypt_password
self.encrypted_password = encrypt(password)
end
Note the use of self, which will properly set the attribute for the user object rather than creating an instance variable which is forgotten.
This is an old question and this is more of a comment but I don't have enough reputation to comment yet. Just wanted to link this question too as it goes into some solid detail about self.
Why isn't self always needed in ruby / rails / activerecord?

Mongoid - getting all attributes including embedded documents

Is there an easy way to get all attributes of a Mongoid document, including those of embedded documents?
For example, if I have the following documents:
class Person
include Mongoid::Document
embeds_many :phone_numbers
field :name
end
class PhoneNumner
include Mongoid::Document
embedded_in :person, :inverse_of => :phone_numbers
field :number
end
I would like to get a Person's attributes and phone numbers like this:
{ :name => "Jenny", :phone_numbers => [{ :number => '867-5309' }, { :number => '867-5309' }] }
Since embedded documents are really just other attributes on the parent document, you can get to them like so:
person = Person.create
person.phone_numbers.create(:number => "123-456-7890")
person.attributes
# => {"_id"=>"4c48ff26f7e2da3704000001",
# "phone_numbers"=>
# [{"number"=>"123-456-7890", "_id"=>"4c48ff26f7e2da3704000002"}]}

Strange DataMapper (0.10.2) error. Please help!

See the full error here: http://notesapp.heroku.com/
I'm using DataMapper and dm-validations 0.10.2. No matter how much I tweak my models, I get the same error, or another one. Here's how my model looks like:
class User
include DataMapper::Resource
attr_accessor :password, :password_confirmation
property :id, Serial, :required => true
property :email, String, :required => true, :format => :email_address, :unique => true
property :hashed_password, String
property :salt, String, :required => true
property :created_at, DateTime, :default => Time.now
property :permission_level, Integer, :default => 1
validates_present :password_confirmation, :unless => Proc.new { |t| t.hashed_password }
validates_present :password, :unless => Proc.new { |t| t.hashed_password }
validates_is_confirmed :password
Looks like you have an old version of DataObjects (probably pre 0.10.0) installed. Please update to the latest version and I think this error will disappear. Depending on the database you use it's most likely either do_postgres or do_mysql you need to upgrade.

Resources