I have an Application model in a Rails 4 app.
It is giving me some strange errors in tests, including
NoMethodError: undefined method `user_id=' for #<Application:0x007f851222d370>
and
ActiveModel::MissingAttributeError: can't write unknown attribute `user_id`
The model definitely has a user_id column. The migration looks like this:
....
t.references :user, index: true, foreign_key: true
...
and inspecting Application.column_names in the console reveals it to be there.
application.rb and user.rb both have the relevant belongs_to and has_many calls defined.
I'm scratching my head and the only thing I can think of is that the term Application behaves strangely in Rails. Is this the case? Or have I missed something obvious?
Rails does not declare Application in the "top-level namespace". There is Rails.application and rails generates a ApplicationController by default.
However you will need to often need to explicitly use ::Application to avoid confusion with Rails::Application.
You don't even have to follow the Rails convention of extending ApplicationController.
However that said having a model named Application may be a bad idea since any poor sod who later has to work on your code will be very confused.
It's a conflict with Rails::Application class or its subclass, defined in config/application.rb, I believe.
Related
I'm trying to manually add data to a table in rails using the rails console, but I keep getting a undefined local variable or method error.
The model is namespaced under ratings:
models/ratings/value_for_money_score.rb
class Ratings::ValueForMoneyScore < ApplicationRecord
end
To try and manually add a record to the database, I run the following in the console:
$ RatingsValueForMoneyScore.create(score: '1', description:"Terrible, definitely not worth what was paid!")
And I get this error: NameError: uninitialized constant RatingsValueForMoneyScore
I have tried a few different versions such as
RatingsValueForMoneyScores.create,
Ratings_ValueForMoneyScores.create,
ratings_value_for_money_scores.create but keep getting the same error. What am I doing wrong?
Try
::ValueForMoneyScore.create(score: '1', description:"Terrible, definitely not worth what was paid!")
The error is descriptive enough in this case, the class RatingsValueForMoneyScore pretty much doesn't exist. Check your namespace, you have a class name (which should be singular) Rating, and the module ValueForMoneyScore. You'd use either
(after renaming the class to Rating)
Rating.create(...)
or
ValueForMoneyScores.create(...)
Your syntax is equivalent to:
class Rating
module ValueForMoneyScores < ApplicationRecord
...
end
end
The answer was a combination of input, so collecting that in one answer.
My namespaces weren't properly set up (I was using "Ratings" rather than "Rating"), so I fixed this for the tables. My models then looked as follows:
models/rating.rb
class Rating < ApplicationRecord
end
models/rating/value_for_money_score.rb
class Rating::ValueForMoneyScore < ApplicationRecord
end
And then this command worked for creating records in the rating_value_for_money_score table
$ Rating::ValueForMoneyScore.create(score: '1', description: "Test")
I'm trying to do a pretty simple join in my model to list all 'Locations' in a 'Post' with a certain id.
Currently, each post has_many :locations, :through => :location_post. I'm using the 'blogit' gem, which puts posts in a module named 'Blogit::Posts'.
I'm getting a wrong argument type Class (expected Module) error when I try to run the following in my Post.rb model:
module Blogit
class Post < ActiveRecord::Base
before_save :reuse_existing_locations
def reuse_existing_locations
existing_locations = Location.include(Blogit::Post).first
end
How can I do a join through a module?
Thanks in advance!
I'm not sure I understand what you're trying to accomplish so just some notes and observations:
By looking at the code, it's clear that Blogit::Post is a class, not a module.
The include method takes modules (not classes), that's the error you're seeing.
You are calling the include method on the Location model and that seems kind
of strange to me. Did you mean to call includes? But then again that
wouldn't make much sense since it seems like you've got a many to many
relationship between Location and Blogit::Post.
In the Location model (which doesn't need to be in the Blogit namespace), you can simply reference the Blogit::Post model as
follows:
has_many :posts, class_name: "Blogit::Post", ...
If existing_locations is in fact an attribute on the model and you want to assign to it, you need to put self in front of it (as in self.existing_locations). Otherwise you're just creating a local variable.
You probably wanted to use ActiveModels includes instead of Rubys include, which is to include methods from another module.
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 am using Ruby on Rails to create a website for a game I play.
I have a User model and a Starbase model. The relationship I am trying to setup is like so
class User < ActiveRecord::Base
has_many :starbases
end
class Starbase < ActiveRecord::Base
belongs_to :user
end
However when I open script/console and try to access the users starbases it gives me an error: NameError: uninitialized constant User::Starbasis.
It seems as if it is a problem with inflection and rails is not pluralizing starbase correct.
I have tried adding this to the inflections.rb in the intializers folder:
ActiveSupport::Inflector.inflections do |inflect|
inflect.plural 'starbase', 'starbases'
end
but it still does not solve the issue. Could anyone give advice on how to get this working?
Have you tried adding a line for the inverse inflection (i.e. 'singular'):
inflect.singular "starbases", "starbase"
I tried your example in my console and it was the singularization that caused problems, not the other way around. I'm not sure if this fixes other issues (like routes), but it should fix the simple stuff (I think).
Little trick i picked up to double check how Active Support might singularize, or pluralize my Class names, and/or Module names.
have your rails app server running and in a new tab enter into your rails console by typing rails console. In there you can easily double check for the correct style for your names.
long way ActiveSupport::Inflector.pluralize "fish"
# => "fish"
short way "fish".pluralize
# => "fish"
You can find more examples here
https://github.com/rails/rails/blob/master/activesupport/test/inflector_test_cases.rb
I am accessing a database that I can't change and it has a column named valid defined. Anytime I try to access an attribute, I get this exception:
valid? is defined by ActiveRecord
(ActiveRecord::DangerousAttributeError)
The exception makes sense, but since I'm not able to change the database, how can I get around this error?
I tried "overriding" the attribute, but I don't know how to remove the original column. I can successfully call this valid_column method, but any time I try to access another attribute defined in the database, I get the same exception. It still seems to be trying to map the valid column.
def valid_column=(valid)
write_attribute(:valid, valid)
end
def valid_column
read_attribute(:valid)
end
I'm not sure if it matters, but here are the details of my environment:
Windows Ruby 1.8.6
Informix database on a Linux server
activerecord (2.3.4)
activerecord-informix-adapter (1.0.0.9250)
ruby-informix (0.7.1)
Thanks in advance!
Try this:
class MyTable < AR:Base
class << self
def instance_method_already_implemented?(method_name)
return true if method_name == 'valid'
super
end
end
end
It's a hack, and it might not work in rails 3, but it could fix the problem for now.
I found it on the ruby on rails mailing list
If you wanted, you could also look at datamapper, which handles these sort of things somewhat more sanely.
Use safe_attributes - https://github.com/bjones/safe_attributes . It works perfectly out of the box:
class WebsiteUser < ActiveRecord::Base
establish_connection 'cf_website'
set_table_name 'nc_users'
bad_attribute_names :hash
end
Without worrying about ActiveRecord's reserved attributes, just add a gem in your gemfile and the gem will take care of name collisions automatically.
gem 'safe_attributes'
http://goo.gl/OO2H7
For reads you might be able to use SQL's select-as statement. Not sure if the following will work, but a default scope may make this easily do-able.
class MyRecord < ActiveRecord::Base
default_scope :select=> 'valid as valid_column'
end