我知道我在这篇文章中要求很多,但在阅读了4本关于Ruby / Rails的书后,我对我没有得到“aha”时刻感到沮丧。如果有人可以帮忙,我会过来给你做早餐(一周)。
我来自PHP / MySQL的世界,我发现很难掌握Rails中的某些东西。我在Michael Hartl上读到的最后一本书提出了一些练习,可以添加到他在本书中构建的应用程序中。它与协会有关。所以我想知道是否有人可以给我一些提示,因为我真的被卡住了。
他构建的应用程序几乎是Twitter克隆。有人发布了Microposts。他们的主页看起来像这样http://ruby.railstutorial.org/chapters/following-users#fig:home_page_with_feed用户自己的Microposts在“feed”的右侧发布。与Feed中用户的Microposts一起,也是当前用户所遵循的用户的Microposts。您可以关注和取消关注任何您想要的用户。
练习建议添加@replies。 @reply是以@username开头的Micropost(例如'@mikeglaz你好吗')。然后,此Micropost将显示在您的Feed和用户名的Feed中(不一定是您关注的人)。作者建议如下:'这可能涉及在微博表中添加一个in_reply_to列,并在Micropost模型中添加一个额外的include_replies范围。但关于跟随其他用户的关联非常复杂,这就是让我陷入困境的原因。我会发布一些代码:
用户
class User < ActiveRecord::Base
attr_accessible :email, :name, :password, :password_confirmation
has_secure_password
has_many :microposts, dependent: :destroy
has_many :relationships, foreign_key: "follower_id", dependent: :destroy
has_many :followed_users, through: :relationships, source: :followed
has_many :reverse_relationships, foreign_key: "followed_id",
class_name: "Relationship",
dependent: :destroy
has_many :followers, through: :reverse_relationships, source: :follower
def feed
Micropost.from_users_followed_by(self)
end
def follow!(other_user)
relationships.create!(followed_id: other_user.id)
end
def unfollow!(other_user)
relationships.find_by_followed_id(other_user.id).destroy
end
end
end
关系
class Relationship < ActiveRecord::Base
attr_accessible :followed_id
belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "User"
end
微柱
class Micropost < ActiveRecord::Base
attr_accessible :content
belongs_to :user
def self.from_users_followed_by(user)
followed_user_ids = user.followed_user_ids
where("user_id IN (?) OR user_id = ?", followed_user_ids, user)
end
end
答案 0 :(得分:0)
如果您愿意,可以查看我在14天前在
添加的解决方案https://github.com/htw-rails/TutorialSampleApp32/
答案 1 :(得分:0)
请注意,我通过使用用户名来查找人员....我特意添加了允许@reply工作的代码。你应该已经完成了Michael Hartl的rails教程
<强> DATABASE 强>
class CreateRecipients < ActiveRecord::Migration
def change
create_table :recipients do |t|
t.string :user_id
t.string :micropost_id
t.timestamps
end
end
def self.down
drop_table :recipients
end
end
<强>模型强>
class Recipient < ActiveRecord::Base
attr_accessible :micropost_id, :user_id
belongs_to :user
belongs_to :micropost
end
class Micropost < ActiveRecord::Base
attr_accessible :content, :recipients
belongs_to :user
USERNAME_REGEX = /@\w+/i
has_many :recipients, dependent: :destroy
has_many :replied_users, :through => :recipients, :source => "user"
scope :from_users_followed_by, lambda { |user| followed_by(user) }
after_save :save_recipients
def self.from_users_followed_by(user)
followed_user_ids = "SELECT followed_id FROM relationships
WHERE follower_id = :user_id"
where("user_id IN (#{followed_user_ids}) OR user_id = :user_id",
user_id: user.id)
end
private
def self.followed_by(user)
followed_ids = %(SELECT followed_id FROM relationships
WHERE follower_id = :user_id)
micropost_ids = %(SELECT micropost_id FROM recipients
WHERE user_id = :user_id)
where("id IN (#{micropost_ids}) OR user_id IN (#{followed_ids}) OR user_id",
{:user_id => user})
end
def save_recipients
return unless reply?
people_replied.each do |user|
Recipient.create!(:micropost_id => self.id, :user_id => user.id)
end
end
def reply?
self.content.match( USERNAME_REGEX )
end
def people_replied
users = []
self.content.clone.gsub!( USERNAME_REGEX ).each do |username|
user = User.find_by_username(username[1..-1])
users << user if user
end
users.uniq
end
end
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation,
:username
has_secure_password
before_save { |user| user.email = email.downcase }
before_save :create_remember_token
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
VALID_UNAME_REGEX = /^[a-z](\w*[a-z0-9])*$/i
has_many :micropost, dependent: :destroy
has_many :relationships, foreign_key: "follower_id", dependent: :destroy
has_many :followed_users, through: :relationships, source: :followed
has_many :reverse_relationships, foreign_key: "followed_id",
class_name: "Relationship",
dependent: :destroy
has_many :followers, through: :reverse_relationships, source: :follower
has_many :replies, :class_name => 'Recipient', :dependent => :destroy
has_many :received_replies, :through => :replies, :source => 'micropost'
def to_param
self.username
end
end
答案 2 :(得分:0)
我的解决方案不涉及任何has_many:关联或范围。它可能更粗糙但似乎有效。
这就是我所做的:
user_name
in_reply_to
添加到Micropost in_reply_to
in_reply_to
与用户ID匹配的帖子答案 3 :(得分:0)
我认为迈克尔·哈特尔暗示要在微博中添加in_reply_to列&#34;过度复杂化了 - 所有你正在做的就是扫描微博内容。看看我的解决方案:
用于在Feed中包含@content的User_Controller方法
#first of all, if you ever want to paginate an array, you need to include
#'will_paginate/array', otherwise you'll experience problems.
require 'will_paginate/array'
def show
current_page = params[:page]
per_page = params[:per_page]
#creates an activity feed
@user = User.find(params[:id])
@ears_burning = Array.new #<<-- this is my @replies array
Micropost.all.each do |m|
#this looks for a username drop in the post, for example "greenranger"
if(m.content.include?(@user.username))
#the micropost with the username(s) is added to the array
@ears_burning.push(m)
end
end
#my example app, users can also post blogs called "articles", hence
#the additional arrays, but it serves as a good example as to how I
#tackled the problem. As you can see, I merge them all into one array
@array = @user.microposts + @user.articles + @ears_burning
#This is the user profile activity array, sorted and paginated by
#created_at time. Simple!
@activity = @array.sort_by(&:created_at).reverse!
@pagination = @activity.paginate(page: params[:show], :per_page => 5)
# anything else that happens in show
end
我看起来有些不整洁,但它完成了工作。您会注意到这只会查找用户名,而不是@,所以这只会在微博中输入elses用户名。我保持这样,因为像twitter这样的社交网站会自动包含用户的个人资料,无论是否有&#39; @&#39;无论如何都要在名称前面签名,但是这可以通过使用我在下面的视图代码中使用的正则表达式稍微改变。
这样做的一个缺点是,如果用户有数以千计的链接微博,那么你可能会注意到性能问题 - 但是有很多方法可以解决这个问题,就像数据库相关的性能问题一样。
添加一个好的&#34; twitter&#34;旋转东西,我在主页上的微博提要中添加了一个标记用户名的链接。同样,有很多方法可以做到这一点,但我认为最简单和最有效的方法是让_micropost部分逐字逐句地构建每个微博,扫描每个微博的一个&#34; @ &#34;标签。微博有140个字符的限制,所以它永远不会是一个巨大的工作。此代码将显示在显示微博的任何地方:
<!-- micropost main content -->
<span class = "content">
<% words = mp.content.split(" ") %>
<% words.each do |e| %>
<!-- this is where the magic happens, re-builds micropost -->
<% if e.include?("@") %>
<!-- adds a link to the user profile if '@' is detected -->
<%= link_to e, User.find_by_username(e[/@.*/].split('@')[+1][/[^ ]+/]
.delete(",")) %> <!-- that regex I was on about -->
<% else %>
<!-- posts the word in sequence if not a tag -->
<%= e %>
<% end %>
<!-- end of magic -->
<% end %>
</span>
这样做的缺点是它确实为Rails应用程序的视图部分带来了一些逻辑 - 但在某些情况下它是不可避免的。希望这有帮助!