I am trying to create a dashboard where users (User model) who has clicked "attending" (which is a flaggable) to an event (Event model) which is connected to a Collection (Collection model) will be able to see what are the Events they are going for.
My question however, is simply how to loop through all possible arrays in order for me to get all the associated IDs for the Events that the User has clicked "attending".
So for example, in my home page I want to display all possible events that the user is attending:
user_statistics.html.erb
<div class="span3 events">
<h3>Events</h3>
<% if @events.empty? %>
<p>You are currently not attending any events.</p>
<% else %>
<p>You are attending: <b><%= pluralize(@events.count, "event") %></b></p>
<p>Event 1: <%= @event1_name %> on Date: <%= @event1.date %> at Time:<%= @event1.time %></p>
<% end %>
</div>
pages_controller.rb
def home
@title = "Title"
@user = current_user
if current_user
@post = Post.new
@feed_items = current_user.feed
@user_following = @user.following
@user_followers = @user.followers
@events = @user.flaggings.with_flag(:attending)
@event1 = Event.find(@events[0].flaggable_id)
@event1_name = Collection.find(@event1.collection_id).name
end
end
I have set the @event1 array to 0 to access the first flag for 'attending', and then get the flaggable_id so I have the id to call up the Collection.
My issue is that if I have several events, how do I go about looping through to all the arrays to ensure I can pull out all the Collections?
For the first User who has clicked "attending" for 2 events, this is the data:
in IRB, for User.first who is attending 2 events
User Load (0.3ms) SELECT "users".* FROM "users" LIMIT 1
MakeFlaggable::Flagging Load (0.4ms) SELECT "flaggings".* FROM "flaggings" WHERE
"flaggings"."flagger_id" = 1 AND "flaggings"."flagger_type" = 'User' AND
"flaggings"."flag" = 'attending'
[#<MakeFlaggable::Flagging id: 16, flaggable_type: "Event", flaggable_id: 3,
flagger_type: "User", flagger_id: 1, flag: "attending", created_at: "2012-02-20 09:26:36",
updated_at: "2012-02-20 09:26:36">, #<MakeFlaggable::Flagging id: 18, flaggable_type:
"Event", flaggable_id: 4, flagger_type: "User", flagger_id: 1, flag: "attending",
created_at: "2012-02-20 10:38:00", updated_at: "2012-02-20 10:38:00">]
You can see that the user has flagged 'attending' for 2 events, which are stored in arrays. Hence if I have 2 events, I would ideally want to loop through such that I have 2 arrays.
I find it quite confusing to implement this... any help would be much appreciated!
user.rb partial code
Class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation, :user_bio,
:shop, :cover_photo, :avatar, :remote_image_url
has_secure_password
mount_uploader :cover_photo, ImageUploader
mount_uploader :avatar, ImageUploader
make_flagger
scope :shop, where(shop: true)
has_many :posts, dependent: :destroy
has_many :relationships, dependent: :destroy,
foreign_key: "follower_id"
has_many :reverse_relationships, dependent: :destroy,
foreign_key: "followed_id",
class_name: "Relationship"
has_many :following, through: :relationships, source: :followed
has_many :followers, through: :reverse_relationships, source: :follower
has_many :collections, dependent: :destroy
...
end
collections.rb partial code
class Collection < ActiveRecord::Base
attr_accessible :name, :description, :image, :remote_image_url
belongs_to :user
has_many :products, dependent: :destroy
has_many :events, dependent: :destroy
mount_uploader :image, ImageUploader
make_flaggable :like
...
end
events.rb partial code
class Event < ActiveRecord::Base
attr_accessible :date, :time, :description
belongs_to :collections
make_flaggable :attending
...
end
It's not 100% clear from your post, but it sounds like you need a named scope for Events where the attending flag is set and a has_many :through association to let the User have Events. With those two bits together, you could do something like:
User.first.events.attending
and AREL will take care of wiring that all up into a nice fast query for you.
Is flaggable a gem or have you written it as a polymorphic class?
This line is kind of nasty (sorry):
@events = @user.flaggings.with_flag(:attending)
The @events variable isn't holding events - it's holding a collection of flaggings. As a naming convention, this is obviously bad.
Also, this line is probably redundant if you've set up (or used a gem) for the flaggable polymorphic relationship:
@event1 = Event.find(@events[0].flaggable_id)
#This could be rewritten as:
@event1 = @events.first.flaggable
Or even nicer, combine the two previous lines into:
#@events = @user.flaggings.with_flag(:attending)
#@event1 = Event.find(@events[0].flaggable_id)
#becomes:
flaggings = @user.flaggings.with_flag(:attending)
@events = flaggings.map(&:flaggable)
@jxpx777 makes a very good point about named scope and hmt associations. This is probably the way forward. You could do something like this:
Class User < AR...
has_many :attendances, :class => 'Flagging', :conditions => {:flag => 'attending'} #You might need to add :type => "Event" if you use flaggings elsewhere...
has_many :events_attending, :class => 'Event', :through => :attendances, :source => :flaggable_id #You'll probably have to change a lot of these variable names - I can't see the rest of your source code...
That will then give you ability to just do:
@events = @user.events_attending.include(:collection)
Caveat - none of this code is tested - it's all off the top of my head, but it should point you in the right direction at least
Okay, I managed to solve my own problem albeit in a very dirty manner...
pages_controller.rb
def home
@title = "Simplifying and socializing online shopping - Ruuva"
@user = current_user
if current_user
@post = Post.new
@feed_items = current_user.feed
@user_following = @user.following
@user_followers = @user.followers
@events_attending = @user.flaggings.with_flag(:attending)
end
end
_user_statistics.html.erb partial
<h3>Events</h3>
<% if @events_attending.empty? %>
<p>You are currently not attending any events.</p>
<% else %>
<p>You are attending these events:</p>
<ol>
<% @events_attending.each do |e| %>
<% unless Event.find_by_id(e.flaggable_id).nil? %>
<li>
Collection: <%= link_to Collection.find(Event.find(e.flaggable_id).collection_id).name, event_path(e.flaggable_id) %>
<br>happening on: <%= Event.find(e.flaggable_id).date %> at <%= Event.find(e.flaggable_id).time %>
</li>
<% end %>
<% end %>
</ol>
<% end %>
I'm pretty sure the code is very bad, and I DO used several 'shortcuts' issues that will bite me back in the future... but an mvp is an mvp. Thanks guys for the help, though! :)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.