How to use method all for elements with two classes - capybara

This code don't work
descriptions = []
page.all('div', class: 'news-tidings__speech news-helpers_hide_mobile-small').each do |el|
descriptions.push(el.text[1..200])
end
one part of HTML:
<div class="news-tidings__speech news-helpers_hide_mobile-small">text </div>

There are a few ways to do what you want.
Just use a standard CSS selector with multiple classes
page.all('div.news-tidings__speech.news-helpers_hide_mobile-small')
If you want to use the :class option it will take an array of the desired classes (element must have all the classes)
page.all('div', class: ['div.news-tidings__speech','news-helpers_hide_mobile-small'])
It you want to make sure those are the only classes, and in a specific order, on the element then you can use a CSS attribute selector
page.all("div[class='news-tidings__speech news-helpers_hide_mobile-small']")

Related

Adding multiple class names in a ruby link_to tag

<%= link_to 'Certificate Name', certificates_path(:sort => 'name'), id:'name_header', class:#name_header %>
I want to use bootstrap to style this link. So I'd like to add multiple class names, but I'm not very sure how to do this as I have used a variable name as a class name. If it was class: 'header' I would have just added the additional class names into the quotes, but I am confused when it is written like this.
You have a couple options. You can pass an array as the class: value:
link_to ..., class: [#name_header, 'some-class', 'some-other-class']
or you could pass a single string and interpolate #name_header:
link_to ..., class: "#{#name_header} some-class some-other-class"
If I was mixing variables and fixed CSS classes, I'd go with the first approach; if I was just using a fixed list of CSS classes, I'd pass them all as a string. That's just personal preference though.

Using collection_radio_buttons on an object array in rails

I have an array of objects and i want to be able to display them using a collection_radio_button but it seems like collection_radio_buttons only works on arrays or ActiveRecord Objects. Is there any way to build a collection_radio_button using an array of objects?
This is my array of objects
[{:image_url=>"https://assets.braintreegateway.com/payment_method_logo/visa.png?environment=sandbox", :card_type=>"Visa", :last_4=>"0004", :expiration_month=>"10", :expiration_year=>"2019"}, {:image_url=>"https://assets.braintreegateway.com/payment_method_logo/visa.png?environment=sandbox", :card_type=>"Visa", :last_4=>"0004", :expiration_month=>"11", :expiration_year=>"2019"}]
This is the code i tried writing but it doesnt work
<%= collection_radio_buttons("cards", :card, #payment_methods, item_wrapper_tag: false) do |b|
b.label { b[:last_4]}
end %>
Any help is appreciated
The collection_radio_buttons helper is looking for an array of objects that will respond to the text_method input - which is then used for the radio button label generated.
The quick'n'dirty way to get your code working would be to turn your array of hashes into an array of objects that respond to methods named after the keys, IE we can turn them into OpenStructs with:
#payment_methods = #payment_methods.map { |pm| OpenStruct.new(pm) }
Passing this new array of OpenStructs should now print out what you're looking for, without the extra block:
<%= collection_radio_buttons(:cards, :card, #payment_methods, :last_4, :last_4) %>
You may want/need to alter the other inputs - :card, :cards or :last_4 - to get the desired result that'll work with the form you're building.
Another option would be to simply build the radio buttons yourself, without using the built in collection_radio_buttons helper... something like:
<% #payment_methods.each do |pm| %>
<%= radio_button_tag 'cards[card]', pm[:last_4] %>
<%= label 'cards[card]', pm[:last_4] %>
<% end %>

Conditionally add multiple classes to element

Suppose I have some #stuff, and I'm rendering a table with a few attributes about each thing. I want every other row to be colored differently, so I'm using the typical cycle trick:
%table
- #stuff.each do |thing|
%tr{ class: cycle('even', 'odd') }
%td thing.bleep
%td thing.bloop
But I also want to render certain rows differently based on some conditions related to each particular thing. So I want certain rows to also have the foo class if thing.foo? is true. If I weren't doing the cycle thing, I'd do:
%tr{ class: 'foo' if thing.foo? }
Is there a convenient way to do both of these things? Or do I really have to hand-write the ugly logic to conditionally append these things together with a space inbetween? It just feels like that sort of tedious logic is error-prone, and that there's an an abstraction I should be using to compose these two CSS class alterations.
You can use an array for class and id attributes:
The :class and :id attributes can also be specified as a Ruby array whose elements will be joined together. A :class array is joined with " " and an :id array is joined with "_".
So in this case you could do:
%tr{:class => [cycle('even', 'odd'), ('foo' if thing.foo?)]}
Any nils are removed from the array so you don’t end up with extra whitespace

Displaying different types of objects in Rails

What I'm trying to do
I am doing a search across several different models using Sphinx in my rails application, and it successfully returns the weighted results (including several different types of objects, let's say posts and users). I currently am testing this with (many.each { |one| one.inspect }), and that works fine.
I am now trying to write a method for each model with the same name that will output my objects in the format that I choose. For example, instead of one.inspect, I'd like to put one.print_pretty and have it output html that neatly prints out the information specific to that type of object. Using the user example, I'd like it to output something like:
<div class="small-2 columns">
<%= image_tag(one.userpic.avatar.url) %>
</div>
<div class="small-10 columns">
<div class="row">
<h3 class="subheader"><%= one.first + " " + one.last %></h3>
</div>
<div class="row">
<%= one.tagline %>
</div>
</div>
By contrast, on my post model, it should output something different that's applicable to the post attributes and priorities.
Question
How do I write a method for a Rails model that will output an html-styled chunk to code or otherwise style output that's of an unknown object type (from a limited pool)?
Would something like this work for you? You could create a separate partial that would show a different output for each object class. In your view, pass the object into a helper method function. For example:
<%= render_partial_for_this_type_of_object(your_object) %>
Then in a helper method, have something like:
def render_partial_for_this_type_of_object(object)
if object.class.name == "ClassA"
render 'class_a_partial', :object => object
elsif object.class.name == "ClassB"
render 'class_b_partial', :object => object
end
end
So to summarize, you are passing the object from the view to the helper, identifying what class of object it is, then passing that object to the appropriate partial based on its class that will then be rendered in the view.
I'm sure there are other ways to do this but this worked well for me in an app I just built.

How would I add a method to ActiveView::Helpers::FormHelper to be used with form_for?

I am currently making a plugin, and I would like to add a method to ActiveView::Helpers::FormHelper, Essentially, the plugin is a helper that will convert checkbox input into bitwise flags so when you do actions like new and update, you can continue to pass in a params hash, and my plugin will pull out the checkbox data and convert it into a single number representing the flag state. Anyway, I want to be able to do something like this:
<% form_for #person do |f| %>
<%= f.check_boxes_for_flags %>
<% end %>
Which would create checkboxes in the HTML and then set them accordingly to the flags. I know how to add an instance method to ActiveView::Helpers::FormHelper, but I'm not sure how to access #person from this method. Any ideas?
Why wouldn't you use:
<%= f.check_boxes_for_flags :country %>
That way you can create your extension similar to how the ActiveView helpers work.
Take a look at how check_box_tag in the rails source code gets the name from the model. Try to follow the conventions set forth by the framework, it makes things easier for you and those who will maintain your code after you.

Resources