Reputation: 847
I have a view that I want to iterate through a parameter called provider
and output a Danger Button, or Success Button based on it.
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</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>
The immediate issue is obvious - It will trigger both cases, per authentication. I'm working on fixing it by modifying it into elsif
but really this seems EXTREMELY redundant. I'm trying to figure out how to iterate through it, and output the button 'per', but the issue is if someone DOESN'T have Facebook, I have no idea how to output the "Sync with Facebook?" button. My idea currently would be the hardcode it into the else
but I'd do that for every provider.
Welcome any input on how I can handle this better.
Excess info:
provider
is a plain string - I can modify the model so it knows that oauth = facebook, twitter, and steam
if that helps solve it but I'm unsure how to resolve
Upvotes: 0
Views: 67
Reputation: 2290
So, I'll borrow Gerry's idea of using a helper, which is probably better overall practice on DRYing the code.
*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 %>
Upvotes: 1
Reputation: 10497
I will use a helper method to clean up the view, like this:
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 %>
Upvotes: 1