I need to get some information from a delivery company who is using soap to get the list of delivery points. I finished my classes to call and execute the soap request and this is the format of the response :
{
:error_message=> "Code retour OK",
:liste_point_retrait =>
[
{
:horaires_ouverture_dimanche => "00:00-00:00 00:00-00:00",
:poids_maxi => "20000",
:conges_partiel => false,
:horaires_ouverture_vendredi => "09:00-12:00 14:30-18:00",
:acces_personne_mobilite_reduite => false,
:horaires_ouverture_jeudi => "09:00-12:00 14:30-17:30",
:nom => "BUREAU DE POSTE SAINT LEU D ESSERENT BP"
},
{
:horaires_ouverture_dimanche => "00:00-00:00 00:00-00:00",
:poids_maxi => "20000",
:conges_partiel => false,
:horaires_ouverture_vendredi => "09:00-12:00 14:00- 17:00",
:acces_personne_mobilite_reduite => true,
:horaires_ouverture_jeudi => "09:00-12:00 14:00-17:00",
:nom => "BUREAU DE POSTE PRECY SUR OISE BP"
},
{
:horaires_ouverture_dimanche => "00:00-00:00 00:00-00:00",
:poids_maxi=> "20000",
:conges_partiel => false,
:horaires_ouverture_vendredi => "08:30-12:00 14:30-17:00",
:acces_personne_mobilite_reduite => false,
:horaires_ouverture_jeudi => "08:30-12:00 14:30-17:00",
:nom => "BUREAU DE POSTE SAINT MAXIMIN BP"
}
],
:error_code=> "0",
:qualite_reponse=> "1",
:ws_request_id => "01587849465dc81b5eb19996cdd5d1cae4ead7766316f12e4fbfa6e86037caae"
}
The problem now is that I don't like the way I currently get the information to display it in my views, for example if #points contains this hash I use this in my code:
<% #points[:liste_point_retrait].each do |point| %>
<%= point[:nom] %>
<% end %>
Is there a better way to handle this response? I would like to have the possibilty to do something like this :
<% #points.each do |point| %>
<%= point.name %>
<% end %>
If you only want the data inside of the :liste_point_retrait key then only use that key?:
#points = #points[:liste_point_retrait]
Then you can continue to traverse this with
<% #points.each do |point| %>
<%= point[:nom] %>
<% end %>
If you would rather use point.nom over point[:nom] then you can create an OpenStruct from each Hash element. That is:
#points.map! { |p| OpenStruct.new(p)
I see you have name vs nom in your example and I'm not sure if that's intentional or not. If so, you need to translate all of these keys yourself.
Related
I have a table that is getting populated from an Array of Hashes. The data looks like this:
[
{'key' => 'some key', 'value' => 'some value'},
{'key' => 'some key2', 'value' => 'some value2'},
{'key' => 'some key3', 'value' => 'some value3'},
{'key' => 'some key4', 'value' => ''},
{'key' => 'some key5', 'value' => ''}
]
But it can also look like this:
[
{'key' => 'some key', 'value' => ''},
{'key' => 'some key2', 'value' => ''},
{'key' => 'some key3', 'value' => ''}
]
What's happening now is that the data where the values are all empty strings is rendering rows on my view. I don't want to render a row if ALL the values are empty strings. If the values have at least one non-empty string, I do want to render that row.
How can I stop the rendering of a row if ALL the values are empty strings? I've tried iterating through the data, which sort of works. This code:
<% #data.each do |r| %>
<tr>
<% r.each do |h| %>
<% unless h['value'].empty? %>
<td><%= h['value'] %></td>
<% end %>
<% end %>
</tr>
<% end %>
stops rendering the rows where all values are empty, but it also doesn't render the <td> where the row has some values that are empty because it's not rendering those <td>.
You can't just skip a few <td> when generating a <tr> because it'll most probably break the rendering of the <table>.
So, before starting to generate a « row » you'll have to make sure that you want to display it.
<% #data.each do |r| %>
<% unless r.all? { |h| h["value"].empty? } %>
<tr>
<% r.each do |h| %>
<td><%= h['value'] %></td>
<% end %>
</tr>
<% end %>
<% end %>
I'm using RGhost-Rails to generate bar codes on a pdf file (with wicked-pdf).
I've the following code (in Ruby on Rails 3)
<% doc=RGhost::Document.new :paper => [7,2]%>
<% doc.barcode_code39('1234567', :text => {:size => 10, :offset => [0,-10], :enable => [:text, :check, :checkintext] }) %>
<% r= doc.render :png, :resolution => 100, :debug => true, :filename => "./public/pdf/rghost_barcode.png" %>
This code works fine but i want to generate my image inline (without worrying with the filename and filepath). Something like (i guess):
<% doc=RGhost::Document.new :paper => [7,2]%>
<% doc.barcode_code39('1234567', :text => {:size => 10, :offset => [0,-10], :enable => [:text, :check, :checkintext] }) %>
<% r= doc.render_stream :png, :filename => "./public/pdf/test.png" %>
<img src="<%= RGhost inline functionality/ r.stream_Object_String? %>" width="16" height="335" alt="asd">
In this way, i wouldn't have to worry about deleting the (generated) code bar files after showing the pdf.
There is any way to do this? If not, there's other gems with these functionality (please note that i also need to show the code bar text - some gems doesn't have this).
Apparently the only solution (not the one i'm looking for) is this
In liquid templates this is achieved like so:
{{ product.metafields.book.author }}
Which returns the value of 'author' for it's key 'book'
I'm using Shopify API and Ruby on Rails and have successfully looped over each metafield for a given product:
In the controller:
#products = ShopifyAPI::Product.find(:all, :params => {:limit => 10})
In the view:
<% #products.metafields.each do |metafield| %>
<%= metafield.key %> : <%= metafield.value %>
<% end %>
This returns all of the metafields for a product, as expected. How do I return only those metafields matching a specific key i.e. 'book' from the example above?
# add metafield
product = ShopifyAPI::Product.find(product_id)
product.add_metafield(ShopifyAPI::Metafield.new({
:description => 'Author of book',
:namespace => 'book',
:key => 'author',
:value => 'Kurt Vonnegut',
:value_type => 'string'
}))
# retrieve metafield
author = ShopifyAPI::Metafield.find(:first,:params=>{:resource => "products", :resource_id => product.id, :namespace => "book", :key => "author"}).value
More info: http://www.shopify.com/technology/3032322-new-feature-metafields
This seems to do the trick:
<% product.metafields.each do |metafield| %>
<% if metafield.key == "book" %>
<%= metafield.key %>: <%= metafield.value %><br/>
<% end %>
<% end %>
or
<% product.metafields.each do |metafield| %>
<% if metafield.key.include?("book") %>
<%= metafield.key %>: <%= metafield.value %><br/>
<% else %>
<% end %>
This works:
ShopifyAPI::Metafield.find(:first,:params=>{:resource => "products", :resource_id => 94549954, :key => "book"})
ShopifyAPI::Metafield.find(:all,:params=>{:product_id => product.id, :key=> 'book'})
You can get all metafields for a product
#product = ShopifyAPI::Product.find(params[:id])
After that, you can get its metafields
#metafields = #product.metafields
Or if you need just a specific metafield for that product
#metafield = ShopifyAPI::Product::Metafield.find(:all, where: {"product_id = ? AND metafield.key = ?", product.id, "book"})
Extract of my Gemfile:
gem 'rails', '3.0.3'
gem 'inherited_resources', '1.2.1'
gem 'simple_form', '1.4.0'
For any resource, I have 1 view for the 3 actions (new, edit & show). Example:
<h1><%= I18n.t('admin.form.'+action_name.downcase, :name => controller_friendly_name) %></h1>
<%= simple_form_for([:admin, resource]) do |f| %>
<%= render "admin/shared/errors" %>
<%= f.input :title,
:label => "Title",
:hint => I18n.t('admin.form.input.title.hint', :name => controller_friendly_name),
:required => true,
:error => false,
:input_html => { :class => :large, :placeholder => I18n.t('admin.form.input.title.placeholder', :name => controller_friendly_name) }
%>
<%= f.input :is_visible,
:as => :radio,
:label => "Visible",
:error => false,
:required => true,
:collection => [['Yes', true], ['No', false]],
:wrapper_class => 'checkboxes-and-radiobuttons',
:checked => true
%>
<%= render "admin/shared/validation", :f => f %>
<% end %>
<% init_javascript "MyApplication.Form.disable();" if [:show].include?(action_name.to_sym) %>
See how the #show action set all the fields to disabled ? This is ugly.
Consider I can't refactor the views to have a show.html.erb file.
What I want to do:
When the action is #show, the simple_form builder use a custom builder wich replace <input>, <textarea>, <select> by <p> html tag, with the value.
Furthermore, I will customise the radiobuttons, checkboxes to.
My first step:
# app/inputs/showvalue_input.rb
class ShowvalueInput < SimpleForm::Inputs::Base
def input
# how to change 'text_field' by <p> container ?
#builder.text_field(attribute_name, input_html_options)
end
end
Can't find the way to do it. Custom Form Builders or Custom Inputs (with monkey patching) ?
Thank for the help !
Here's my solution
in my application_helper.rb:
def set_show_method_to_builder(builder)
builder.instance_eval <<-EVAL
def show?
#{action_name == "show"}
end
EVAL
end
In my forms (in the simple_form block):
<%- set_show_method_to_builder(f) -%>
And finally, in #app/inputs/string_input.rb:
class StringInput < SimpleForm::Inputs::StringInput
def input
if #builder.show?
content_tag(:p, #builder.object[attribute_name], :class => :show)
else
super
end
end
end
There's some problem with data types not mapped, but it's another story:
Can't create Custom inputs for some (Text, Booleans, ...) types, with SimpleForm
I am trying to filter Client Comments by using a select and rendering it in a partial. Right now the partial loads #client.comments. I have a Category model with a Categorizations join. This all works, just need to know how to get the select to call the filter action and load the partial with ajax. Thanks for you help.
Categories controller:
def filter_category
#categories = Category.all
respond_to do |format|
format.js # filter.rjs
end
end
filter.js.erb:
page.replace_html 'client-note-inner',
:partial => 'comments',
:locals => { :com => Category.first.comments }
show.html.erb (clients)
<% form_tag(filter_category_path(:id), :method => :put, :class => 'categories', :remote => true, :controller => 'categoires', :action => 'filter') do %>
<label>Categories</label>
<%= select_tag(:category, options_for_select(Category.all.map {|category| [category.name, category.id]}, #category_id)) %>
<% end %>
<div class="client-note-inner">
<%= render :partial => 'comments', :locals => { :com => #comments } %>
</div><!--end client-note-inner-->
Hope that makes sense.
Cheers.
It's straightforward with a simple onchange
<%= select_tag(:category, options_for_select(Category.all.map {|category| [category.name, category.id]}, #category_id), onchange => 'form.submit()') %>