I have an issue with the includes method in Rails.
I have this user model:
class User < ActiveRecord::Base
has_one :account
end
And this account model:
class Account < ActiveRecord::Base
belongs_to :User
end
Now the user model has :id and :names
and the account model has :user_id and :country
In another controller i want to fetch and display all the user names with their countries.
I am using this query
#users = User.includes(:account).where(some condition)
Please tell me what can I add in the query to fetch all the countries associated with the user names?
Thanks in advance
user should be plural in the controller as you are getting list of records . like this
#users = User.includes(:account)
in view you can do this.
<% #users.each do |user| %>
<%= user.names %>
<%= user.account.country %>
<% end %>
As names is user attribute, you can fetch directly, while country is account's attribute, you can fetch using user.account.country
If it gives you error like
NoMethodError (undefined method `account' for #)
then this means you are converting it into an array in controller itself.
Change your code
eg:
#users = User.includes(:account).where('id < 5')
And in View
<% #users.each do |user| %>
<%= user.name %>
<%= user.account.country %>
<% end %>
Whenever we are using includes it by default does an outer join, so there will may be users who does not have any account and you will get error while trying to access user.account.country as user.account is nil and on the nil object it will try to call country method which does not exist.
Related
is a little project and I try to associate patient model with consultations. one patient has_many :consultations, in my form I have:
<%= f.association :patient %>
I pass the id parameter from the patient to the action 'new' in this way:
<%= link_to new_consultum_path(:id => #patient.id) %>
And in the view I have:
How can I make that the f.association field take the correspondent patient_id automatically?
How can I be sure that the patient_id is the current patient?
If I want to hide this field is that ok if I put
instead of
Is a better way to do this?
And why in the view shows me # patient:0x007f4e7c32cbd0 ?
thanks for your help.
And why in the view shows me # patient:0x007f4e7c32cbd0
This is a Patient object.
It means you need to call an attribute of this object - EG #patient.name.
--
f.association field take the correspondent patient_id automatically
This might help:
It looks like Organization model doesn't have any of these fields: [
:to_label, :name, :title, :to_s ] so SimpleForm can't detect a default
label and value methods for collection. I think you should pass it
manually.
#app/models/patient.rb
class Patient < ActiveRecord::Base
def to_label
"#{name}"
end
end
Apparently, you need to have either title, name or to_label methods in your model in order for f.association to populate the data.
-
How can I be sure that the patient_id is the current patient?
If you're having to verify this, it suggests inconsistencies with your code's structure. If you need the patient_id to be set as the current patient, surely you could set it in the controller:
#app/controllers/consultations_controller.rb
class ConultationsController < ApplicationController
def create
#consultation = Constultation.new
#consultation.patient = current_patient
#consultation.save
end
end
I can provide more context if required.
You want to associate consultations to patients using fields_for, which is similar to form_for, but does not build the form tags.
It you start with your patient object, you can iterate through the consultation associations binding it to form fields as you go.
it would look something like this
<%= form_for #patient do |patient_form| %>
<% patient_form.text_field :any_attribute_on_patient %>
<% #patient.consultations.each do |consultation| %>
<%= patient_form.fields_for consultation do |consultation_fields| %>
<% consultation_fields.text_field :any_attribute_on_consulatation %>
<% end %>
<% end %>
<% end %>
Sorry, the code may not be exactly right.
Check out the docs for field_for here
You will also have to set accepts_nested_attributes_for consultations on patient. When you set accepts_nested_forms_for, Rails will automatically update the associated consultations object to the patient and save any edits you have made. You DEFINITELY want to use accepts_nested_attributes_for most nested form handling of this type.
I'm creating a has_and_belongs_to_many relationship with Rails. Each group has many participants and each participant can be part of many groups.
The relationship seems to be set up ok as I can use check boxes to add relationships using this in my form:
<%= collection_check_boxes(:group, :participant_ids, #participants, :id, :name) %>
However, I need to use a hidden field to submit these relationships (I use AJAX to fetch them in the view) with an array of ids (e.g. [1, 3]). I've tried using a text field like this but it doesn't save the data:
<%= f.text_field :participant_ids %>
When participant_ids saves using the checkboxes and I output it on the show view it's an array of ids but I can't seem to submit it in that format to start with.
Why can't I submit the participant_ids using a text/hidden field and is there a way around this?
For reference I've set up the join table and the models look like this:
class Group < ActiveRecord::Base
has_and_belongs_to_many :participants
end
class Participant < ActiveRecord::Base
has_and_belongs_to_many :groups
end
I also modified the group controller to work with strong parameters like this:
def group_params
params.require(:group).permit(:user_id, :purpose, :participant_ids => [])
end
I can post more code if necessary.
This answer worked for me. You will have to
<% #participants.each do |participant| %>
<% f.hidden_field 'participant_ids][', :value => participant.id %>
<% end %>
I'm adding a new model to my equasion and I'm wondering if there is a way to associate two models into one model then display any/all results within a view. For example, here is what I've currently have;
#tweet_category.order("position").each do |tweet|
<%= tweet.title %>
end
just a short example... now what if I added facebook into this. I was first thinking of creating a model thats named stuff then associate it to tweet_category and facebook_category like so;
class Stuff < ActiveRecord::Base
attr_accessible :title
belongs_to :user
has_many :tweet_category
has_many :facebook_category
end
Now in my controller I'm guessing I would do the following;
class StuffController < ApplicationController
def index
#stuff_list = Stuff.find(:all)
end
end
and in my view I would just simply do the following from above view;
#stuff_list.order("position").each do |stuff|
<%= stuff.title %>
end
am I understanding the logic here??? would that work having two models / two tables db.. etc..
First of all, I don't understand why you would need that "stuff" model. It belongs to users and has_many tweet_category and facebook_category, and just does nothing but offering a "title", when your User model could do the job ( I mean, each user could have many tweets and fb category, instead of having one or several "stuff" which has/have many of them ).
Anyway, if you want to make links between your models and then display everything in a view, first in your User model you just have to do :
class User < ActiveRecord::Base
...
has_many :facebook_categories #( I don't know how rails would pluralize it, btw, I'm just making an assumption )
has_many :tweeter_categories
end
and
class Facebook_category
...
belongs_to :user
end
and do the same fot the tweeter category
Then in your controller :
def show_everything #Here it's a custom action, but you can call it wherever you want
#users = User.all
end
And finally in your view :
<% #users.each do |user| %>
<% user.facebook_categories.all.each do |fb_c| %>
<%= fb_c.title %>
<% end %>
<% user.tweeter_categories.all.each do |t_c| %>
<%= t_c.title %>
<% end %>
<% end %>
Maybe just try to grab a better name for your models, so the pluralization doesn't get messy ( and I saw that the ".all" method is deprecated, so maybe replace it with something
Hope it helps !
Edit :
Basically, when you're doing
#users = User.all
What rails' doing is putting every hash defining every "User" in an array. So, if you want to mix two tables' arrays inside a single array, you can do something like this :
#categories = [] << Facebook_category.all, Tweeter_category.all
You will then have an array ( #category ), filled with 2 arrays ( one ActiveRecord relation for Facebook_category and one for Tweeter_category ). Themselves filled with hashes of their model. So, what you need to do is :
#categories.flatten!
Here's the API for what flatten does ( basically removing all your nested arrays inside your first tarray )
Now, you got a single array of hashes, being the informations from both your model's instances. And, if these informations can be ordered, in your view, you just have to :
<% #categories.order("updated_at").each do |i| %>
<%= i.title %>
<% end %>
There are
a user-model/table,
a schedule-model/table and
a users_schedules-table.
The models has_and_belongs_to_many each other.
I can add a relationship with #user.schedules << #schedule in the controller.
How can I get access to the join-table 'users_schedules' ?
I want to show the users which has_and_belongs_to_many schedules:
I thought about something like this: schedules.users_belongs_to. As you can see in the view-code below.
view: (There is an example I want to add)
<table class="table table-hover">
<tbody>
<% #user_schedules_date.sort.each do |date_time, schedules| %>
<tr class="thead success">
<th colspan="4" scope="col"><p><%= date_time.strftime("%A, %d.%m.%Y") %></p></th>
</tr>
<% for schedule in schedules %>
<tr>
<th scope="row"><p><%= schedule.titel %></p></th>
<td><p><%= schedules.users_belongs_to #ALL USERS WHO ARE BINDED TO THIS SCHEDULE# %></p></td>
<td><p><%= schedule.date_time.strftime("%H:%M:%S") %></p></td>
<td><p><%= schedule.location %></p></td>
<td>
<p>
<%= link_to 'Bearbeiten', {:controller => 'schedule', :action => 'edit', :id => schedule.id} %>
oder
<%= link_to 'löschen', {:controller => 'schedule', :action => 'delete', :id => schedule.id} %>
</p>
</td>
</tr>
<% end %>
<% end %>
</tbody>
</table>
In the controller I tried the following, but I don't know how to replace/fit the placeholder (:email).
controller:
class WelcomeController < ApplicationController
def index
if(current_user)
#user_schedules = current_user.schedules
#user_schedules_date = #user_schedules.order(:date_time).group_by { |sched| sched.date_time.beginning_of_day }
#users_schedules_shared = User.find_by(:email) #HERE I NEED THE USER WHICH BELONGS_TO THIS SCHEDULE
end
end
end
I hope you can understand my problem.
Thanks for your help!
EDIT:
I gather all the data in the controller:
class WelcomeController < ApplicationController
def index
if(current_user)
#user_schedules = current_user.schedules
#user_schedules_date = #user_schedules.order(:date_time).group_by { |sched| sched.date_time.beginning_of_day }
#users_all = User.includes(user_schedules: :schedules)
end
end
end
and edit the view as the following:
<% #users_all.each do |user| %>
<% user.name %>
<% end %>
But I get the following error:
Association named 'user_schedules' was not found on User; perhaps you misspelled it?
I red this, as deyan said, but I dont understand it.
#users_all = User.includes(user_schedules: :schedules) <- returns an array ?!?? (If I understood it correctly)
So I need each array-item.name to show the Users name??
Can anyone tell me what I am doing wrong?
Database:
http://i.stack.imgur.com/Apg7y.png
users
schedules_users (join-table with fk)
schedules
I want to show the users which has_and_belongs_to_many schedules
This will use something called a many-to-many relationship - meaning that if you access the associated data through a model - you'll have an appended attribute / method to capture them.
So what you'd do is the following:
#app/models/schedule.rb
Class Schedule < ActiveRecord::Base
has_and_belongs_to_many :users
end
#app/models/user.rb
Class User < ActiveRecord::Base
has_and_belongs_to_many :schedules
end
This will append a collection to each of these model objects, allowing you to call the collection as required:
#schedules = Schedule.all
#schedules.each do |schedule|
schedule.users #-> outputs a collection
schedule.users.each do |user|
user.name
end
end
Using includes with Rails is actually quite a bad thing, considering you can call ActiveRecord associations to do the heavy-lifting for you
--
has_and_belongs_to_many
Simply, you can't access the has_and_belongs_to_many table directly, as it has no primary_keys in place.
Rails basically uses the relational database infrastructure (through ActiveRecord) to access the associative data. This means that if you're using this particular type of table, you'll just be able to access the collection it provisions:
#app/models/user.rb
Class User < ActiveRecord::Base
has_and_belongs_to_many :schedules
end
#app/models/schedule.rb
Class Schedule < ActiveRecord::Base
has_and_belongs_to_many :users
end
This will allow you to access:
#user = User.find 1
#user.schedules #-> shows schedules collection. You will have to loop through this
If I understand you correctly, you want to show the schedules for your current user, and for each schedule to show what other users belong to it.
Based on your view, to get all users for a schedule, all you would need is to replace schedules.users_belongs_to withschedule.users.
If you want to get together all unique users for all the schedules the current user might have, then in the controller you could do current_user.schedules.collect{|s| s.users|}.uniq. This is only useful if you want to show all users, no matter which schedule each user belongs to.
I would advice you to gather all the data in the controller and then to print it in the view. You could join all tables in a single call to the DB, which might look something like this: User.includes(users_schedules: :schedules) but you would need to adapt it depending on what your models are called.
Methods 1 or 2 are solving your problem using your current code, but might be slow. I would suggest you read more here: http://guides.rubyonrails.org/active_record_querying.html and get all data at once (method 3).
I have a controller which looks something like this:
class EventController < ApplicationController
def index
...
#events = Event.where(['eventdate < ?', DateTime.now]).order("eventdate")
...
end
end
And my model defines the following relationship:
class Event < ActiveRecord::Base
...
has_many :match_items, dependent: :destroy
...
end
I am now trying to access the event_items linked to the events defined in the the instance variable #event in my view as follows:
<h2>Your Events</h2>
<% #events.each do |event| %>
</br><span>
<%= event.eventdate.to_formatted_s(:rfc822) %>
<%= event.event_items.event_comment %>
</span>
<% end %>
the event.event_items.event_comment line throws an error: undefined method 'event_comment' for []:ActiveRecord::Relation
Why can't I not access event_comment as a method?
If I just use event.event_items the line doesn't display an error and shows the whole event_items array with all it's content displayed in my view.
So i thought maybe I can just access the event_commentas part of the array through using:
<%= event.event_items.event_comment[i] %> #where i is the index of event_comment in the array
But this then doesn't return anything in my display.
Any suggestions on how I can access the attribute event_comment stored in my event_items db table? Any help is very much appreciated!
The reason you are getting that error is because event.event_items returns a ActiveRecord::Relation and not an instance of EventComment. Try using:
event.event_items.first.event_comment