Find items with belongs_to associations in Rails? - ruby-on-rails

I have a model called Kase each "Case" is assigned to a contact person via the following code:
class Kase < ActiveRecord::Base
validates_presence_of :jobno
has_many :notes, :order => "created_at DESC"
belongs_to :company # foreign key: company_id
belongs_to :person # foreign key in join table
belongs_to :surveyor,
:class_name => "Company",
:foreign_key => "appointedsurveyor_id"
belongs_to :surveyorperson,
:class_name => "Person",
:foreign_key => "surveyorperson_id"
I was wondering if it is possible to list on the contacts page all of the kases that that person is associated with.
I assume I need to use the find command within the Person model? Maybe something like the following?
def index
#kases = Person.Kase.find(:person_id)
or am I completely misunderstanding everything again?
Thanks,
Danny
EDIT:
If I use:
#kases= #person.kases
I can successfully do the following:
<% if #person.kases.empty? %>
No Cases Found
<% end %>
<% if #person.kases %>
This person has a case assigned to them
<% end %>
but how do I output the "jobref" field from the kase table for each record found?

Maybe following will work:
#person.kase.conditions({:person_id => some_id})
where some_id is an integer value.
Edit
you have association so you can use directly as follows:
#kases= #person.kases
in your show.rhtml you can use instance variable directly in your .rhtml
also #kases is an array so you have to iterate over it.
<% if #kases.blank? %>
No Kase found.
<% else %>
<% for kase in #kases %>
<%=h kase.jobref %>
<% end %>
<% end %>

If your person model has the association has_many :kases then, you can get all the cases that belongs to a person using this
#kases = Person.find(person_id).kases
Assuming person_id has the id of the person that you want to see the cases for.

You would probably want something like
has_many :kases
in your Person model, which lets you do #kases = Person.find(person_id).kases
as well as everything else that has_many enables.
An alternate method would be to go through Kase directly:
#kases = Kase.find_all_by_person_id(person_id)

Related

