现在的情况是,任何人都可以创建新的 issue 即使是未登录的人也可以,这个显然有问题,所以需要给网站来添加权限管理机制,大的 web 应用中可能 这方面会很复杂,有用户的身份有很多,网站可以执行的操作也可能有很多。不过这一集里,咱们也就算在 authorization 这个角度来开个头,只是区分 最简单的两种用户身份,一种是已经登录用户,另一种是未登录用户,看看如何给他们赋予不同的操作权限。
登录后才能创建新活动
点击首页的发布新活动按钮,如果用户没有登录,则给出一个 flash 来,需要的代码调整是在 issues_controller.rb 中,把原有的 new 动作改成
def new
if not current_user
flash[:notice] = "没有执行此操作的权限,请先登录"
redirect_to :root
return
else
@issue = Issue.new
end
end
隐藏评论框。 退出登录条件下再来访问一个活动的展示页面就会报错。这是因为在评论框的代码中用到了 current_user 。解决方法是到 issues/show.html.erb 中
+ <% if current_user %>
<%= render partial: 'shared/comment_box', locals: {issue: @issue} %>
+ <% else %>
+ <%= link_to "登录发评论", login_path %>
+ <% end %>
重构 issue
需要用到 @issue.user
所以先要来添加这两个资源的一对多关系。
rails g migration AddUserIdToIssues user_id:integer
bundle exec rake db:migrate
issues_controller.rb 中调整一下
def issue_params
- params.require(:issue).permit(:title, :content)
+ params.require(:issue).permit(:title, :content, :user_id)
end
user.rb 中添加
has_many :issues
issue.rb 中添加
belongs_to :user
现在的问题 issue#new 和 #edit 中目前是复用的一个 partial,但是现在 new 中需要把 user_id 作为 hidden_field 传递过去,所以把 _form.html.erb 中 的内容拷贝到 issues/new.html.erb 中,然后做如下调整
- <%= form_for issue do |f| %>
+ <%= form_for(Issue.new(user_id: current_user.id)) do |f| %>
+ <%= f.hidden_field :user_id %>
原先创建的 issue 肯定是没有 user_id 的,所以都删除了,重新创建。
rails c
Issue.destroy_all
这样新创建的 issue 就可以打开了,但是头像和用户名现在还都是 happypeter,这个也不对,要调整一下
_issue_list.html.erb 中
- <a href="/happypeter">
- <img src=http://gravatar.com/avatar/a92785d8d68f1d1d83b008574f8b5dba.png?s=512&d=retro alt="">
- </a>
+ <%= link_to "#" do %>
+ <%= image_tag i.user.avatar %>
+ <% end %>
- <a href="/happypeter">happypeter</a>
+ <%= link_to i.user.name, '#' %>
issues/show.html.erb 中也是一样的
- <img src="http://gravatar.com/avatar/a92785d8d68f1d1d83b008574f8b5dba.png?s=512&d=retr" alt="" class="image-circle">
+ <%= image_tag @issue.user.avatar, class: "image-circle" %>
- <h5 class="name"><a href="#">happypeter</a></h5>
+ <h5 class="name"><%= link_to @issue.user.name, "#" %></h5>
只有作者本人可以修改 issue
需要把 issues/show.html.erb 中的 edit 和 destroy 按钮对作者外的其他所有人隐藏,所以做如下的代码调整
- <%= link_to 'Destroy', issue_path(@issue), method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-primary" %>
- <%= link_to 'edit', edit_issue_path(@issue), class: "btn btn-primary" %>
+ <% if current_user && current_user == @issue.user %>
+ <%= link_to 'Destroy', issue_path(@issue), method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-primary" %>
+ <%= link_to 'edit', edit_issue_path(@issue), class: "btn btn-primary" %>
+ <% end %>
OK,更多关于权限控制的技巧,可以查看 railscasts.com 的 authorization 标签。