Right now I have some functionality working but its really ugly and I know there's a better way to do it.
Here's what I have right now in my User model:
def attending
dayseventsusers=self.days_events_users
daysevents=Array.new
events=Array.new
dayseventsusers.each do |deu|
daysevents<<DaysEvent.find(deu['days_events_id'])
end
daysevents.each do |de|
events<<Event.find(de['event_id'])
end
return events
end
I'm trying to get a list of events for a certain group of dayseventsusers records but I have to move through several relationships to accomplish this. What I'd really like to do is something like self.days_events_users.days_event.event, but I don't know if it can be this simple assuming my relationships are setup correctly.
User model
has_many :days_events_users
DaysEventsUsers model
belongs_to :user
belongs_to :days_event
DaysEvent
has_many :days_events_users
belongs_to :event
The days_events_users object belong to a single days_event, which belongs to a single event. Any suggestions are welcome!
Without having tested this, does the following work:
dayseventusers.collect(&:daysevent).collect(&:event)
Related
I'm not getting a concept (nothing new there) on how to scope a Active Record query. I want to only receive the records where there is a certain condition in a related record. The example I have happens to be polymorphic just in case that is a factor. I'm sure there is somewhere where this is explained but I have not found it for whatever reason.
My Models:
class User < ActiveRecord::Base
belongs_to :owner, polymorphic: true
end
class Member < ActiveRecord::Base
has_one :user, as: :owner
end
I want to basically run a where on the Member class for related records that have a certain owner_id/owner_type.
Lets say we have 5 Members with ids 1-5 and we have one user with the owner_id set to 3 and the owner_type set to 'Member'. I want to only receive back the one Member object with id 3. I'm trying to run this in Pundit and thus why I'm not just going at it form the User side.
Thanks for any help as always!!!
Based on your comment that you said was close I'd say you should be able to do:
Member.joins(:user).where('users.id = ?', current_user.id)
However based on how I'm reading your question I would say you want to do:
Member.joins(:user).where('users.owner_id = ?', current_user.id)
Assuming current_user.id is 3.
There may be a cleaner way to do this, but that's the syntax I usually use. If these aren't right, try being a little more clear in your question and we can go from there! :)
In my Rails app Users can have many People which in turn can (but don't have to) belong to Organisations.
In short, this:
Users --< People >-- Organisations
Now, it would be nice to be able to create new organisations from within a people view somehow. It tried this:
class Person < ActiveRecord::Base
attr_accessible :name, :organisation_attributes
belongs_to :user
belongs_to :organisation
accepts_nested_attributes_for :organisation
end
But it's not working because Organisation is not a child of Person.
Is there another way to realise this?
Thanks for any help.
I can see that Person is actually a child of Organisation and its possible to make nested form for parent model also. And you are already using accepts_nested_attributes_for.
Im assuming that you want to show a Organisation form for a already saved person. Then
In your PeopleController#show method build the organisation
#person.build_organisation
And in people/show.html.erb
form_for(#person) do |f|
f.fields_for(:organisation) do |fo|
# show the fields of organisation here.
end
end
It should work.
Update:
I tried something similar and it worked :) Ive made a gist including the snippets.
Please follow the link https://gist.github.com/3841507 to see it working.
User has_one UserProfile which has_one Community.
Given a community_id, I want a list of emails from the Users table.
How do I get a list of all User.email where community_id = 5?
The best I can find (which does work) is:
User.select(:email).joins(:user_profile).merge(UserProfile.for_community(5))
But it seems brute-force... is there not a way to do something simpler along the lines of this below?
User.user_profile.community(5)
I don't think you know what your code does...
If the UserProfile has_one community, then the communities table must have a column titled user_id. That means there is only one User associated with any given community id.
To solve your question, as stated, you could delegate the user method to the user_profile.
class Community < ActiveRecord::Base
belongs_to :user_profile
delegate :user, to: :user_profile
end
Then you could do Community.find(community_id).user.email
Hope that helps.
I think going from the other direction might accomplish what you're looking for:
Community.find("5").user_profile.user.emails
In Rails, I want to override the behavior of an association. For example, by default, if Person has_many :hats, calling some_person.hats would do a simple join using person.id and hat.person_id.
I want to modify that query to include some other criteria. For example, maybe a person's collection of hats should be just the hats that are appropriate to their country.
It seems that I could do something like this:
class Person < ActiveRecord::Base
has_many :hats, :through => :country do
# John lives in Canada, so he gets a baseball cap and a hockey helmet
self.country.hats
end
end
Can I control what an association returns like this? If not, would a scope be the best solution?
I know this is a silly example, but explaining the domain logic that I need this for would be way too boring for everyone here. :)
Scopes are probably your best option because they're chainable and reusable outside your association. Otherwise, you could use association extensions. Check out this thread for more info. Association Extensions
It is easy to associate a model to another using has_many/belongs_to methods. Let's suppose the following models:
class Movie < ActiveRecord::Base
has_many :actors
end
So, I can find the actors from a given movie instance. But now, given an actor instance obtained through the actors association, I'd like to find the movie instance related in the association. Some method like 'associated_instance' or 'back_association' that would make the following statement return true:
movie_instance.actors[0].**associated_instance** == movie_instance
Is there any built in way to do that?
Thanks
Assuming you have your relationships correctly defined, I'm guessing your encountering the situation where you want to effectively traverse an association but then traverse backwards eg.
movie.actors.movie
With a HABTM relationship rails doesn't build the .movie method for you on the actors collection, but what you can do is extend the association to include such a method:
class Movie < ActiveRecord::Base
has_and_belongs_to_many :actors do
def movie
proxy_owner
end
end
end
There is an excellent guide on association extensions by Mike Gunderloy on the Rails Guides site: http://guides.rubyonrails.org/association_basics.html#association-extensions
Hope I've stabbed at this question in the right direction :)
Yes you can do what you want using
movie_instance.actors[0].movie
The question still remains why you would want to do this as you already have it
...given an actor instance obtained
through the actors association...
If you're using the actors association, you already have the movie object. What is the problem that you're trying to solve here?
My suspicion is that if we finally get to the bottom of what you're trying to accomplish, the answer is going to be "read the docs on 'has_and_belongs_to_many' and/or 'has_many :through'."
Edit:
I just now noticed your clarification below (although movies and plots could be considered many-to-many as well, since they get recycled endlessly).
Assuming that you really are trying to use a many-to-one relationship, is the root of your problem that you forgot the following?
class Plot < ActiveRecord::Base
belongs_to :movie
end