I am trying to update a nested has_one model using mongoid but it will not persist the has_one association
im running Rails 3.07 & Mongoid 2.2
widget model
class Widget
include Mongoid::Document
embeds_many :permissions, :default => []
end
permission model
class Permission
include Mongoid::Document
field :admin, :type => Boolean, :default => false
has_one :user
embedded_in :widget
end
user model
class User
include Mongoid::Document
belongs_to :permission
end
Heres the results im getting from rails console;
#widget.permissions << Permission.new(:user => current_user)
=> [#<Permission _id: 4e5aced1c155df4b33000001, _type: nil, admin: false>]
#widget.save
=> true
#widget.permissions.first.user
=> #<User _id: 4e5ac71ec155df470f000001, _type: nil, email: "ada ..... >
Appears as if the user is saved, however it is not persisted to mongo.
The permission is being saved but has no user.
Any ideas?
Should you be using "embedded_in" rather than "belongs_to" in the User model?
Related
I have created an active record enum field: role. Added it to the model and the table. But it doesn't generate the helpers?
Membership model
enum role: [:employee, :admin, :owner]
after_initialize :set_default_membership_role, :if => :new_record?
def set_default_membership_role
self.role ||= :employee
end
pry output
=> [#<Membership id: 1, company_id: 1, user_id: 1, created_at: "2014-11-25 16:06:03", updated_at: "2014-11-25 16:06:03", role: 0>]
[3] pry(main)> #membership.role
from /Users/gtheys/.rbenv/versions/2.1.2/gemsets/worke_rs/gems/activerecord-4.1.5/lib/active_record/relation/delegation.rb:136:in `method_missing'
Is it because because Membership is a join model for user and companies?
model/User.rb
has_many :companies, :through => :memberships, dependent: :destroy
model/Companies.rb
has_many :users, :through => :memberships
Or is there another problem why the enum helpers are not created?
Are you sure you are calling .role on the actual membership model?
In your example (pry output) it looks like #membership is an active_record/relation.
Try #membership.first.role
I followed the post http://techspry.com/ruby_and_rails/multiple-table-inheritance-in-rails-3/ to implement the multiple table inheritance with Rail 4. I have three models: user, applicant and tutor. Here is my code:
class User < ActiveRecord::Base
belongs_to :student, :polymorphic => true
end
class Tutor < ActiveRecord::Base
acts_as_student
end
class Applicant < ActiveRecord::Base
acts_as_student
end
# in the /lib/student_module.rb
module Student
def acts_as_student
include InstanceMethods
has_one :user, :as => :student, :autosave => true, :dependent => :destroy
alias_method_chain :user, :build
user_attributes = User.content_columns.map(&:name) #<-- gives access to all columns of Business
# define the attribute accessor method
def student_attr_accessor(*attribute_array)
attribute_array.each do |att|
define_method(att) do
user.send(att)
end
define_method("#{att}=") do |val|
user.send("#{att}=",val)
end
end
end
student_attr_accessor *user_attributes #<- delegating the attributes
end
module InstanceMethods
def user_with_build
user_without_build || build_user
end
end
end
The User Table has username, email attributes.The Tutor table has first_name,last_name,intro,program,entry_year attributes.
In the rails console, I got
tutor = Tutor.new => #<Tutor id: nil, first_name: nil, last_name: nil, intro: nil, created_at: nil, updated_at: nil, entry_year: nil, program: nil>
tutor.username
=> ActiveRecord::UnknownAttributeError: unknown attribute: student_id
I found the error was from the student_attr_accessor method. How should I fix it? Thanks!
I found I forgot to declare a foreign key column and a type column in the User Model. To fix this, just run a migration like:
def change
add_column :users, :student_id,:integer
add_column :users, :student_type,:string
end
I have a very odd mass assignment error that shows up when I use association methods to create new objects.
I have a user model that looks like this:
class User < ActiveRecord::Base
has_many :posts, :dependent => :destroy
end
I also have a posts model that looks like this:
class Post < ActiveRecord::Base
belongs_to :user
attr_accessible :body, :title
end
If I do the following in console, I get a mass assignment warning:
> user = User.create(:name => "Daniel");
> user.posts.create(:title => "Hello World")
=> #<Post id: 1, body: nil, title: "Hello World", created_at: "2011-11-03
18:24:06", updated_at "2011-11-03 18:24:06", user_id = 1>
> user.posts
=> WARNING: Can't mass-assign attributes: created_at, updated_at, user_id
When I run user.posts again, however, I get:
> user.posts
=> [#<Post id: 1, body: nil, title: "Hello World", created_at: "2011-11-03
18:24:06", updated_at "2011-11-03 18:24:06", user_id = 1>]
There are a couple of other tricks I can do to avoid the mass assignment error, such as calling user.posts before I do users.posts.create.
Why is this happening and how can I prevent it?
I'm using Rails 3.0.7.
How about changing your user model to include attr_accessible for posts association
class User < ActiveRecord::Base
has_many :posts, :dependent => :destroy
attr_accessible :posts
end
i have a strange problem. i am new to mongoid, so i am having trouble determining if it is me or mongoid at fault... presenting my code is perhaps the best explanation (minus the fields/validations/etc.)
class User
include Mongoid::Document
embeds_one :profile, :class_name => "UserProfile"
references_and_referenced_in_many :roles
end
class UserProfile
include Mongoid::Document
embedded_in :user
end
class Role
include Mongoid::Document
references_and_referenced_in_many :users
end
with the following associations, when i create instances of these objects like so...
user = User.new :username => 'username',
:email => 'user#domain.com',
:password => 'password'
user.build_profile :first_name => 'John',
:last_name => 'Doe',
:birthday => Date.new(1980, 1, 1)
user.roles << Role.new(:name => 'Administrator')
user.save
...i can view this user with User.first or user
...i can view the profile with User.first.profile and user.profile
...i can view roles with user.roles but i CANNOT view them with User.first.roles.
another strange thing is user.roles.count AND User.first.roles.count both return 0, even though when i view user.roles, it returns [#<Role _id: 4d8c0173e1607cdeae00002c, name: "Administrator", user_ids: [BSON::ObjectId('4d8c0173e1607cdeae00002a')]>]. (User.first.roles returns an empty array)
this seems like a bug.
use :autosave => true for the relational association
references_and_referenced_in_many :roles, :autosave => true
or you can explicitly save the role as
role = Role.new(:name => 'Administrator')
user.roles << role
role.save
user.save
This is due to changes in mongoid.2.0.0.rc.1 + listed here.
Relational associations no longer
autosave when the parent relation is
created. Previously a save on a new
document which had a references_many
or references_one association loaded
would save the relations on it's first
save. In order to get this
functionality back, an :autosave =>
true option must be provided to the
macro (This only applies to
references_many and references_one)
Here are my models:
class User
include Mongoid::Document
include Mongoid::Timestamps
references_many :roles, :stored_as => :array, :inverse_of => :users
...
end
class Role
include Mongoid::Document
field :name, :type => String
references_many :users, :stored_as => :array, :inverse_of => :roles
...
end
I first create the roles via seed, rake db:seed. My seed file contains:
puts '*** Add default roles'
[
{ :name => 'User' },
{ :name => 'Artist' }
].each do |h|
Role.create(h)
end
The roles are created successfully. However, when I add a role to a user, I do:
foobar = User.first
foobar.roles.create(:name => 'User')
I notice 2 things:
1) It adds the role as a reference in the User collection.
2) It creates a 3rd role in the Role collection.
This is kind of strange because now I have 3 roles: User, Artist and User. The 2nd User collection has a user_ids reference which contains foobar's id.
Is this normal?
I think you rather want to do:
foobar = User.first
foobar.roles << Role.find(:name => 'User')
foobar.save
This way a role object is not created, but a reference is added to an already existing record.