Error when I use a relational callback in a method - ruby-on-rails

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.

Related

Rails .includes() returning 'undefined method'

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.

How can I access to related object by string field name in Ruby on Rails ActiveRecord?

Usually when we need to use ActiveRecord related object, we write such code:
main_object.related_object
Where main_object is instance of MainObject class and related_object is instance of RelatedObject that connected to MainObject via related_object_id field:
class MainObject < ActiveRecord::Base
:has_one => :related_object
end
class RelatedObject < ActiveRecord::Base
:belongs_to => :main_object
end
Count of relations might be difference and more than one. Also my task supposes custom queries where I don't know which one relation will be used.
So, I want to get related object via its name, eg:
main_object.relations['related_object']
Is it possible in Ruby on Rails ActiveRecord?
You can use public_send
main_object.public_send(:related_object)
ActiveRecord objects has association method returns association information for name.
It return ActiveRecord::Associations::* class instance that contains target method:
association = main_object.association :related_object
association.target # returns RelatedObject instance that I wanted

How to initialize record from session variable in rails so that we need not to execute query for initializing a record?

Is there any way to initialize a record from session. for e.g I have a organization object and I put this in session object like
session[:organization] = organization
Now I made a custom method current_organization (I know about devise) like
def current_organization
Organization.new(session[:organization])
end
This will return organization object. My organization belongs_to a team a devise model and team has_many :organizations but when I call
current_team.organizations.includes?(current_organization)
in view. It is returning false even if it is included in team's organizations but doing this
current_team.organizations.reload.includes?(current_organization)
is returning true. I set the session variable with organization object before calling view where i am using above method. Is there any thing which I missed like I am not able to figure out the reason for not returning true even it is included?
Try saving the record first.
Until you save it into the database, it is likely not to show up when you query for the team's organization children.
session[:organization_id] = organization.id
def current_organization
Organization.find session[:organization_id]
end
Ok after some googling i found that instead of using
Organization.new(session[:organization])
I should use
Organization.instantiate(session[:organization])
From apidock I found that
instantiate(attributes, column_types = {}) public
Given an attributes hash, instantiate returns a new instance of the
appropriate class. Accepts only keys as strings.
For example, Post.all may return Comments, Messages, and Emails by
storing the record’s subclass in a type attribute. By calling
instantiate instead of new, finder methods ensure they get new
instances of the appropriate class for each record.

Trying to build a one to one relationship between two preexisting models

I am new to rails and I am trying to build a one to one relationship between two preexisting models (test and test_type) in rails.
Here is my workflow.
has_one :test_type - to tests model
belongs_to :test - to test_types model
rails g migration Add_Test_Type_To_Test test_type:references
rake db:migrate
Now that looks like it has worked ok but when I try to verify that it looks like it hasn't.
rails console
#type = TestTypes.new :name => "My Type"
#type.save
#test = Tests.new :name => "My Test"
TestTypes.find(1) //returns record ok
#test.test_type //returns nil
#test.test_type = TestTypes.find(1) //NameError: uninitialized constant Tests::TestType
#test.test_type //still nil
According to the output it finds my type in the database but it doesn't seem to be able to add it to my test class which indicates to me that the relationship is not working.
Is anybody able to tell what I am doing wrong?
Does it work if you just change one line of code belongs_to :test -> has_one :test to make it one-on-one relationship. But I think your error comes from the fact that you have not added test_type instance to test_type attribute of test object. So before making #test.test_type request you need to add it #test.test_type = #test_type. If you wanna save the change to database then update_attribute method is very useful for that purpose update_attribute(name, value), #test.update_attribute('test_type', #test_type)
Updated answer: Rails Guide says:
4.2.1 Methods Added by has_one
When you declare a has_one association, the declaring class automatically gains five methods related to the association:
association(force_reload = false)
association=(associate)
build_association(attributes = {})
create_association(attributes = {})
create_association!(attributes = {}
so try this #test.create_test_type(test_id: test.id), that bit of code can replace the following code I mentioned earlier #test.test_type (sorry I'm not Rails expert - still learning)

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.

Resources