Use deface to change bad code in Spree store - spree

I am working in Spree, and I am trying to use Deface to change this
<% if order.has_step?("delivery") %>
<div class="columns alpha four" data-hook="order-ship-address">
<h6><%= Spree.t(:shipping_address) %> <%= link_to "(#{Spree.t(:edit)})", checkout_state_path(:address) unless #order.completed? %></h6>
<%= render :partial => 'spree/shared/address', :locals => { :address => order.ship_address } %>
</div>
<% end %>
<% if #order.has_step?("delivery") %>
<div class="columns alpha four">
<h6><%= Spree.t(:shipments) %> <%= link_to "(#{Spree.t(:edit)})", checkout_state_path(:delivery) unless #order.completed? %></h6>
<div class="delivery">
<% order.shipments.each do |shipment| %>
<div>
<i class='fa fa-truck'></i>
<%= Spree.t(:shipment_details, :stock_location => shipment.stock_location.name, :shipping_method => shipment.selected_shipping_rate.name) %>
</div>
<% end %>
</div>
<%= render(:partial => 'spree/shared/shipment_tracking', :locals => {:order => #order}) if #order.shipped? %>
</div>
<% end %>
..into this.
<div class="columns alpha four" data-hook="order-ship-address">
<h6><%= Spree.t(:shipping_address) %> <%= link_to "(#{Spree.t(:edit)})", checkout_state_path(:address) unless #order.completed? %></h6>
<%= render :partial => 'spree/shared/address', :locals => { :address => order.ship_address } %>
</div>
I've already submitted a pull request about the redundant if statement and adding a data-hook to the second if #order.has_step?("delivery"), but in the meantime I need to write a deface override that will change the page to how I need it to look. I might be able to remove the first if #order.has_step?("delivery") since I think Deface will target the first instance of what I'm talking about on the page if I write
:remove => "erb[silent]:contains('if order.has_step?(\"delivery\"')")
although to be honest the documentation is not very good on that point. Anyway, how can I remove the entirety of the second if statement? There's no data-hook to target it, and using
:remove_content => "erb[silent]:contains('if order.has_step?(\"delivery\"')")
just removes the content of the first if statement. I can't target the first div in the second if statement since there's already a div class="columns alpha four" in the first if statement. I don't want to leave an empty div on the page, so what can I do?

The two if statements in the referenced code do not refer to the same variable. The first if refers to order, and the second to #order.
When using deface to remove existing sections of erb, the string passed in to contains must exactly match the code you want to move in order for the override to properly locate it. Since the second if statement uses #order, and your matcher doesn't include the # symbol, it won't remove that particular if statement.
Based on the rspec tests in the deface repo, it doesn't appear that you can currently use multiple matching strings with one override in the remove action. Instead, you'll have to use a second override to mach the second if statement and remove it.

