Rails .includes() returning 'undefined method' - ruby-on-rails

I have a Company object with an associated Location.
Company has_many :locations
Location belongs_to :company
When I call:
#company = Company.find(5).includes(:locations)
I get the error:
NoMethodError: undefined method `includes' for #<Company:0x000000066ad398>
I'm following the rubyonrails.org instructions to a T... as far as I can tell.

find() triggers a database query, and returns an instance of the model. You can't call includes on it, as includes is supposed to have an ActiveRecord::Relation as receiver.
You need to invert the order: find must stay at the end:
#company = Company.includes(:locations).find(5)

Did you check the records in the database on location.rb model. The company_id is there?
You can use pry-rails in order to debug the code. Your code looks ok.
The json you are creating is with jbuilder? because is that the case, you need to create the corresponding each loop.

Related

Rails Associations don't work

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

undefined method 'id' for #<Page::ActiveRecord_Associations_CollectionProxy:0x007f4723af2208>

I have no idea what is going on with a query I am doing in Rails console. I am running Rails 4.1.5. First I get a group of items:
pages = Item.item_steps.map {|item| item.pages }
Once I have these pages, I then find out the class:
pages.class
#array
So, I now have an array. Easy enough as I know a ton of methods that you can run on an array. However, when I do any valid array method on the pages array it doesn't work. For example:
pages.map(&:id)
NoMethodError: undefined method `domain_id' for #<Page::ActiveRecord_Associations_CollectionProxy:0x007f4723af2208>
or
irb(main):090:0> pages.pluck("id")
NoMethodError: undefined method `pluck' for #<Array:0x007f4725681640>
I just want to get the "id" from the pages array, but nothing I know of works with this.
thanks
Mike
If you read carefully through the errors, I think you would see what the issue is. Your current query produces the following type of result:
[ACollectionOfPages, ACollectionOfPages, ...]
So your map code is trying to call #id on an ActiveRecord collection, because that is what each element of your array is.
If you really want to use your current code, I'd run:
pages.map { |collection| collection.map(&:id) } # possibly with .flatten
You would be better of creating an association like:
class Item < ActiveRecord::Base
has_many :item_steps
has_many :pages, through: :item_steps
end
Then, Item.pages will return an ActiveRecord collection, so you could run Item.pages.pluck(:id).

Make a method on an array of Rails models

I have a model, Report and I'd like to create a method users such that I can call #reports.users and get a list of all users for all reports in the array. Where do I write the function definition?
seems like you need to add static method in your reports model. Its better if you name your method some thing other than 'users' because if you have association like this
has_many :users
it will cause couple of errors or may be anonymous behaviors.
def self.get_all_users
all_users = collect{|report| report.users}
all_users.flatten!
end
now
#reports.get_all_users
will return all users
I think you need relationship to call that function
In Your reports model,
add these
belongs_to :user
In Your user model
add
has_many :reports
Make sure your report model has user_id field.
Then you can call
#report.users from your report controller.
like this in your report controller index method
#reports = Report.users

Having trouble in tracing code in Rails

I am currently struggling with this piece of code
#play = current_user.playlist.find_by_id(params[:id])
What does current_user.playlist.find_by_id() mean? How can I trace this code to find current_user, playlist and find_by_id() function?
You could be using devise, if that is the case, current_user returns an instance of class User which is the currently logged in user. Or nil if there is no logged in user.
playlist is a method defined in class User, you should find this class in app/models/user.rb, usually this method would be defined with:
has_one :playlist
or:
belongs_to :playlist
find_by_id is a method defined by Rails for class User, you won't see this directly in file. It is created when you have something like this:
class User < ActiveRecord::Base
ActiveRecord::Base creates a lot of methods more.
Debug your code
I would print each part of the sentence
p current_user
p current_user.playlist
p params[:id]
p current_user.playlist.find_by_id(params[:id])
and check results in my server console, you could spot which of these is the first nil.
In Ruby, everything is an object, and objects have methods. Objects also have types.
Your top-level object there is current_user. This is an instance of some class - you can find out what kind by looking at current_user.class. I suspect you're going to find that it's an instance of User.
So, you find where your User is defined. This is likely a model, defined in app/models/user.rb. This model will specify a number of attributes and associations. In this case, you likely have a has_many :playlists association. What this does is set up an association between a User instance and a number of Playlist instances. Given a user instance, user_instance.playlists accesses this association. Your Playlist model will have a user_id field that associates a playlist with a user record. You can read more about associations in the relevant documentation.
Finally, this association will have a number of methods from Rails. ActiveRecord has a standard set of finders, as well as some "magic" finders like find_by_id, which infer the field to find from based on the method name. find_by_id(params[:id]) is functionally equivalent to something like find_by(:id => params[:id]), but it's a little more English-y. You can read more about this in the Dynamic Finders method of the documentation.
find_by_id will generate the SQL necessary to find the playlist records with that ID that also have a user_id matching current_user's ID. If it finds a matching record, it will instantiate a Playlist record with the data it retrieved and return it. If no matching record is found, it will return nil.

Error when I use a relational callback in a method

I'd like to have read-only access to model's attributes (:test) that is related to another model (:query) by a has_many association.
I can get the associated :test object to save when I create and associate a new :query, but I can't work with that associated :test's attributes in a `before_create' method.
From what I'm reading in the API documentation I should be able to use the association method (#test = #query.test.whatever) to use the "whatever" attribute, but I am getting the following error when I try to run that code: private method 'test' called for nil:NilClass.
:query is related to :test in a belongs_to relationship...
I've tried #test = #query.test.build to instantiate the test object in my method, but that does not work either.
You simply got a name collision. Every object in Ruby has its private method test.

Resources