I have a rails app that is using Redis as the DB, and Ohm as an ORM.
I have a model Activity that has a set of Users. In the rails console I am able to call Activity[id].users.to_a and get the expected list. When trying to do the same thing in a method in my app, I always get an empty string. I've tried this several different ways, including using self.users.to_a in the method and nothing has worked.
I haven't come across a problem like this before where everything is working fine in console but not in the app. BTW the rails.env is set to development.
Any help would be really appreciated, this has stumped me for a bit now. Thanks.
Activity.rb
class Activity < Ohm::Model
include Ohm::Timestamps
include Ohm::DataTypes
include Ohm::Callbacks
include ModuleLibrary
attribute :type
index :type
attachment :attached
attribute :time, Type::Integer
attribute :description
attribute :to_calendar, Type::Integer
set :contacts, :Contact
set :users, :User
reference :company, :Company
reference :account, :Account
def user_names #empty string in app, works fine in console
users.map(&:name).to_sentence
end
end
EDIT: So apparently it turns out where I was calling the method from, the users hadn't been added yet. (duh!) I moved where the method is called to a different spot, and it's all working now.
Related
I've read through many tutorials, and copied their code exactly, yet what they claim works for them doesn't work for me.
I'm making a most basic "has_many" and "belongs_to" association, but rails refuses to acknowledge any association whatsoever.
A user "has_many" emails. Emails "belong_to" user. Here's my code:
user.rb
class User < ActiveRecord::Base
unloadable
has_many :emails
accepts_nested_attributes_for :emails,
:allow_destroy => true,
# :reject_if => :all_blank
end
email.rb
class Email < ActiveRecord::Base
unloadable
belongs_to :user
end
Then, in the console:
User.emails.build
NoMethodError: undefined method `emails' for #<Class:0x00000006c16e88>
Indeed, this "NoMethodError" persists no matter what.
As of now, my guess is that a capacitor in my hardware burnt out while I was installing rails, causing everything to work except this one thing. Or maybe it's something else :p
EDIT:
Another console attempt:
my_user = User.new
my_user.emails.build
Also results in an undefined "emails" method.
I noticed that my original user class has a bad comma at the end; removing that, I get this error:
ActiveRecord::UnknownAttributeError: unknown attribute 'user_id' for Email.
First, you'll need to make sure you have a user_id attribute on your email table in the database. If you don't have one, you can add it with a migration.
Then, you need to tell Rails which instance of a user's emails you want to look at. So, you'll need to make sure you have a user in the database (user = User.create) and then that user's emails can be found using user.emails.
You're confusing the concept of classes and instances. You need an instance of the User class in order to build associated relations. The error you're getting (NoMethodError: undefined method emails for #<Class:0x00000006c16e88>) hints to this, since it's telling you you're trying to call the method emails on a Class object.
Try something like:
my_user = User.new
my_user.emails.build
Please use like this
#email = User.first.emails.build
I have two models one is the Project model and the other one is the ProjectSyndication model, code looks something like this:
class Project
has_one :project_syndication
end
class ProjectSyndication
belongs_to :project
end
ActiveAdmin.register Project, as: 'Offering' do
end
ActiveAdmin.register ProjectSyndication do
belongs_to :offering, parent_class: Project
end
This code gives me an error when I go to the show page of a ProjectSyndication, which is the following:
undefined method `project_syndications' for #<Project:0x007fc309a972b0>
I did just a bit of digging and for the hell of it created an empty project_syndications method in my Project model then got the following error:
undefined method `find' for nil:NilClass
So I can deduce that ActiveAdmin is treating this association like a has_many association and trying to find the ProjectSyndication after finding all the project syndications of one project, which won't work.
I solved the problem by making the following method under the Project model
def project_syndications
ProjectSyndication.where(project_id: id)
end
This works fine, but I feel it is not the right way to do it. I looked through the ActiveAdmin docs, but have not been able to find much. What I asked is for the right way to fix the issue or if this is a bug/feature from ActiveAdmin.
Any help will be appreciated, thank you in advance.
Your question is very vague.
Maybe provide your database migrations as well.
I would check the following (vague guesses):
class Project; has_one :project_syndication; end
=> This inidicates your db has the field projects.project_syndication_id
=> Maybe try "has_many" there?
ActiveAdmin.register Project, as: 'Offering' do; end;
=> Case Offering vs offering below
=> Redundant code? (remove it)
ActiveAdmin.register ProjectSyndication do; belongs_to :offering, parent_class: Project; end
=> Redundant code? (remove it)
I am using https://github.com/mailboxer/mailboxer and I am trying to add my own photos to attach to each message
inside /config/initializes/extensions/mailboxer/message.rb
Mailboxer::Message.class_eval do
has_many :photos, as: :imageable, :class_name => 'Photo'
end
This works great, except that it randomly throws an error:
undefined method `photos' for #<Mailboxer::Message:0x6eb0758>
When I start up the server for the first time it works. When I start modifying code (can be anything, nothing related to mailboxer) I get the error. I have to restart the server to get it working again.
I tried putting the file outside the initializes folder and adding an include path as the last line in config/boot.rb, same issue.
Any ideas as to why it is losing reference?
When Rails detects your code has been modified, it "forgets" all the models, etc. it has auto-loaded, including Mailboxer::Message. The next time that model is used, it is reloaded from the mailboxer gem without your monkey patches.
To ensure your monkey patches "stick", I think you need to give Rails a hint that you want your code reapplied when it does a reload. Putting your patches in a to_prepare block may do the trick:
Rails.application.config.to_prepare do
Mailboxer::Message.class_eval do
has_many :photos, as: :imageable, :class_name => 'Photo'
end
end
I'm trying to get associations in FactoryGirl to work, and they just ... don't. I've basically got this:
class Foo
include Mongoid::Document
belongs_to :bar
end
class Bar
include Mongoid::Document
has_many :foos
end
FactoryGirl.define do
factory :foo, class => Foo do
bar
end
factory :bar, class => Bar do
end
end
At least so the docs lead me to believe... But then in my test, I have
a_foo=FactoryGirl.create :foo
a_foo.bar # Hooray! It's an associated object
Foo.where( _id: a_foo._id ).includes( :bar ).first.bar # This is nil!
Why is the associated value nil on the last line? I need it not to be, because the actual code being tested does this same thing, and it has a right to expect it to work... What am I missing about why this doesn't work right? Something to do with eager loading, perhaps?
Your code actually works for me with FactoryGirl 4.2.0, Mongoid 3.0.9. But I've run into similar issues when I've been running mongoid with the identitymap disabled (which is default behavior). Without the identitymap, you can have two different ruby objects representing the same document in the database, getting out of sync with each other. So, if you have autosave off, for example, this could cause the problem you're seeing.
Try pasting your simplified code into the rails console yourself -- if it works, then you probably changed something significant in pairing down your real code. (Sorry to point out the obvious, but the fact that you have a syntax error in your factory code makes me think you didn't actually test your sample code.)
I'm trying to create a nested child and grandchild record. The child belongs_to both the parent and the grandchild. The child won't validates_presence_of the grandchild because it hasn't been saved yet.
I'm using Rails 2.3.11, Formtastic, InheritedResources, and Haml, and everything else seems to work correctly - for example, validation errors on the grandchild populate properly in the parent form, and the invalid values are remembered and presented to the user. The parent model doesn't even try to update unless everything is valid, just as it should be.
My code is something like this, though in a different problem domain:
class Project < ActiveRecord::Base
has_many :meetings, :dependent => :destroy
accepts_nested_attributes_for :meetings
end
class Meeting < ActiveRecord::Base
belongs_to :project
belongs_to :task
accepts_nested_attributes_for :task
validates_presence_of :task_id, :project_id
end
class Task < ActiveRecord::Base
has_many :meetings, :dependent => :destroy
end
The Project ALWAYS exists already, and may already have Meetings that we don't want to see. Tasks may belong to other Projects through other Meetings, but in this case, the Task and Meeting are ALWAYS new.
In the controller, I build a blank record only on the new action
#project.meetings.build
and save the data like this:
#project.update_attributes(params[:project])
and in the view
- semantic_form_for #project do |f|
- f.semantic_fields_for :meetings do |m|
- next unless m.object.new_record?
= m.semantic_errors :task_id
- m.object.build_task unless i.object.task
- m.semantic_fields_for :task do |t|
- f.inputs do
= t.input :task_field
= m.input :meeting_field
When I try to save the form, I get a validation error of "Task can't be blank." Well, sure, the Task hasn't been saved yet, I'm trying to validate, and I don't have an ID for it.
Is there a simple and elegant way to make sure that the grandchild record (Task) gets built before the child record?
I've tried something like this in the Meeting model:
before_validation_on_create do |meeting|
meeting.task.save if meeting.task.valid?
end
and that seems to save the Task, but the Meeting still doesn't get the right ID. Same error, but the Task record gets created.
I've also tried this:
before_validation_on_create do |meeting|
new_task = meeting.task.save if meeting.task.valid?
meeting.task = new_task
end
Which has the strange behaviour of raising ActiveRecord::RecordNotFound "Couldn't find Task with ID=XX for Meeting with ID=" - which I sort of get, but seems like a red herring.
I also tried adding :inverse_of to all the relationships and validating :task instead of :task_id. The latter, oddly, fails but seems to give no error message.
My actual goal here is to create more than one Task, each with an initial Meeting on a previously selected Project... so I could take another approach with my problem - I could do something simple and ugly in the controller, or create the first Meeting in an after_create on the Project. But this is so pretty and soooo close to working. The fact that I'm getting proper validation errors on :task_field and :meeting_field implies that I'm on the right track.
I see what the problem is, but not how to solve it: I suspect I'm missing something obvious.
Thank you!
Well, I found a solution, based on one of the similar questions out there, but the short of it is "rails 2.3 doesn't seem to be very good at this." I think I can put the answer in a more succinct way than any of the other answers I've seen.
What you do is you skip the validation of the :task_id, but only if task is valid! Most of the other answers I've seen use a proc, but I think it's more readable using delegate, like this:
delegate :valid?, :to => :task, :prefix => true, :allow_nil => true
validates_presence_of :task_id, :unless => :task_valid?
I also had another problem hidden under the waterline - in the case, the "Project" is actually a special sort of record that I wanted to protect, which has a validation that (intentionally) fails only for this special record, and I also set readonly? to true for the special record.
Even though I'm not actually changing that special record, it still needs to validate and can't be readonly to update children through it. For some reason, I wasn't seeing the error message for that validation. To solve that, I made the validation on the Project only applicable :on => :create, and I took out the readonly? thing.
But the general solution is "don't validate presence of the unbuilt belongs_to object if the object itself is valid." Nil is never valid, therefore the validation still works if you just have an object_id.
(Please don't vote down a sincere question unless you have an answer or a link to one. I'm aware the question has been asked by others in other ways, I read many of those other questions, none seemed to be precisely the same problem, and I had not found a solution.)