The pull request I posted to Spree made this whole issue moot (which you can find here if you're interested: https://github.com/spree/spree/pull/5692 ). Also, it turns out that #order and order function in exactly the same way in that document, and all references to #order are in the process of getting removed from Spree anyway.

Related

Globalize accessors on subset of available locales

By design, some classes will deal with only a subset of available languages.
the globalize-accessors gem is quite useful, however, the rendering requires that the following be defined
Class.globalize_attribute_names
so while available_locales = [:en, :ru, :fr, :de], the goal is to work with a smaller array [:en, :ru]
The documentation states Calling globalize_accessors with no options will therefore generate accessor methods for all translated fields and available languages. But the purported way to invoke is in the model
globalize_accessors :locales => [:en, :fr], :attributes => [:title]
How can the globalize_accessorsmethod refer to an array, something generated by the likes of
#post.owner.ownerlocales.pluck('locale')
(although the array values are quoted...)
A working solution found but that does not address the above question, is based on the fact that globalize-accessors
gives you access to methods: title_pl, title_en, title_pl=, title_en=
Thus, a controller method that generates a whitelist
#locales = []
#post.owner.ownerlocales.each do |ol|
locale = ol.locale
#locales.push(locale)
end
... then process in the view filtering out the globalize_processors from whitelist
<% Post.globalize_attribute_names.each do |lang| %>
<% my_string = lang.to_s %>
<% #locales.each do |locale| %>
<% checkstring = "_" + locale %>
<% if my_string.include? checkstring %>
<div class="row">
<%= t(lang[0..-4]) %> - <%= lang[-2, 2] %> <br />
<%= f.text_area lang, rows: "3" %>
</div>
<% end %>
<% end %>
<% end %>
Not efficient, functional.

using a regex inside an HTML helper

I would like to add an HTML element attribute depending whether I'm passing an URL or not to an HTML helper.
I tried this in my template.html.eex:
<%= if Regex.match?(~r/www/, "#auxButton_linkURL") do %> target="_blank" <% else %><% end %>
I know that I'm close but this is not working (although no error, it simply just doesn't add the target attribute).
How to use it correctly?
Do you mean to use the #auxButton_linkURL value from conn.assigns? If so you should use:
<%= if Regex.match?(~r/www/, #auxButton_linkURL) do %> target="_blank" <% else %><% end %>
Notice there are no quotes around #auxButton_linkURL. As an aside, variables by convention should use snake_case (#aux_button_link_url)

Rails .each enumerator with a special case for the first line

I'm trying to put an enumerator to run over the top of a (refills/bourbon) front end framework. The element is a tab accordian which has repeatable elements but a special is-active class tag which flags to javascript which one should be expanded and the focus of a users attention.
I want to design an enumerator to create tabs and fill content based on how many records there are in ActiveRecord so I'm using an enumerator - but is there a smart way I can create a clean exception for the first <a> it outputs so it includes the is-active tag?
Currently my murky hack is below:
<div class="vertical-tabs-container">
<div class="vertical-tabs">
<% tab_num = 0 %>
<% #user.items.each do |item| %>
<% tab_num += 1 %>
<% if tab_num = 1 %>
<%= content_tag( :a, #user.item, :class=>"js-vertical-tab vertical-tab is-active, :rel="tab#{tab_num}", :href="javascript:void(0) %>
<% else %>
<%= content_tag( :a, #user.item, :class=>"js-vertical-tab vertical-tab, :rel="tab#{tab_num}", :href="javascript:void(0) %>
<% end %>
</div>
... content goes here...
</div>
There seems something deeply un-rails about that tab_num bit... and I sense a disturbance in the MVC force for putting this in my view... Plus this way I'd have to have another enumerator for the body element of the vertical-tabs-container...
Anyone got a better idea of how to do this neatly?
Firstly, this looks like it belongs in a helper or a presenter/decorator.
The code itself could be simplified. Helper method:
In your view:
<div class="vertical-tabs-container">
<div class="vertical-tabs">
<%= user_tabs(#user) %>
</div>
... content goes here...
</div>
Then in your helper:
def user_tabs(user)
output = ""
user.items.each_with_index do |item,i|
output << content_tag(:a, item, :class=>"js-vertical-tab vertical-tab #{i == 0 ? '' : 'is-active'", :rel="tab#{i}", :href="javascript:void(0)
end
output
end
However if you're going to start adding content and tabs seperately, take a look at draper and define methods for tab and body on the item element.

Rails 4 Index.html.erb loop

So I have the following index for my mailboxer conversations:
conversations/index.html.erb
<p><% #conversations.each do |conversation| %>
<% conversation.participants.each do |participant| %>
<% if participant != current_user %>
From: <%= participant.name %> <br />
<% end %>
<% end %>
Subject: <%= link_to conversation.subject %> <br />
Date: <%= conversation.updated_at.strftime("%a, %m/%e/%Y %I:%M %p") %> <br />
<%= link_to "Move to Trash", {:controller => "conversations", :action => "trash", :id => conversation.id}, :title=> "Move to Trash", :method=>'post' %> <br/> </p>
<% end %>
I came around to this because first it was saying there was no local method for "participant" and then it was saying there was no local method for "conversation." So I just made an each.do loop for both of them.
This works... It lists the sender and subject and the option to move each message to a trash folder... but it starts looping about 5 times per second to infinity. (I'm assuming this is hell on the server.)
THEN I noticed that this also happens for the users index.html and edit.html
Figured it out. I'll try to explain the problem and the solution as in-depth as possible.
Load the index.html.erb of a short page (user edit, index... whatever.)
tail the production or development.log file (or just look at the webrick screen
Notice that it's looping over and over and your cpu is heating up.
Turns out it was some crazy endless_scroll.js that never did anything for anyone... that all-of-a-sudden decided to activate and loop any page it deemed was too short.
Now the crazy thing (and mind you, I'm typing to myself at this point) is that, if you just threw in some random paragraphs... it would stop. Delete them? It would start looping again. (I guess according to the scroll limit.)
So I just deleted the endless_scroll.js and did a rake assets:clean and a rake assests:precompile.
Now everything is back to normal.

Showing Spree taxonomy tree on product page

I'm running Spree 2.2. I'm trying to get the standard taxonomy/filter list to appear on each individual product page in Spree, but I cannot find where it decides that there's sidebar content to be displayed. If anyone can shed any light on where/how that's decided I'd be most grateful.
On the front-end part of spree, more specific, on the index view of the products controller, route spree_frontend/app/views/spree/products/index.html.erb at the beginning of the file, it get's decided whether there will be displayed the taxons or not:
<% content_for :sidebar do %>
<div data-hook="homepage_sidebar_navigation">
<% if "spree/products" == params[:controller] && #taxon %>
<%= render :partial => 'spree/shared/filters' %>
<% else %>
<%= render :partial => 'spree/shared/taxonomies' %>
<% end %>
</div>
<% end %>
So what you can do is to write an override pointing at any part of the products/show view, in particular i suggest after the product_left_part_wrap" data-hook, wich is a wrapper for the sidebar on the products show view, so your deface could look something like this:
Deface::Override.new(
:virtual_path => 'spree/products/show',
:name => 'add_map_to_product_show',
:insert_after => '[data-hook="product_left_part_wrap"]',
:partial => "spree/products/the_taxons_and_filters"
)
And inside the file named _the_taxons_and_filters.html.erb located on app/views/spree/products/ you can add the code from above and include the taxons filters. Hope this was helpful.