如何遍历Ruby代码中的所有可用数组

时间:2012-02-20 11:32:43

标签: ruby-on-rails ruby arrays loops

我正在尝试创建一个仪表板,其中用户(用户模型)已经点击“参与”(这是一个可标记的)事件(事件模型)连接到集合(集合模型)将能够看到他们的目标是什么。

我的问题是,如何遍历所有可能的数组,以便我获取用户点击“参加”的事件的所有相关ID。

例如,在我的主页中,我想显示用户正在参加的所有可能事件:

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

我已将@ event1数组设置为0以访问'参加'的第一个标志,然后获取flaggable_id,以便我有id来调用Collection。

我的问题是,如果我有几个事件,我如何循环到所有数组以确保我可以取出所有集合?

对于第一个点击“参加”2个事件的用户,这是数据:

IRB中的

,参加2场活动的User.first

  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">] 

您可以看到用户已为2个事件标记了“参与”,这些事件存储在数组中。因此,如果我有2个事件,我理想地想要循环,以便我有2个数组。

我觉得实现这个很困惑......任何帮助都会非常感激!

user.rb部分代码

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部分代码

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部分代码

class Event < ActiveRecord::Base
attr_accessible :date, :time, :description
belongs_to :collections
make_flaggable :attending
...
end

3 个答案:

答案 0 :(得分:0)

您的帖子并非100%明确,但听起来您需要named scope用于设置参加标志的事件和has_many :through关联以让用户拥有活动。将这两个位组合在一起,您可以执行以下操作:

User.first.events.attending

并且AREL将负责为您提供快速查询。

答案 1 :(得分:0)

可以标记为宝石还是你把它写成多态类?

这条线很讨厌(对不起):

@events = @user.flaggings.with_flag(:attending)

@events变量不是持有事件 - 它持有一系列标记。作为命名惯例,这显然很糟糕。

此外,如果您为可标记的多态关系设置(或使用gem),则此行可能是多余的:

@event1 = Event.find(@events[0].flaggable_id)
#This could be rewritten as:
@event1 = @events.first.flaggable

甚至更好,将前两行合并为:

#@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对命名范围和hmt关联提出了非常好的观点。这可能是前进的方向。你可以这样做:

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...

那将使你能够做到:

@events = @user.events_attending.include(:collection)

警告 - 这些代码都没有经过测试 - 它完全脱离了我的头脑,但至少应该指向正确的方向

答案 2 :(得分:0)

好吧,我设法解决了自己的问题,虽然方式很脏......

<强> 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 %>

我很确定代码是非常糟糕的,而且我使用了几个'快捷方式'问题,这些问题将在未来引起我的反击......但是mvp是一个mvp。谢谢你的帮助! :)