I am new to rails and am following the Depot application in the Pragmatic Agile Web development with rails and I am having an odd problem.
In my product model I created a validator for confirming that the image asked for in the image url field actually exist as an asset. Here is my product model code.
class Product < ActiveRecord::Base
attr_accessible :description, :image_url, :price, :title
validates :description, :price, :title, :presence => true
validate :image_url_exists, on: :create
def image_url_exists
if Rails.application.assets.find_asset(image_url) == nil
errors.add(:image_url, 'is not valid. The image does not exist.')
end
end
end
Now the problem is when I run my unit test. Here is what it is:
require 'test_helper'
class ProductTest < ActiveSupport::TestCase
test "the products attributes should not be empty" do
p = Product.new
assert p.invalid?
end
end
But doing so triggers a bunch of errors in my code. Without the custom validtor, everything seems to work just fine. Here are the errors I am currently getting.
test_the_products_attributes_should_not_be_empty(ProductTest):
TypeError: can't convert nil into String
/var/lib/gems/1.9.1/gems/sprockets-2.2.2/lib/sprockets/base.rb:156:in `initialize'
/var/lib/gems/1.9.1/gems/sprockets-2.2.2/lib/sprockets/base.rb:156:in `new'
/var/lib/gems/1.9.1/gems/sprockets-2.2.2/lib/sprockets/base.rb:156:in `find_asset'
/var/lib/gems/1.9.1/gems/sprockets-2.2.2/lib/sprockets/index.rb:60:in `find_asset'
/var/lib/gems/1.9.1/gems/sprockets-2.2.2/lib/sprockets/environment.rb:78:in `find_asset'
/home/saurabh/Desktop/SCRIPTS/Rails/depot/app/models/product.rb:6:in `image_url_exists'
/var/lib/gems/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:418:in `_run__4343689776242734370__validate__107120755283260520__callbacks'
/var/lib/gems/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:405:in `__run_callback'
/var/lib/gems/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:385:in `_run_validate_callbacks'
/var/lib/gems/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:81:in `run_callbacks'
/var/lib/gems/1.9.1/gems/activemodel-3.2.9/lib/active_model/validations.rb:228:in `run_validations!'
/var/lib/gems/1.9.1/gems/activemodel-3.2.9/lib/active_model/validations/callbacks.rb:53:in `block in run_validations!'
/var/lib/gems/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:403:in `_run__4343689776242734370__validation__107120755283260520__callbacks'
/var/lib/gems/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:405:in `__run_callback'
/var/lib/gems/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:385:in `_run_validation_callbacks'
/var/lib/gems/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:81:in `run_callbacks'
/var/lib/gems/1.9.1/gems/activemodel-3.2.9/lib/active_model/validations/callbacks.rb:53:in `run_validations!'
/var/lib/gems/1.9.1/gems/activemodel-3.2.9/lib/active_model/validations.rb:195:in `valid?'
/var/lib/gems/1.9.1/gems/activerecord-3.2.9/lib/active_record/validations.rb:69:in `valid?'
/var/lib/gems/1.9.1/gems/activemodel-3.2.9/lib/active_model/validations.rb:203:in `invalid?'
The problem is Rails.application.assets.find_asset(image_url), image_url is nil when you create a refresh object at test:
p = Product.new # Here p.image_url => nil
You can find the reason of the error looking at log
/var/lib/gems/1.9.1/gems/sprockets-2.2.2/lib/sprockets/base.rb:156:in `initialize'
Here (link) the line 156 where error happens, path was nil here.
So to solve this problem you need to add a condition at your if to check if image_url isn't nil, here is my sugestion
if self.image_url.nil? || Rails.application.assets.find_asset(self.image_url).nil?
errors.add(:image_url, 'is not valid. The image does not exist.')
end
Related
I'm trying to be a good rails developer and write tests as I go. I've run into something I'm unclear on and am looking for advice. I have a model that has a unique case insensitive attribute. The test is failing however. Whats the correct way to test this? What am I doing wrong?
class Tenant < ApplicationRecord
validates :name, presence: true
validates :name, uniqueness: { case_sensitive: false }
end
RSpec.describe Tenant, type: :model do
it { should validate_presence_of :name }
it { should validate_uniqueness_of(:name).case_insensitive }
end
It seems like it's trying to set the id as nil even though we have another validation that requires the presence. But why is it doing that while testing name? I'm confused.
Test shows the following result;
Failures:
1) Tenant Validates Uniqueness of should validate that :name is case-insensitively unique
Failure/Error: self.id = self.id.downcase
NoMethodError:
undefined method `downcase' for nil:NilClass
# ./app/models/tenant.rb:17:in `block in <class:Tenant>'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/validator.rb:96:in `perform_validation'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/validator.rb:89:in `validation_result'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/validator.rb:85:in `validation_error_messages'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/validator.rb:64:in `messages'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/validator.rb:25:in `has_messages?'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/validator.rb:55:in `messages_match?'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/validator.rb:21:in `call'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb:38:in `matches?'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb:24:in `each'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb:24:in `detect'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb:24:in `first_passing'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/allow_value_matcher.rb:533:in `public_send'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/allow_value_matcher.rb:533:in `run'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/allow_value_matcher.rb:400:in `does_not_match?'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/disallow_value_matcher.rb:32:in `matches?'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/validation_matcher.rb:155:in `run_allow_or_disallow_matcher'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_model/validation_matcher.rb:93:in `disallows_value_of'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb:606:in `validate_two_records_with_same_non_blank_value_cannot_coexist?'
# /Users/a/.rvm/gems/ruby-2.5.0/gems/shoulda-matchers-3.1.2/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb:330:in `matches?'
# ./spec/models/tenant_spec.rb:49:in `block (3 levels) in <top (required)>'
Finished in 0.09495 seconds (files took 1.89 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/models/tenant_spec.rb:49 # Tenant Validates Uniqueness of should validate that :name is case-insensitively unique
Note: this is likely something dumb and obvious that I'm just missing. Your help/advice is appreciated.
Versions:
Ruby 2.50 :: Rails 5.14 :: Rspec 3.7 :: Shoulda-matcher 3.12
As nattfodd mentions:
It seems you have some before/after hooks defined. Please show more code of Tenant model class.
It was a beforehook that was the issue.
I'm trying to create a dynamic application to create any kind of data needed through metaprogramming the MVC i tried this for models:
class DynamicRecord
attr_accessor :name, :attributes
def initialize(name, attributes = [])
raise "Error: Constant #{name} already in namespace" if name.in? Object.constants
a_new_class = Class.new(Object) do |clazz|
include Mongoid::Document
attributes.map do |attribute|
field attribute[:name], type: attribute[:type]
end
end
Object.const_set(name, a_new_class)
end
end
DynamicRecord.new('Person', [{name: :name, type: String}, {name: :email, type: String}])
person = Person.new(name: "Foo", email: "Foo#foo.com")
person.save
Then I get this error:
Mongo::Error::OperationFailure: Invalid ns [mongodb_divcad_development.] (16257)
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongo-2.4.1/lib/mongo/operation/result.rb:256:in `validate!'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongo-2.4.1/lib/mongo/operation/write/insert.rb:60:in `block in execute_message'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongo-2.4.1/lib/mongo/server/connection_pool.rb:107:in `with_connection'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongo-2.4.1/lib/mongo/server.rb:242:in `with_connection'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongo-2.4.1/lib/mongo/operation/write/insert.rb:59:in `execute_message'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongo-2.4.1/lib/mongo/operation/write/write_command_enabled.rb:39:in `execute'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongo-2.4.1/lib/mongo/collection.rb:365:in `block in insert_one'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongo-2.4.1/lib/mongo/retryable.rb:112:in `write_with_retry'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongo-2.4.1/lib/mongo/collection.rb:356:in `insert_one'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongoid-5.2.0/lib/mongoid/query_cache.rb:182:in `insert_one_with_clear_cache'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongoid-5.2.0/lib/mongoid/persistable/creatable.rb:79:in `insert_as_root'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongoid-5.2.0/lib/mongoid/persistable/creatable.rb:27:in `block in insert'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongoid-5.2.0/lib/mongoid/persistable/creatable.rb:118:in `block (2 levels) in prepare_insert'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/activesupport-4.0.2/lib/active_support/callbacks.rb:373:in `_run__4510143668266298615__create__callbacks'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/activesupport-4.0.2/lib/active_support/callbacks.rb:80:in `run_callbacks'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongoid-5.2.0/lib/mongoid/interceptable.rb:138:in `run_callbacks'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongoid-5.2.0/lib/mongoid/persistable/creatable.rb:117:in `block in prepare_insert'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/activesupport-4.0.2/lib/active_support/callbacks.rb:373:in `_run__4510143668266298615__save__callbacks'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/activesupport-4.0.2/lib/active_support/callbacks.rb:80:in `run_callbacks'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongoid-5.2.0/lib/mongoid/interceptable.rb:138:in `run_callbacks'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongoid-5.2.0/lib/mongoid/persistable/creatable.rb:116:in `prepare_insert'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongoid-5.2.0/lib/mongoid/persistable/creatable.rb:23:in `insert'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/mongoid-5.2.0/lib/mongoid/persistable/savable.rb:23:in `save'
from (irb):70
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/railties-4.0.2/lib/rails/commands/console.rb:90:in `start'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/railties-4.0.2/lib/rails/commands/console.rb:9:in `start'
from /home/cassiano/.rvm/gems/ruby-2.3.3/gems/railties-4.0.2/lib/rails/commands.rb:62:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
This can be done? There is a better approach without falling into a Entity-attribute-value model?
Mongoid doesn't know about namespace when you try to use dynamic model. In order to fix it you should set namespace with store_in
Example:
class DynamicCollection
def self.create(collection, fields)
klass = Class.new do
include Mongoid::Document
store_in collection: collection.downcase
fields.each do |item|
field item[:name], type: item[:type]
end
end
Object.const_set(collection, klass)
end
end
fields = [
{name: 'name', type: String},
{name: 'email', type: String}
]
DynamicCollection.create('Demo', fields)
Demo.create!(name: 'SomeValue', email: 'SomeValue')
I didn't try this locally, and this could be a dumb answer...but I would change
attributes.map to attributes.each seems like map would return an array and would cause an error.
Also...
https://github.com/mongodb/mongoid/blob/master/lib/mongoid/fields.rb#L335
Looking at the source for mongoid. There is a method called add_field that you maybe able to utilize.
I am trying to setup fabricator-gem to handle my models for testing. The problem I am running into is that it doesn't seem to be able to handle polymorphic relations. I am using MongoDB as my database and Mongoid as my ORM. Consider this example:
class Description
include Mongoid::Document
include Mongoid::Timestamps
embeds_many :images, as: :photo, cascade_callbacks: true
end
class Image
include Mongoid::Document
include Mongoid::Timestamps
embedded_in :photo, polymorphic: true
end
Using this code, you can embed Image documents into many different types of documents, because you set polymorphic: true. This turns out to be a problem when using fabricator, because you would like to do something like this:
Fabricator(:description) do |f|
f.images(count: 1) { |description, i| Fabricate(:image, photo: description) }
end
But Fabricator-gem automatically assumes there must be a class named Photo. Therefore, when you run your tests, the following error is thrown:
NameError:
uninitialized constant Photo
How do I tell Fabricator that this is a polymorphic association?
EDIT: Stacktrace Here:
NameError: uninitialized constant PhotoOf
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/activesupport-3.2.11/lib/active_support/inflector/methods.rb:230:in `block in constantize'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/activesupport-3.2.11/lib/active_support/inflector/methods.rb:229:in `each'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/activesupport-3.2.11/lib/active_support/inflector/methods.rb:229:in `constantize'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/activesupport-3.2.11/lib/active_support/core_ext/string/inflections.rb:54:in `constantize'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/mongoid-3.0.17/lib/mongoid/relations/metadata.rb:602:in `klass'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/mongoid-3.0.17/lib/mongoid/relations/builders/nested_attributes/one.rb:33:in `build'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/mongoid-3.0.17/lib/mongoid/attributes/processing.rb:170:in `block in process_relations'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/mongoid-3.0.17/lib/mongoid/attributes/processing.rb:167:in `each_pair'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/mongoid-3.0.17/lib/mongoid/attributes/processing.rb:167:in `process_relations'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/mongoid-3.0.17/lib/mongoid/attributes/processing.rb:153:in `process_pending'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/mongoid-3.0.17/lib/mongoid/attributes/processing.rb:32:in `block in process_attributes'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/mongoid-3.0.17/lib/mongoid/attributes/processing.rb:193:in `with_mass_assignment'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/mongoid-3.0.17/lib/mongoid/attributes/processing.rb:22:in `process_attributes'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/mongoid-3.0.17/lib/mongoid/document.rb:148:in `block in initialize'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/mongoid-3.0.17/lib/mongoid/threaded/lifecycle.rb:84:in `_building'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/mongoid-3.0.17/lib/mongoid/document.rb:143:in `initialize'
... 33 levels...
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/fabrication-2.5.4/lib/fabrication/generator/base.rb:91:in `block in process_attributes'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/fabrication-2.5.4/lib/fabrication/generator/base.rb:90:in `each'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/fabrication-2.5.4/lib/fabrication/generator/base.rb:90:in `process_attributes'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/fabrication-2.5.4/lib/fabrication/generator/base.rb:6:in `build'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/fabrication-2.5.4/lib/fabrication/generator/base.rb:26:in `create'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/fabrication-2.5.4/lib/fabrication/schematic/definition.rb:62:in `block in fabricate'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/fabrication-2.5.4/lib/fabrication/schematic/definition.rb:61:in `instance_eval'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/fabrication-2.5.4/lib/fabrication/schematic/definition.rb:61:in `fabricate'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/fabrication-2.5.4/lib/fabrication/fabricator.rb:10:in `fabricate'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/fabrication-2.5.4/lib/fabrication.rb:51:in `Fabricate'
from (irb):1
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/railties-3.2.11/lib/rails/commands/console.rb:47:in `start'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/railties-3.2.11/lib/rails/commands/console.rb:8:in `start'
from /Users/max/.rvm/gems/ruby-1.9.3-p362/gems/railties-3.2.11/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
I think the issue is actually with how you defined your embeds_many association. Try removing the "as" option completely and see if that fixes the issue.
class Description
include Mongoid::Document
include Mongoid::Timestamps
embeds_many :images, cascade_callbacks: true
end
class Image
include Mongoid::Document
include Mongoid::Timestamps
embedded_in :photo, polymorphic: true
end
Fabrication doesn't attempt to turn attribute names to classes. As long as you have a Fabricator(:image) defined, preferably without the photo association in it, then you should just be able to do this:
Fabricator(:description) do
images(count: 1)
end
When running unit tests I get the following error for some of my tests:
6) Error:
test_name_can't_be_nil(NodeTest):
NoMethodError: undefined method `detect' for :"Node#children":Symbol
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/naming.rb:85:in `model_name'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/errors.rb:315:in `generate_message'
org/jruby/RubyArray.java:2339:in `collect'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/errors.rb:314:in `generate_message'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/errors.rb:235:in `add'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/errors.rb:256:in `add_on_blank'
org/jruby/RubyArray.java:1615:in `each'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/errors.rb:254:in `add_on_blank'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/validations/presence.rb:9:in `validate'
org/jruby/RubyBasicObject.java:1704:in `__send__'
org/jruby/RubyKernel.java:2101:in `send'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activesupport-3.1.4/lib/active_support/callbacks.rb:306:in `_callback_before_47'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activesupport-3.1.4/lib/active_support/callbacks.rb:410:in `_run_validate_callbacks'
org/jruby/RubyBasicObject.java:1698:in `__send__'
org/jruby/RubyKernel.java:2097:in `send'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activesupport-3.1.4/lib/active_support/callbacks.rb:81:in `run_callbacks'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/validations.rb:212:in `run_validations!'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activemodel-3.1.4/lib/active_model/validations.rb:179:in `valid?'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/neo4j-2.0.1-java/lib/neo4j/rails/validations.rb:29:in `valid?'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/neo4j-2.0.1-java/lib/neo4j/rails/callbacks.rb:26:in `valid_with_callbacks?'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/activesupport-3.1.4/lib/active_support/callbacks.rb:405:in `_run_validation_callbacks'
/Users/dave/.rvm/gems/jruby-1.6.7.2/gems/neo4j-2.0.1-java/lib/neo4j/rails/callbacks.rb:26:in `valid_with_callbacks?'
/Users/dave/Projects/myapp/test/test_helper.rb:11:in `assert_presence'
/Users/dave/Projects/myapp/test/unit/node_test.rb:9:in `test_name_can't_be_nil'
org/jruby/RubyBasicObject.java:1698:in `__send__'
The offending test in question is:
class NodeTest < ActiveSupport::TestCase
def assert_presence( model, field)
model.send( (field.to_s + '='), nil )
model.valid?
assert_match /can not be blank/, model.errors[field].join,
"Presence error for #{field} not found on #model.class"
end
def setup
#node = FactoryGirl.build :node
end
test "name can't be nil" do
assert_presence #node, :name
end
....
end
Where Nodes are defined in the model as:
class Node < Neo4j::Rails::Model
include Neo4j::NodeMixin
property :name, type: String, index: :exact
property :description, type: String
has_one(:creator).from(User, :created_nodes)
has_n(:children).to(Node) ## <--- Suspected difficult line
has_n(:parents).from(Node, :children) ## <--- Suspected difficult line
has_n(:capable_users).from(User, :capabilities)
# The following has the Class commented out because this somehow triggers
# an error from the 'has_n(:children).to(Node)' line
has_n(:challenges) #.to(Challenge)
....
end
Basically, the server can run fine, but will crash anytime I try to call valid? on a Node (not other models). Does anyone know why this might be happening?
The problem was my choice of attributes, namely parents (and maybe children).
I took a look at the source in active model where the error was occurring (here), and saw this:
def model_name
#_model_name ||= begin
namespace = self.parents.detect { |n| n.respond_to?(:_railtie) } # <--- this line
ActiveModel::Name.new(self, namespace)
end
end
As you can see, parents appears to be in use. I changed the names and the validations, saving, etc, now works.
Using Rails 2.3.2 (not in a good situation to upgrade at the moment) with ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]. Getting the following error when trying to save when doing validations on the model, if the validations are :on => :update. If I change the validations to :on => :create and create a new record, I don't see the error, and I have no problem saving it if there are no validations.
Completed in 392ms (View: 10, DB: 296) | 200 OK [http://localhost/barfoos/update]
/!\ FAILSAFE /!\ Tue Sep 14 16:38:49 -0400 2010
Status: 500 Internal Server Error
User can't be referred
/path/to/project/vendor/rails/activerecord/lib/active_record/session_store.rb:67:in `dump'
/path/to/project/vendor/rails/activerecord/lib/active_record/session_store.rb:67:in `marshal'
/path/to/project/vendor/rails/activerecord/lib/active_record/session_store.rb:123:in `marshal_data!'
/path/to/project/vendor/rails/activesupport/lib/active_support/callbacks.rb:178:in `send'
/path/to/project/vendor/rails/activesupport/lib/active_support/callbacks.rb:178:in `evaluate_method'
/path/to/project/vendor/rails/activesupport/lib/active_support/callbacks.rb:166:in `call'
/path/to/project/vendor/rails/activesupport/lib/active_support/callbacks.rb:93:in `run'
/path/to/project/vendor/rails/activesupport/lib/active_support/callbacks.rb:92:in `each'
/path/to/project/vendor/rails/activesupport/lib/active_support/callbacks.rb:92:in `send'
/path/to/project/vendor/rails/activesupport/lib/active_support/callbacks.rb:92:in `run'
/path/to/project/vendor/rails/activesupport/lib/active_support/callbacks.rb:276:in `run_callbacks'
/path/to/project/vendor/rails/activerecord/lib/active_record/callbacks.rb:344:in `callback'
/path/to/project/vendor/rails/activerecord/lib/active_record/callbacks.rb:249:in `create_or_update'
/path/to/project/vendor/rails/activerecord/lib/active_record/base.rb:2539:in `save_without_validation'
/path/to/project/vendor/rails/activerecord/lib/active_record/validations.rb:1009:in `save_without_dirty'
/path/to/project/vendor/rails/activerecord/lib/active_record/dirty.rb:79:in `save_without_transactions'
/path/to/project/vendor/rails/activerecord/lib/active_record/transactions.rb:229:in `send'
/path/to/project/vendor/rails/activerecord/lib/active_record/transactions.rb:229:in `with_transaction_returning_status'
/path/to/project/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction'
/path/to/project/vendor/rails/activerecord/lib/active_record/transactions.rb:182:in `transaction'
/path/to/project/vendor/rails/activerecord/lib/active_record/transactions.rb:228:in `with_transaction_returning_status'
/path/to/project/vendor/rails/activerecord/lib/active_record/transactions.rb:196:in `save_without_unsaved_flag'
/path/to/project/vendor/rails/activerecord/lib/active_record/transactions.rb:208:in `rollback_active_record_state!'
/path/to/project/vendor/rails/activerecord/lib/active_record/transactions.rb:196:in `save_without_unsaved_flag'
/path/to/project/vendor/plugins/active_scaffold/lib/extensions/unsaved_record.rb:15:in `save'
/path/to/project/vendor/rails/activerecord/lib/active_record/session_store.rb:300:in `set_session'
/path/to/project/vendor/rails/activerecord/lib/active_record/base.rb:1453:in `silence'
/path/to/project/vendor/rails/activerecord/lib/active_record/session_store.rb:297:in `set_session'
/path/to/project/vendor/rails/actionpack/lib/action_controller/session/abstract_store.rb:132:in `call'
/path/to/project/vendor/rails/activerecord/lib/active_record/query_cache.rb:29:in `call'
/path/to/project/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:34:in `cache'
/path/to/project/vendor/rails/activerecord/lib/active_record/query_cache.rb:9:in `cache'
/path/to/project/vendor/rails/activerecord/lib/active_record/query_cache.rb:28:in `call'
/path/to/project/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:361:in `call'
/path/to/project/vendor/rails/actionpack/lib/action_controller/reloader.rb:9:in `call'
/path/to/project/vendor/rails/actionpack/lib/action_controller/failsafe.rb:11:in `call'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `call'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `synchronize'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `call'
/path/to/project/vendor/rails/actionpack/lib/action_controller/dispatcher.rb:106:in `call'
/path/to/project/vendor/rails/railties/lib/rails/rack/static.rb:31:in `call'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:46:in `call'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:40:in `each'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:40:in `call'
/path/to/project/vendor/rails/railties/lib/rails/rack/log_tailer.rb:17:in `call'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/content_length.rb:13:in `call'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/handler/webrick.rb:50:in `service'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/httpserver.rb:104:in `service'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/httpserver.rb:65:in `run'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:173:in `start_thread'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:162:in `start'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:162:in `start_thread'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:95:in `start'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:92:in `each'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:92:in `start'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:23:in `start'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:82:in `start'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/handler/webrick.rb:14:in `run'
/path/to/project/vendor/rails/railties/lib/commands/server.rb:111
/Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
/Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
script/server:3
The model looks like this:
class Barfoo < ActiveRecord::Base
default_scope :conditions => {:scoping_model_id => ScopingModel.current_version.id}
belongs_to :scoping_model
# validate is false to keep from attempting to validate Foobar on Barfoo save, as Foobar can be saved, even if invalid, unlike Barfoo.
has_one :foobar, :validate => false
validates_presence_of :foobar_id, :on => :create, :message => "can't be blank"
validates_inclusion_of :accepted_an_agreement, :in => [true, false], :on => :update, :message => "please choose whether you agree or disagree"
validates_presence_of :some_option_string, :on => :update, :message => "before agreeing, you must specify the some string", :if => Proc.new { |detail| detail.accepted_an_agreement == true }
validates_presence_of :some_text, :on => :update, :message => "you must provide details if option is 'Other'", :if => Proc.new { |detail| detail.some_option_string == 'Other' }
end
What I specify as the values of these fields doesn't matter, and as Shadwell notes in his comment below, it appears to be session-related. There is one thing session-related and user-related that we do in ApplicationController that could be causing this issue, even though it's never been a problem before now. ApplicationController looks like:
class ApplicationController < ActionController::Base
include ExceptionNotifiable
require 'something_that_defines_update_method_that_we_redefine_in_controller'
include Userstamp
ActionController::Base.session_options[:httponly] = true
ActionController::Base.session_options[:secure] = true
prepend_before_filter :user_setting_method
...
protected
def user_setting_method
session[:username] ||= optional_override_username
session[:username] = session[:username] # touch the session for timeout purposes
#user ||= User.find_by_username session[:username]
true
end
...
end
Search didn't bring up much about /!\ FAILSAFE /!\ with User can't be referred. Any idea about what would cause this and are there common solutions to this or things to look for that might be wrong?
Note that the foobar instance attached to this is saved, but in this particular case, foobar has previously been saved long before, but does not validate (was saved without validation, which is a normal possible state, since it is data from a multi-page form that saves the data partially and user can come back and correct later to finish).
After continuing to develop the model a bit more I started getting another error:
/!\ FAILSAFE /!\ Fri Sep 17 14:53:50 -0400 2010
Status: 500 Internal Server Error
can't dump hash with default proc
I tried saving the model in console and was successful, but saw some wierd things. It was asking for foobar_id to be valid (for example) when I'd already set a valid foobar on the model. So, I talked about it with a team member and heard that he had read about issues trying to validate on id of an associated object like that.
I removed:
validates_presence_of :foobar_id, :on => :create, :message => "can't be blank"
and it worked.
But, it was suggested to me by another coworker that the issues I was having were probably related to doing validates_presence_of :foobar_id, when, in the controller, I was attempting to set foobar:
barfoo.foobar = foobar
rather than setting foobar_id like:
barfoor.foobar_id = foobar.id
I also noticed that, with the former example, it wasn't setting foobar_id in the related row in the database.
After changing it to set foobar_id on barfoo, it seems to save on create and update as long as there is no update validation. However, if I add validation that validates :on => :update, it fails.
Im so late here. But I too had the same problem and I got a temporary fix for it
Just Override the marshal method in activerecord/lib/active_record/session_store.rb
ActiveRecord::SessionStore::ClassMethods.module_eval do
def marshal(data)
# To prevent from Marshal dump error
begin
::Base64.encode64(Marshal.dump(data)) if data
rescue
# Checks for any ActiveRecord object in session variables and reloads it
data.each_pair do |key,obj|
if obj.is_a?(ActiveRecord::Base) || obj.is_a?(Array)
unless obj.is_a?(Array)
data[key] = obj.reload
next
end
data[key].collect do |it_obj|
if obj.is_a?(ActiveRecord::Base)
it_obj.reload
else
it_obj
end
end
end
end
::Base64.encode64(Marshal.dump(data)) if data
end
end
end
In simple it will reload all the ActiveRecord objects present in the session variable