using a regex inside an HTML helper - regex

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)

Related

Rails 5 erb doesn't escape html

In a rails 5.2.3 erb template:
<% input = "<script>alert('XSS')</script>" %>
<p><%= input %></p>
is showing <script>alert('XSS')</script> instead of &gt.. etc
Isn't <%= ... %> supposed to prevent against reflected xss attack?
Same issue if input is retrieved from params[:input]
The raw is output in the html:
Need to look in source ctrl+u
as Gabor suggested

What is '<%%' in ERB in Rails?

I have bean seen code of scaffold in rails. I found
<%% breadcrumb_add "<%= plural_table_name.capitalize %>", <%= plural_table_name %>_path %>
<%%= render 'form' %>
https://github.com/rails/rails/blob/3fcc0ca99107fa57110421b392f5854555f17fe2/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb
What is <%% and how to use?
<%% in Erb produces a literal <% in the output. You can use it if you want the output of your template to also be Erb, which is what is happening in the Rails example you link to.
In your code, the output will be something like (if the variable plural_table_name is things):
<% breadcrumb_add "Things", thing_path %>
<%= render 'form' %>
which itself is Erb.

Rails 4, Draper: authenticated user and views

<% if user_signed_in? %>
<!-- lots of html/erb -->
<% end %>
This view pattern seems to not separate concerns.
I wrap several views in my app with logic demanding the user is signed in and would instead like to separate concerns and put the <% if user_signed_in? %> logic where it belongs...this seems like a decorator thing to me (hence the Draper tag).
What is best practice here?
Not sure understood your question, but try to answer.
At first to separate logic you dont need to use decorators in front of all, they serves for a little another thing.
To separate logic you can use simple partials depending on current user state, for ex:
<% if user_signed_in? %>
<%= render 'file_with_html_for_signed_user' %>
<% else %>
<%= render 'file_with_html_for_non_signed_user' %>
<% end %>
You can declare this statement in your layouts/application.html.erb

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.

Use deface to change bad code in Spree store

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.