I'm hooked up with an API, and I want to show all the profiles the user has. However I only want to show the profiles where 'service' is equal to 'test'.
Currently I'm doing:
<%= debug #client.profiles %>
which, quite obviously shows all the profiles of the client. However I want to only show the profiles where the profiles, service is equal to test.
Does anybody know how to do that? In an ideal situation I create a loop, like so:
#client.profiles.each do |profile|
and it only loops through the profiles, that I want.
You can use where clause for finding profiles where 'service' is equal to 'test'.
#client.profiles.where(service: "test")
Then you can loop with the same for profile.
You can simply do
In client model
class Client < ActiveRecord::Base
has_many :profiles, -> { where(service: "test") }
end
In Profile model
class Profile < ActiveRecord:::Base
belongs_to :client
end
In profiles table must contain client_id
In Controller
class Clients < ApplicationController
def show
#client = Client.find(params[:id])
end
end
IN/app/views/clients/show.html.erb
`
<% #client.profiles.each do |profile| %>
<%= profile.name %>
<%end %>
Related
<% #review.each do |review|%>
<% if review.host_id == #host.id>
<%= #user = User.find(review.user_id) %>
<% end %>
<% end %>
So I'm a bit confused. I have a few things going on here. I'm doing a loop through all reviews of hosts and then checking if the stored host.id value is equal to the active #host object's id that is passed from the controller. Problem is.. Now I need get the user object from the user ID stored in the review but, I'm unsure exactly how to do it. I can't do it from the controller as all this is done in the loop. As you can see I tried to do it with the code above but, I highly doubt I did it right. Please help me out on this. Thanks.
You should pre-load users with loading reviews, in controller. First, you should have belongs_to association, like this:
class Review < ActiveRecord::Base
belongs_to :user
# ...
end
then, in controller, you could use includes, this way:
#reviews = Review.includes(:user)
Now, for every review record in #reviews relation, to get associated user you can call user method, like this:
review.user
What's more, (and that's advantage of using includes) it doesn't fire new SQL query for every single review, so you avoid quite common N + 1 problem.
You can make a relationship in
class Review < ActiveRecord::Base
belongs_to :user
end
and then in view
review.user #gives you user
Put association in Review Model
class Review < ActiveRecord::Base
.
.
.
belongs_to :user
.
.
.
end
After putting association you can directly call association to find user object using Review object.
review.user
But this will raise N+1 query problem, so better user include user while finding review, It will execute only two queries one for finding reviews and another for finding users.
#reviews = Review.includes(:user)
I have a page that outputs all of the user profiles that exist in the system. It was working before, I haven't changed anything, and now it is not working. It is telling me that I have "an undefined method `profile_name' for nil:NilClass", but I refer to profile_name many times elsewhere in the application. Here is the index view page:
<% #profiles.each do |profile| %>
<%= link_to profile.user.inspect, profile_path(profile.user.profile_name) %><br><br>
<% end %>
Here is the profile model:
class Profile < ActiveRecord::Base
belongs_to :user
end
Here is the user model:
class User < ActiveRecord::Base
has_one :profile
Here is the profiles controller:
def index
#profiles = Profile.all
end
Also, the profile table in the database has a column user_id. Plus, I checked my database and all user's have a profile name. On the profile page, I reference #user.profile.(profile attribute) so I know the has_one/belongs_to relationship is working. I can't figure out what to do. Please help.
Thanks.
Do all your Profiles have a user_id value? You might want to consider doing the following to verify that user_id is present for all Profiles:
Profile.pluck :user_id
I suspect a profile object/record does not have a user_id and hence traversing via profile.user.profile_name renders the nil class error.
For whatever reason, your profile.user is nil. Since nil does not have the method .profile_name defined, you get your error.
My guess is there's a profile in #profiles that does not have user_id defined.
Sorry for the vague title, but it's a little much to explain in a sentence.
I've got three models, User, Device, and DeviceMessage. Their relationships are fairly simple:
a User has_many :devices,
a Device belongs_to :user,
a Device has_many :device_messages,
and a DeviceMessage belongs_to :device.
Rails provides ways to start playing with these associations quickly, like the ability to get all device messages that belong to a certain user (from any device).
In order to do this, I defined a method in the User model:
class User < ActiveRecord::Base
...
has_many :devices, :as => : owner #Other entities may "own" a device
def device_feed
DeviceMessage.that_belong_to_user(self)
end
end
And I define the called method in the DeviceMessage model:
class DeviceMessage < ActiveRecord::Base
...
belongs_to :device
def self.that_belong_to_user(user)
device_ids = "SELECT owner_id FROM devices WHERE owner_id = :user_id
AND owner_type = \"User\""
where("device_id IN (#{device_ids})", user_id: user.id)
end
end
I define a user page where they can associate a device to their account (the device has a name as well), and upon adding the device to the account, it will add the name to a list of device names in a pane to the left, while showing the user's device feed much like a twitter feed (yes, I followed Michael Hartl's RoR tutorial). At this point it is important to note that I am using helper functions to keep track of the current user so I can display this information when a user visits the root_path while logged in. When visiting the root_path, the controller for the root_path is defined so that:
if user_signed_in?
#device_feed_items = current_user.device_feed.paginate(page: params[:page])
end
And this all works perfectly!
So... what's the issue? When I create a new user via the signup page, and associate the device via the device-association page, I am redirected to the root_path, the device name is correctly displayed in the left pane (which mean the device is correctly associated with the new user), but the device_feed is not displayed.
I've used the Rails console to verify that the device messages should be showing (User.find(2).devices.first.device_messages.first displays the first message associated with the first device that is newly associated with the 2nd user), so I know that I need to reach down into the database to get a fresh rather than cached copy of the current_user, but I'm confused because it seems like that should be happening every time the user.device_feed method is called because of it's use of where() which is a part of the query API...
Any ideas? Thanks in advance for any and all answers.
-MM
I am just wondering why you have the device_feed function. For your feed display could you not just a loop like this one, this is
class Device < ActiveRecord::Base
scope :in_new_message_order, :joins => :device_messages, :order => "created_at DESC"
end
Added a joined scope
class User < ActiveRecord::Base
...
has_many :devices, :as => : owner #Other entities may "own" a device
scope :in_sort_order, order("message_date DESC")
def device_feed
DeviceMessage.that_belong_to_user(self)
end
end
Above I have added a scope to sort your messages
<% user.devices.in_new_message_order.each do |device| %>
<% device.device_messages_in_sort_order.each do |message| %>
<%= ....render out the message %>
<% end %>
<% end %>
I'm working in Rails and Activerecord and trying to merge some data from related tables together in my view, here are my models:
class Report < ActiveRecord::Base
has_many :votes
end
class Vote < ActiveRecord::Base
belongs_to :reports
end
class User < ActiveRecord::Base
has_many :votes
end
Each vote has a user and a report.
In my view I need the following, hopefully as easily as possible:
a total number of votes for each report from all users
a true/false if the user has voted on the particular report
Right now, my basic understanding of ActiveRecord queries only takes me as far as creating a helper with the report and the current user and than querying for the existence of report
Same goes for counting the total number of votes for all users for a report as follows:
Controller
def index
#this is where I need some help to get the related information into a single
#object
#reports = Report.where('...')
end
View
<% #reports.each do |report| %>
<% if(hasVoted(#current_user.id, report.id)) %>
<!-- display the 'has voted html' -->
<% end %>
<% end %>
Helper
def hasVoted(current_user_id, report_id)
if(Vote.exists?(:user_id => current_user_id, :report_id => report_id))
true
else
false
end
end
Hope that gives you some insight into helping...thanks!
Sure.
Firstly, please consider naming your method has_voted? instead of hasVoted. Secondly, consider moving that method in the user model.
#user.rb
def voted_on?(report_id)
votes.where(:report_id => report_id).exists?
end
Your view will then read
<% if current_user.voted_on?(report) %>
...
<% end %>
The other question you had was to find the number of votes a report has received. This is simple too. You could do this in your view inside the loop where you iterate over #reports
<% vote_count = report.votes.size %>
Please keep in mind that his would result in N queries (where N = number of reports). Since you are new to Rails i'm not going to complicate your Reports query in the controller where you fetch you reports to include the vote count (unless you ask me to). But once you are comfortable with what happening in here, thats where you would optimize.
I am using Ruby on Rails 3 and I am trying to retrieve some data from a just saved child model (associated model) in order to store that data in the parent model.
More precisely (in steps) I would like to do:
Save the child model Account of the parent model User
Retrieve the just created Account ID value and save that value in the User model attribute named users_account_id.
... and more explicitly (in values) I would like to have the following scenario after saving the child model Account:
# Account values
Account.id = 222
Account.name = "Test_name"
...
Account.user_id = 111
# User values
User.id = 111
User.users_account_id = 222
I already implemented the first step, but how can I implement the second step?
In order to retrieve the Account ID, I tryed to use an association callback
class User < ActiveRecord::Base
has_one :account, :before_add => :callback_name
validates_associated :account
accepts_nested_attributes_for :account
def callback_name
self.users_account_id = Account.find_by_id(self.id).id
end
end
but I get this error:
Unknown key(s): before_add
This is way overkill. All you need to do is put the user_id in the form of the account that is getting created as a hidden field.
<% form_for(#account) do |f| %>
<%= f.hidden_field :user_id, :value => current_user.id %>
<% end %>
Of course add your other fields that you want for account and you need a current_user object which you will need anyways with your current logic.
I'm going to side step your question a bit, and ask why you need IDs pointing in both directions? I assume you want your User to be related to an Account, and an Account to have one or more Users. The "Rails Way" to do this would be something like the following:
class User < ActiveRecord::Base
belongs_to :account
end
class Account < ActiveRecord::Base
has_many :users
end
In your database the users table will have account_id and the accounts table will not have a user_id of any kind.
This will still allow you to user the association in both directions:
some_user.account # Returns the correct account object
some_account.users # Returns all users for the account
I hope this helps somewhat!