I have a relationship between User and Organization:
User migration file: t.references :organization, index: true, foreign_key: true
t.string :xml_file, null: false
User model file: belongs_to :organization
Organization model file: has_one :user
The user model contains a variable xml_file, which is a file stored somewhere (haven't written that controller methods yet). I am trying to write an integration test:
def setup
emptymap = fixture_file_upload('test/fixtures/empty.xml', 'application/xml', :binary) # I have uploaded this file in the fixtures directory.
#organization = organizations(:one) # Which is in the organizations fixtures file.
#user = #organization.users.build(xml_file: emptymap)
end
test "should be valid" do
assert #user.valid?
end
This generates the error (referring to the #user line in the test):
NoMethodError: undefined method `users' for #<Organization:0x00000008a41d18>
If I change the #user line in def setup to #user = #organization.user.build(xml_file: emptymap) it generates the error message: NoMethodError: undefined methodbuild' for nil:NilClass`. So that doesn't seem to be it, either.
Any idea what I am doing wrong here?
build as you use it only works with collections. since you have in User belongs_to :organization and in Organizationhas one :user` you don't have a collection, you have a one-to-one relationship.
So the correct attribute is #organization.user
And there's a special format for one-to-one relationships... build_(something)
#organization.build_user(xml_file: emptymap)
Inspect the string xml_file to see what.it contains. Have you associated an uploader with it?
Related
From inside edit action in the contacts controller have ...
#programs << #contact.program
Which produces the following error:
NoMethodError - undefined method `<<' for Program::ActiveRecord_Relation
Contacts Model:
belongs_to :program
Program Model:
has_many :contacts
validates :name, presence: true, uniqueness: true
#programs.class
Program::ActiveRecord_Relation
#contact.program.class
Program(id: integer, name: string, active: boolean, created_at: datetime, updated_at: datetime)
Question: Why does this operation fail? Why can't the record get added to the record collection. What is preventing the collection(ActiveRecord_Relation) from adding the record?
You're contradicting yourself here:
Program has_many contacts vs Programs << Contact.program
If you're trying to add a Contact to a particular program, you would be looking at adding the contact:
program.contacts << contact
And if you're trying to set the program for the contact:
contact.program = program
What does not make sense, however, is to try to add something to “programs”, which isn't a relationship. Nothing in this system as you've defined it has_many :programs, so #programs.<< cannot possibly act on a relationship.
You're receiving this error because the ActiveRecord::Relation class is only a collection of results returned by an ActiveRecord query. You probably got it by running Program.where or a similar query. It is not an ActiveRecord::Association and therefore you cannot add more records to it.
You must instead use the association returned by the parent object.
Here's an example of what you're doing, vs what you should be doing:
class User < ApplicationRecord
has_many :programs
end
class Program < ApplicationRecord
belongs_to :user
end
new_program = Program.new
# What you're attempting.
programs_where = Program.where(user_id: User.first) # Class is Program::ActiveRecord_Relation
programs_where << new_program # Throws Error b/c << is not available on ActiveRecord::Relation objects.
# What you should be attempting.
user = User.first
programs_assoc = user.programs # Returns Programs::ActiveRecord_Associations_CollectionProxy
programs_assoc << new_program # Returns Correctly
Note: It's not clear how #programs is defined. Is this answer does not work for you then please provide the complete controller code, as well as the other model you're using.
Im buliding an app with users model which can have different privileges, described by user_types model (id and type as a string). As I am running rails test, I am getting error
LoadError: Unable to autoload constant User_type, expected app/models/user_type.rb to define it
Here is my model:
class UserType < ActiveRecord::Base
belongs_to :user
validates :type, presence: true, length: { maximum: 100 }
end
Below is the controller and test file
class UserTypeController < ApplicationController
def index
#user_type = User_type.all
end
def new
#user_type = User_type.build(user_type_params)
end
private
def user_type_params
params.require(:user_type).permit(:type)
end
end
Testing model:
require 'test_helper'
class UserTypeTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
def setup
#user_type = User_type.new(id:2,type:"test")
end
test "is_valid" do
assert #user_type.valid?
end
end
I wanted to do some basic "is_valid" test and I got an error described above. I have also dropped last model "user_type" and created it as "UserType" but It didn't work.
Throughout your controller and test you use User_type.all, User_type.build, User_type.new, but your model is named UserType.
Your model's class name is UserType. User_type is not defined anywhere. You either keep the model name as is and fix your test and controller, or rename the model name. The former is the Rails convention, so I'd suggest you go with that (the CamelCased name).
Change your model name to UserType as defined in class and from that UserType model's table remove type column or rename it to something like user_type since that is a reserved column name, can be used for single table inheritance only.
Edit: This issue is resolved. The issue was caused by a conflict specific to my application. Another module dynamically created a method named .sources. I was able to troubleshoot by removing the relationship and inspecting the objects method list. Thanks anyways.
I'm using Rails 4.1 with Mongoid 4.0 and have setup a relation as follows:
class Organization
include Mongoid::Document
has_many :sources
end
and
class Source
include Mongoid::Document
belongs_to :organization
end
Then in my rspec test I have:
require 'rails_helper'
RSpec.describe PartnershipsController, :type => :controller do
describe "POST #record" do
it "should create a partnership for the source's organization" do
organization = FactoryGirl.create(:organization)
source = FactoryGirl.create(:source)
organization.sources.push source
end
end
There's more after, but the test fails at the organization.sources.push source line with:
undefined method `push' for nil:NilClass
I don't understand why the error is happening. Looks like in the mongoid documentation that's how I should be adding the related source, but so far no dice. What is the correct way to make this relation?
Edit: adding factory
Here's the organization factory, in case it helps clarify something:
FactoryGirl.define do
factory :organization do
app_name = Faker::App.name
company_name = Faker::Company.name
sequence(:name) { |n| "#{([app_name, company_name].sample)}#{n}" }
defaults_hash = { 'item_type' => 'charity', 'child_item_type' => 'product'}
defaults defaults_hash
end
end
I have the following factory:
FactoryGirl.define do
factory :poem do
skip_create
title "Poem title"
intro_verse
trait_verse
message_verse
end
end
for the following non active record model class:
class Poem
attr_accessor :title, :intro_verse, :trait_verse, :message_verse
end
Can I create a factory for such a class?
When I run the following test:
it "has a valid factory" do
expect(build(:poem)).to be_valid
end
I get the following error:
Failure/Error: expect(build(:poem)).to be_valid
NoMethodError:
undefined method `valid?'
The error is because the class does not have an instance method valid?. (Active Record models have this defined by default)
You need to come up with some logic for determining whether a Poem instance is valid or not, and write a valid? method accordingly.
IIRC, the syntax expect(something).to be_condition simply calls the method condition? on something and fails if it returns false.
Use the ActiveModel::Validations module to adds the ability to validate class objects like in Active Record:
class Poem
include ActiveModel::Validations
validates :title, presence: true
attr_accessor :title, :intro_verse, :trait_verse, :message_verse
end
poem = Poem.new
poem.valid? #false
poem.title = "title"
poem.valid? #true
Wondering if someone can help me find this issue. I'm using rails 4, ruby 2, and have spent alot of time trying different accessors, etc and nothing has worked.
The whole plan model:
class Plan < ActiveRecord::Base
has_many :users
end
Some of the user model:
class User < ActiveRecord::Base
...
validate :plan_type_valid
belongs_to :plan
...
def plan_type_valid
if free_ok
# the following line causes error
valid_plans = Plan.where(price_tier: plan.price_tier).pluck(:id)
else
valid_plans = Plan.where(price_tier: plan.price_tier).where.not(stripe_id: 'free').pluck(:id)
end
unless valid_plans.include?(plan.id)
errors.add(:plan_id, 'is invalid')
end
end
end
Here's a pastebin of the whole users controller:
http://pastebin.com/GnXz3R8k
the migration was all messed up because of a superuser issue and it wasn't able to create the extensions for hstore field type.