undefined method `concert_id' for #<FollowUp::ActiveRecord_Associations_CollectionProxy:0x00007f8d481b3dc0> Did you mean? concat

I have a model of follow_ups and volunteers as:
class FollowUp < ApplicationRecord
belongs_to :volunteer
belongs_to :member
belongs_to :concert
end
class Volunteer < ApplicationRecord
enum type: [:admin, :regular]
has_many :follow_ups, dependent: :delete_all
has_many :members, through: :follow_ups
end
Now I wanted to print follow_ups by all volunteers.
It was working fine when I tried in rails console i.e Volunteer.first.follow_ups
I want to show those value in the form, what I tried is:
Volunteer.all.each do |volunteer|
volunteer.follow_ups.concert_id
end
The has_many relation denotes a one-to-many association. Instead of returning a single object, it returns a collection of follow_ups.
That said, you can't do volunteer.follow_ups.concert_id, because follow_ups is an Active Record collection. Make an iteration instead:
volunteer.follow_ups.each { |follow_up| puts follow_up.concert_id }
The Ruby on Rails documentation has great content about Active Record Associations.
To collect such information you should use:
volunteer.follow_ups.pluck(:concert_id)
Edit:
It's very important to note that using pluck is more efficient than using iterators like map and each due to saving server RAM and request time. Then you can print to rails logger:
volunteer.follow_ups.pluck(:concert_id).each{|ci| Rails.logger.info ci}
Edit2
Referring to your text
I want to show those value in the form
If I understand you, you want to show concert_id of each follow_up in the volunteer form. in this case you should add
accepts_nested_attributes_for :follow_ups in your volunteer.rb
then:
<%= form_for #volunteer do |f| %>
<%= f.fields_for :follow_ups do |form_builder| %>
<%= label_tag "custom_label", "follow up id : #{form_builder.object.id}, concert_id : #{form_builder.object.concert_id}%>
<% end %>
<% end %>
The fields_for helper will iterate through all follow_ups , then you can get the object for each follow_up using object which allow you to deal with object directly and get your concert_id attribute from it.

How can I synchronize a has_many association using accepts_nested_attributes_for by foreign_key instead of ID?

I would like to synchronize a has_many association by foreign key. It seems I have to write custom code to do this. Is there any Rails / Active Record magic / Gem to achieve this? Specifically, I'd like to synchronize a join-table where the pairs of foreign keys should be unique.
class Food < ActiveRecord::Base
has_many :food_tags, :dependent=>:destroy, :inverse_of => :food
accepts_nested_attributes_for :food_tags, :allow_destroy => true
end
class FoodTag < ActiveRecord::Base
belongs_to :tag, :inverse_of=>:food_tags
belongs_to :food, :inverse_of=>:food_tags
end
class Tag < ActiveRecord::Base
has_many :food_tags, :dependent=>:destroy, :inverse_of=>:tag
has_many :foods, :through=>:food_tags
end
For my form with nested attributes (or my JSON API), I'd really like to omit the FoodTag id and use the tag_id to synchronize when updating a food.
I want to submit this on update to show that the tag is set or cleared
# this one is set
food[food_tag_attributes][0][tag_id] = 2114
food[food_tag_attributes][0][_destroy] = false
# this one is cleared
food[food_tag_attributes][1][tag_id] = 2116
food[food_tag_attributes][1][_destroy] = true
Instead, I have to submit this for update:
# this one is set
food[food_tag_attributes][0][id] = 109293
food[food_tag_attributes][0][tag_id] = 2114
food[food_tag_attributes][0][_destroy] = false
# this one is cleared
food[food_tag_attributes][0][id] = 109294
food[food_tag_attributes][1][tag_id] = 2116
food[food_tag_attributes][1][_destroy] = true
This pushes a burden to the client to know the IDs of the food tag records instead of just being able to Set or Clear tags based on the tag id.
Can this be done easily? I'm sure I could write a before_save filter on Food, but it seems like there should be a reasonably generic solution.
There is an option called index: for fields_for in the view helper. You can set the index as your foreign_key. Then instead of sequential or some arbitrary numbers, your foreign_key will be used as the key to refer to your object.
EDIT:
<%= form_for #person do |person_form| %>
<%= person_form.text_field :name %>
<% #person.addresses.each do |address| %>
<%= person_form.fields_for address, **index**: address.id do |address_form|%>
<%= address_form.text_field :city %>
<% end %>
<% end %>
<% end %>

rails relationship. Rails 4

I'm new in the world of rails developers. Please, help me to understand.
I've 3 tables:
Calls, Questions, Results
Calls is:
id, name, date
Questions is:
id, question
Results is:
id, call_id, question_id, result
I've read the Rails manual, as i understand i've created 3 models.
In my model Call.rb
I've done next relationship:
has_many :results
has_many :question, through: :results
My Result.rb
belongs_to :call
belongs_to :question
My Question.rb
has_many :result
So, there are can be many records in the table "results" with one call_id, and it's can be one relation with question through results table
If if try to launch code like this:
#calls = Call.all
Than on my view:
<% #calls.each do |call| %>
<%= call.result.result %>
<% end %>
i've error that "result is undefined method". But it's must be a property.
What i do wrong?
Thanks!
According to your schema, your associations should look like this
class Call < ActiveRecord::Base
has_many :questions
has_many :results
end
class Question < ActiveRecord::Base
belongs_to :call
end
class Result < ActiveRecord::Base
belongs_to :call
end
So in the view,
<% #calls.each do |call| %>
<% call.results.each do |result| %>
<%= result.result%>
<% end %>
<% end %>
A few things.
First, you need to fix your associations so the plural and singular tenses match. has_many :result does not work as Marcelo points out.
Second, you need to ensure that your tables actually have the correct id's to make the associations work. Use the rails console to inspect Result. From your question info, it should have attributes for call_id and question_id. Once you've confirmed this, create a few objects in the console and test your associations.
#call = Call.create(name: "test", date: Time.now)
#result = Result.create(call_id: #call.id, result: "some result")
Then
#call.result # should yield the Result record you just created
Lastly, you need to rename the result attribute for Result. That's super confusing and will only cause problems.
The first thing I notice is that your call should have many questions, and many results through questions. That's because calls own questions, which in turn own results themselves.
class Call < ActiveRecord::Base
has_many :questions
has_many :results, through: :questions
end
You didn't need call_id in Result class. But, if you wish to keep it there, you dont need through: :questions in your call class (given there is a direct relation between them)
In your Question class, I assume it is a typo, but it should be plural
has_many :results
Having said that, your loop through calls will bring results (plural) and not result (singular) given that a call may have many results. Therefore:
<% #calls.each do |call| %>
<% call.results.each do |result| %>
<%= call.result %>
<% end %>
<% end %>

Ruby on Rails collection_select complexity

i have the following Problem, i Have the following in my customer bill view
<%= f.collection_select :product_id,Product.all,:id,:name %>
This is getting list of all the products from "Product" model and giving option to select from it. But i want to select the list of products from the "StoreOpeningStock" model.
I have these in my model
class Product< ActiveRecord::Base
has_many :store_opening_stocks
has_many :customer_bills
attr_accessible :name
end
class StoreOpeningStock < ActiveRecord::Base
attr_accessible :product_id
belongs_to :product
end
class CustomerBill < ActiveRecord::Base
attr_accessible :product_id
belongs_to :product
accepts_nested_attributes_for :store_opening_stock
end
Can anyone guide me how i can get product name and id from store_opening_stock??? Should i use Helpers??? or is there any other way?? Thanks in advance
I tried using helpers
def getting_prod_names
#sto = StoreOpeningStock.all
for x in #sto
[
['{x.product.title}', '{x.product_id}']
]
end
end
getting following output
<%= f.select :product_id, options_for_select(getting_prod_names) %>
ANy Help?? :)
When you create a form the data used to ccreate a collection_select isnt limited to the Class your going to create an object for. You could simply do the following:
<%= f.collection_select :product_id,StoreOpeningStock.all,:product_id ,:name %>
This should to it for you,...
add this to your StoreOpeningStock class:
def name
return self.product.name unless self.product.nil?
""
end
You need to clarify the relationship between your models...
But just to give you an idea. You can define the collection of products you want to display in your controller, inside the action related to the view (where you are displaying the collection).
Controller:
#products= #here you should call all products you want
Then, your collection of products can be displayed like:
<%= f.collection_select :product_id, #products,:id,:name %>
EDIT
You need to revise the relationship between your models. A product has many customer_bills, but are you sure that each customer_bill belongs to a single product?
I think you have a many-to-many relationship, as a customer_bill can also have many products.
If I understand it right, the solution is to create a ProductLine model between this many-to-many relationship.
Also, what is the difference between Product and StoreOpeningStock? What attributes have you included in the StoreOpeningStock?
If you have created this model only to show the availability of products, why don't you add an attribute in the Product model, for example a boolean column called availability.
So you want to find all products that have a StoreOpeningStock.
This is solely a model concern and have nothing to do with helpers.
class Product
# Find all products that have a StoreOpeningStock
def self.in_stock
find(StoreOpeningStock.product_ids)
end
end
class StoreOpeningStock
# Collect all product ids from stocks
def self.product_ids
uniq.pluck(:product_id)
end
end
Now you can use Product.in_stock instead of Product.all to have the only ones in stock.
I'd add a scope to your products model:
class Product< ActiveRecord::Base
has_many :store_opening_stocks
has_many :customer_bills
attr_accessible :name
scope :having_store_opening_stocks, :joins => : store_opening_stocks, :select => 'distinct product.*', :conditions => 'store_opening_stocks.product > 0'
end
Then you can use Product.all.having_store_opening_stocks to select only products with such stocks, for example:
<%= f.select :product_id, Product.having_store_opening_stocks.map { |product| [product.name, product.id] } %>

how is this rails call getting an object from just an id?

i have a User model and a UserMessage model (a model for holding the private messages between two users)
in my view i have..
<% if #message_items.any? %>
<ol class="messages">
<%= render partial: 'message_item', collection: #message_items%>
</ol>
<%= will_paginate #message_items %>
<% end %>
which i render with...
<li id="<%= message_item.id %>">
<span class="user">
<%= link_to message_item.user.name, message_item.user %>
</span>
<span>
<%= message_item.title %>
</span>
<span>
<%= message_item.body %>
</span>
</li>
how is the object UserMessage(which is coming from message_item) able to render the User object? my design for the UserMessage just has the following attributes "id, user_id, from_id, title, body, created_at, updated_at".
i guess its from the user_id, and rails somehow makes the connection and is able to find the User object from the user_id. is that correct?
but i what i really want though, is the user from the from_id (the person sending the message). is there a way to retrieve that? i know doing something like.. message_item.user.from_id does not work.
the only way i could think of that works is by doing
<%= User.find(id= message_item.from_id).name %>
but that doesn't seem right putting so much code in my view. sorry but ive been super stuck. help would be much appreciated. thanks
You need the following models
class User < ActiveRecord::Base
has_many :received_user_messages,
:class_name => "UserMessage", :foreign_key => :receiver_id
has_many :sent_user_messages, :class_name => "UserMessage",
:class_name => "UserMessage", :foreign_key => :sender_id
end
class UserMessage < ActiveRecord::Base
# should have sender_id and receiver_id columns
# make sure you index these columns
belongs_to :sender, :class_name => "User"
belongs_to :receiver, :class_name => "User"
end
Do the following, to list the messages received by an an user:
current_user.received_messages(:include => :sender).each do |message|
p "[#{message.sender.name}]: #{message.content}"
end
Do the following, to list the messages sent by an an user:
current_user.sent_messages(:include => :receiver).each do |message|
p "[#{message.receiver.name}]: #{message.content}"
end
i think you are looking for foreign_key option for belongs_to in model. So what you need is to specify something like sender/from relation with from_id in UserMessage message
belongs_to :sender, foreign_key: :from_id, class_name: "User"
Then in template you just call this relation in view.
message_item.sender
It should work same as message_item.user.
For further reference visit documentation for associations
In addition i recommend you not call .name method in template, but specify to_s method in your model. Good approach pointed by klump in his answer is to use .include method for better performance. It will load user data while loading UserMessage data, not in another query.
Article.find :all, :include => :revisions
Code was derived from another answer — Rails ActiveRecord: Is a combined :include and :conditions query possible?
Try this:
In your UserMessage class, make two class methods named sender and recipient that perform the complex queries you want. Then use these methods in your view.
First you need to set the associations. I guess that one user has many messages and one message belongs to one user.
add to the models:
app/models/user.rb
has_many :user_messages
*app/models/user_messages.rb*
belongs_to :user
You might need to add a column to your user_messages table, called user_id
When you fetch the messages in the controller, tell rails to load the associated user right away, so rails doesnt have to do this later on:
#message_items = UserMessage.includes( :user ).all
Now you can access the user object "owning" the message really easy:
<%= message_item.user.name %>
If you need all the messages owned by a user this also is easy now:
#user = User.find( some_id )
#user.messages # this returns an array with all the message objects

Resources