How to call attributes from a embedded_in relationship in Rails? - ruby-on-rails

I have the models
class PersonInfo
include Mongoid::Document
field :first_name, type: String
field :last_name, type: String
embedded_in :person
validates :first_name, :last_name, presence: true
end
and
class Person
include Mongoid::Document
field :account_id, type: String
validates :account_id, presence: true
embeds_one :person_info, class_name: PersonInfo
validates :person_info, presence: true
end
I need to add a new attribute with a default that uses account_id from Person
I've tried adding to PersonInfo
field :account_id, type: String, default: -> { person.account_id }
but in the rails console when I run person.person_info.account_id I keep getting NoMethodError
Any idea how to walk backward through an embedded_in relationship?

You can only references a relationship outside of a default value.
You can add a method to PersonInfo
def person_account_id
Person.account_id
end
But you can't access this method or Person.account_id from inside a default value

Related

mongoid validates array has at least 1 element

We have
class Event
include Mongoid::Document
field :categories, type: Array, default: []
end
How to validate an event object to have at least 1 element in categories? Should I use custom validator? Thank you
class Event
include Mongoid::Document
field :categories, type: Array, default: []
validates :categories, length: { minimum: 1 }
end
Should do the trick (http://guides.rubyonrails.org/active_record_validations.html#length)

rails validate uniqueness within inheritance

I have to models: Tag and TagNumeric each one with a category field
I shouldn't be able to create Tags of different types with the same category. How can I validate this?
EDIT:
I forgot to mention
TagNumeric < Tag
class Tag
include Mongoid::Document
validates_presence_of :type, :value
field :category, type: String
field :value, type: String
field :color, type: String
validates :value, :presence => true, :uniqueness => {:scope => :category}
class TagNumeric < Tag
field :value, type: Integer
it 'its category should be unique within the Tag class type' do
Tag.create(category: 'Movie', value: 'Avatar')
TagNumeric.create(category: 'Movie', value: 'Iron man').should_not be_valid
end
If anybody is having the same problem here is how I solved it
validate :uniqueness_within_category
def uniqueness_within_category
first_category_type = (Tag.find_by(category: self.category).nil?)? 'none' : Tag.find_by(category: self.category)._type
if first_category_type == 'none'
#It doesnt exist then should be allowed
return
end
#If it exists within another class type then shouldnt be allowed
if self._type != first_category_type
errors.add(:category, 'Must be unique within tag type')
end
end
Testing started at 6:22 PM ...
1 examples, 0 failures, 1 passed

Mongoid: search in has_many relation

I'm using mongoid, and have the following code:
class Users::User
include Mongoid::Document
field :username, type: String
has_many :emails, class_name: "Users::Email"
end
class Users::Email
include Mongoid::Document
field :email, type: String
belongs_to :user, class_name: "Users::User", inverse_of: :emails
end
database:
#users collection
{
"_id" : ObjectId("5162de8a359f10cbf700000c"),
"username" : "bilbo"
}
#emails collection
{
"_id" : ObjectId("5162de8a359f10cbf700000b"),
"email" : "bilbo#jenkins.com",
"user_id" : ObjectId("5162de8a359f10cbf700000c"),
}
I'm trying to find with the following query:
Users::User.includes(:emails).any_of({username: login},{"emails.email"=> login}).first
and I don't know why, but this query ignoring search in emails relation.
When login = "bilbo" => true, but when login = "bilbo#jenkins.com" => nil
So, what I'm doing wrong?
You need a join to do what you're trying to do and Mongoid doesn't have joins. If you only need to access the emails through a user, you could denormalize them and embed them in Users::User.
class Users::User
include Mongoid::Document
field :username, type: String
embeds_many :emails, class_name: "Users::Email"
end
class Users::Email
include Mongoid::Document
field :email, type: String
embedded_in :user, class_name: "Users::User", inverse_of: :emails
end
That way, you can query on a user's emails:
irb(main):011:0> login = "bilbo#jenkins.com"
=> "bilbo#jenkins.com"
irb(main):012:0> Users::User.any_of({username: login},{"emails.email"=> login}).first
=> #<Users::User _id: 5163ee96e44f7b0301000001, username: "bilbo">
If Users::Email's only property is email you could go even a step further and omit the model completely and store the string in an array:
class Users::User
include Mongoid::Document
field :username, type: String
field :emails, type: Array
end
Querying gets even easier:
Users::User.any_of({username: login},{"emails"=> login}).first
=> #<Users::User _id: 5163ef95e44f7b6254000001, username: "bilbo", emails: ["bilbo#jenkins.com"]>

How to define has_and_belongs_to association in rails

I am following this video http://railscasts.com/episodes/258-token-fields-revised and i implement this also sucessfully. But now i am using namespace.
I have lends_controller inside folder employee inside asset folder.
this is my model of lend controller
class Employee::Asset::Lend
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
field :text, type: String
field :date
field :asset_tokens
field :user_id, type: String
has_and_belongs_to_many :assets
belongs_to :tags
def asset_tokens=(tokens)
self.asset_ids = Asset.ids_from_tokens(tokens)
end
end
Now i have another model asset. There i have to define has and belongs to this lend model also I did this
class Asset
include Mongoid::Document
field :name, type: String
field :description, type: String
field :serial_number, type: String
field :status, type: Integer
field :tag_tokens
field :quantity, type: Integer
validates_presence_of :name
validates :serial_number,:uniqueness => true
has_and_belongs_to_many :employee_asset_lends
has_and_belongs_to_many :tags
def self.tokens(query)
assets = where(name: /#{Regexp.escape(query)}/i)
end
form for lend controller is
<%= f.label :asset_tokens, "Assets" %>
<%= f.text_field :asset_tokens, data: {load: #employee_asset_lend.assets}%><br>
<%= f.input :date,:input_html => { :class => "dp1"},:label=> "Lend Date"%>
inside coffescript file for lend.js.coffee
jQuery ->
$('#employee_asset_lend_asset_tokens').tokenInput '/assets.json'
theme: 'facebook'
prePopulate: $('#employee_asset_lend_asset_tokens').data('load')
But it gives error uninitialized constant EmployeeAssetLend from asset views.
and from lend view it gives error like undefined methodall_of' for Employee::Asset:Module`
pleaes check the right way to make HABTM-has_and_belongs_to_many Assosiation for more details

Why doesn't mongoid add my nested attributes on new()?

I can't seem to figure out why Mongoid won't set the nested attributes for a child object when I create a new parent. I want to create a new Folio, add one child Feature, then push it on the Folios array on Profile.
I have a Profile, which embed many Folios, which embed many Features:
class Profile
include Mongoid::Document
include Mongoid::Timestamps::Updated
#regular fields here; removed for brevity
embeds_many :folios, class_name: "Folio"
end
class Folio
include Mongoid::Document
include Mongoid::Timestamps::Updated
accepts_nested_attributes_for :features
embedded_in :profile
field :name
field :desc
field :order, type: Integer, default:0
embeds_many :features
attr_accessible :name, :desc, :order
end
class Feature
include Mongoid::Document
include Mongoid::Timestamps::Updated
embedded_in :folio
belongs_to :project
field :content_type, type: Integer #ContentType
field :content_id
field :txt, type: String
field :order, type: Integer, default:0
attr_accessible :project_id, :content_type, :content_id, :txt, :order
end
Controller:
def new
#folio = Folio.new
#folio.features.build
end
def create
#folio = Folio.new(params[:folio])
##folio.features is still empty here.
#profile.folios << #folio
#profile.save
render "create_or_update.js"
end
In create, the param hash looks good:
{"folio"=>{"id"=>"new", "name"=>"new name", "desc"=>"new description", "features_attributes"=>{"0"=>{"project_id"=>"4ea0b68e291ebb44a100000a", "content_type"=>"1", "content_id"=>"4ea0b68e291ebb44a100000d", "txt"=>"note here"}}}, "commit"=>"Save", "action"=>"create", "controller"=>"folios"}
But #folio.features is still empty.
This worked fine with AR, if I remember. Strangely, there is no features_attributes=() method on Folio. I thought that was required for the nested attributes to work? What am I missing?
This is on Rails 3.1 with Mongoid 2.2.3.
have you tried enabling AutoSave true for features in Folio document
class Folio
include Mongoid::Document
include Mongoid::Timestamps::Updated
accepts_nested_attributes_for :features , :autosave => true
embedded_in :profile
end

Resources