如何为Rails构建含onclick与内联样式的自定义视图助手?
Hey there! Let's fix that helper and turn your messy view code into clean, maintainable logic. Since you're new to custom view helpers, I'll break this down step by step.
First, let's recap what we need: our helper needs to generate the correct HTML for each social media type (print, email, facebook) while accepting the book object as input (since we need its image and name).
Step 1: Fix the Helper Structure
Your initial helper was missing a case statement (to match media types) and proper parameter handling. Let's build it out properly in books_helper.rb:
module BooksHelper def social_share_button(media, book) case media when 'print' content_tag(:div, class: 'jssocials-share jssocials-share-email') do link_to '#', onclick: "PrintImage('#{image_url(book.book_image.to_c)}'); return false;", class: 'jssocials-share-link', style: 'background-color: purple; width: 73px;' do 'Print' + content_tag(:i, '', class: 'jssocials-share-logo') end end when 'email' content_tag(:div, class: 'jssocials-share jssocials-share-email') do mail_to '', 'E-mail', subject: 'Book Subject', body: "I saw this and thought of you! http://url.com/books/#{book.book_name}", class: 'jssocials-share-link' do content_tag(:i, '', class: 'fa fa-at jssocials-share-logo') + content_tag(:span, 'E-mail', class: 'jssocials-share-label') end end when 'facebook' share_url = "http://url.com/books/#{book.book_name}" encoded_share_url = CGI.escape("https://www.url.com/somebooks/books/#{book.book_name}") content_tag(:div, class: 'jssocials-share jssocials-share-facebook fb-share-button', id: 'fbid') do content_tag(:div, data: { href: share_url, layout: 'button', size: 'small', mobile_iframe: 'true' }) do link_to "https://www.facebook.com/sharer/sharer.php?u=#{encoded_share_url}", class: 'fb-xfbml-parse-ignore jssocials-share-link', target: '_blank' do content_tag(:i, '', class: 'fa fa-facebook jssocials-share-logo') + content_tag(:span, 'Share', class: 'jssocials-share-label') end end end end end end
Key Notes About the Helper:
- We use
caseto handle each media type separately, making it easy to add new types later content_taglets us generate HTML tags with Rails-friendly syntax (no messy string concatenation)link_toandmail_toare built-in Rails helpers that handle link generation safely- We pass the
bookobject so we can access itsbook_imageandbook_nameattributes dynamically - We properly encode the Facebook share URL using
CGI.escapeto avoid invalid characters breaking the link
Step 2: Refactor Your View
Now replace those repetitive <li> blocks in your view with calls to our helper. This will make your view much cleaner and easier to read:
<div class="btn-group wkt-btn-group"> <button type="button" class="btn share dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">SHARE <span class="fa fa-angle-down" style="font-size:16px;"></span> </button> <ul class="dropdown-menu wk-social"> <li><%= social_share_button('print', book) %></li> <li><%= social_share_button('email', book) %></li> <li><%= social_share_button('facebook', book) %></li> </ul> </div>
Step 3: Bonus - Make It Even More Flexible
If you ever need to add more social media types, you just add a new when clause to the helper. For example, adding a Twitter button would be as simple as:
when 'twitter' content_tag(:div, class: 'jssocials-share jssocials-share-twitter') do link_to "https://twitter.com/intent/tweet?url=#{CGI.escape("http://url.com/books/#{book.book_name}")}&text=Check out this book!", class: 'jssocials-share-link', target: '_blank' do content_tag(:i, '', class: 'fa fa-twitter jssocials-share-logo') + content_tag(:span, 'Tweet', class: 'jssocials-share-label') end end
Then add a new <li> in your view: <li><%= social_share_button('twitter', book) %></li>
This approach keeps all your share button logic centralized in the helper, so you don't have to duplicate HTML across views (and if you need to update styles or URLs, you only change one place!).
内容的提问来源于stack exchange,提问作者Jake

