Rails - 如果在每次迭代时重复自己

时间:2017-07-20 19:21:57

标签: ruby-on-rails

我有一个观点,我想迭代一个名为provider的参数,并根据它输出一个危险按钮或成功按钮。

  <!-- Modal content-->
  <div class="modal-content">
    <div class="modal-header">
      <button type="button" class="close" data-dismiss="modal">&times;</button>
      <h4 class="modal-title">Modal Header</h4>
    </div>
    <div class="modal-body">
      <% @user.authentications.each do |i| %>
        <% if i.provider == 'twitter' %>
          You have Twitter. Do you want to delete it?
          <%= button_to 'Delete Auth', deauth_url(i.id), :class => "btn btn-danger" %>
        <% else %>
          <span>You don't have Twitter. Want to add it?</span>
          <%= link_to "Sync with Twitter!", user_twitter_omniauth_authorize_url, :class =>"btn btn-success" %>
        <% end %>
        <% if i.provider == 'facebook' %>
          You have Facebook. Do you want to delete it?
          <%= button_to 'Delete Auth', deauth_url(i.id), :class => "btn btn-danger" %>
        <% else %>
          <span>You don't have Facebook. Want to add it?</span>
          <%= link_to "Sync with Facebook!", user_twitter_omniauth_authorize_url, :class =>"btn btn-success" %>
        <% end %>
        <% if i.provider == 'steam' %>
          You have Steam. Do you want to delete it?
          <%= button_to 'Delete Auth', deauth_url(i.id), :class => "btn btn-danger" %>
        <% else %>
          <span>You don't have Steam. Want to add it?</span>
          <%= link_to "Sync with Steam!", user_twitter_omniauth_authorize_url, :class =>"btn btn-success" %>
        <% end %>
      </p>
    </div>
    <% end %>
    <div class="modal-footer">
      <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
    </div>
  </div>

直接问题很明显 - 根据身份验证,它会触发两种情况。我正在通过将其修改为elsif来修复它,但实际上这看起来非常多余。我正在试图弄清楚如何迭代它,并输出按钮'per',但问题是如果有人没有Facebook,我不知道如何输出“与Facebook同步?”按钮。我的想法目前是else的硬编码,但我会为每个提供商做到这一点。

欢迎任何有关如何更好地处理此事的意见。

信息过多: provider是一个普通的字符串 - 我可以修改模型,因此它知道oauth = facebook, twitter, and steam是否有助于解决它,但我不确定如何解决

2 个答案:

答案 0 :(得分:1)

因此,我将借用Gerry关于使用帮助程序的想法,这可能是干燥代码的更好的整体实践。

*your_controller.rb*

def action_on_your_controller
  @user = User.find(params[:id]) # I guess?
end

*your_helper.rb*

def build_authentication_hash(user_authentications)
  # build the original hash, where all authentications are non-existing, in this case false, you could extend it to accommodate any number of providers
  authentications = {
    facebook: false,
    twitter: false,
    steam: false
  }
  user_authentications.each do |auth|
    # iterate through all the user authentications, auth is the authentication record/object, so basically what happens is, each auth will substitute its own key on the authentications hash from false to itself, but if the authentication doesn't exist, it's not iterated through and remains false, allowing us to use that on the template logic
    authentications[auth.provider.to_sym] = auth
  end
  return authentications #here return the full hash, which will allow us to iterate
end

# here you call the helper method, passing it the collection of authentications of the user. 
# This helper method will return the authentications hash, which you can iterate on,
# where `p` is the `key` (facebook, steam, etc) and `v` will be the `authentication` record itself, it there was one, or `false`.
# Since we built the hash that way it means you have access to the provider name as `p`,
# but also to all fields of the provider record, by using `v.attribute`, such as `v.id`, etc.
# Since all providers are present on the hash you can safely use the `if` branching to decide what to show relative to that provider.
# Because in case the user doesn't have an authentication for twitter, the hash will have kept the value of `false`
# So `if v` will evaluate to `false`. 
# you usually write |k,v| and not |p,v|, being k(ey), v(alue), referring to the hash structure. I wrote p because of p(rovider)

<%- build_authentication_hash(@user.authentications).each do |p,v| %>
  <div id="#{p}-section">
  <%- if v %>
    <%= "You have #{p.capitalize}. Do you want to delete it?" %>
    <%= button_to 'Delete Auth', deauth_url(v.id), :class => "btn btn-danger" %>
  <%- else %>
    <span><%= "You don't have #{p.capitalize}. Want to add it?" %></span>
    <%= link_to "Sync with #{p.capitalize}!", user_twitter_omniauth_authorize_url, :class =>"btn btn-success" %>
  <%- end %>
  </div>
<%- end %>

答案 1 :(得分:1)

我将使用辅助方法来清理视图,如下所示:

users_helper.rb:

def check_provider(provider, auths)
  auth = auths.find { |auth| auth.provider == provider }

  if auth.present?
    capture do
      concat "You have #{provider.capitalize}. Do you want to delete it?"
      concat button_to("Delete Auth", "#{auth.id}", class: "btn btn-danger")
    end
  else
    capture do
      concat content_tag(:span, "You don't have #{provider.capitalize}. Want to add it?")
      concat link_to("Sync with #{provider.capitalize}!", "twitter", class: "btn btn-success")
    end
  end
end

view.html.erb:

<% %w(twitter facebook steam).each do |provider| %>
  <%= check_provider(provider, @auths)%>
<% end %>