What's the best way to replace a string inside a string in ruby? - ruby

I have a bunch of these:
'link' => "http://twitter.com/home?status=Check out "{title}" {url}",
And Want to replace the {title} and {url} bits.
I'm currently doing this with gsub:
l.gsub! "{url}", URI::encode(#opts[:url])
l.gsub! "{title}", URI::encode(#opts[:title])
But I have the feeling there's a much better way to do this than with gsub...
#
This is an edit / addition to clarify:
class SocialBookmarkMaker
require 'open-uri'
attr_accessor :opts
def initialize(opts)
#opts = ##default_opts.merge opts
end
##default_opts = {
:icon_folder => "/images/icons/social_aquatic/24 X 24",
:sites => ['facebook', 'twitter', 'delicious', 'digg', 'stumbleupon', 'reddit', 'technorati', ],
:ext => 'png',
:url => 'not provided',
:title => 'not provided',
}
##bookmarks = {
'yahoo' => {
'name' => 'Yahoo! My Web',
'link' => 'http://myweb2.search.yahoo.com/myresults/bookmarklet?u={url}&t={title}',
},
'google' => {
'name' => 'Google Bookmarks',
'link' => 'http://www.google.com/bookmarks/mark?op=edit&bkmk={url}&title={title}',
},
'windows' => {
'name' => 'Windows Live',
'link' => 'https://favorites.live.com/quickadd.aspx?url={url}&title={title}',
},
'facebook' => {
'name' => 'Facebook',
'link' => 'http://www.facebook.com/sharer.php?u={url}&t={title}',
},
'digg' => {
'name' => 'Digg',
'link' => 'http://digg.com/submit?phase=2&url={url}&title={title}',
},
'ask' => {
'name' => 'Ask',
'link' => 'http://myjeeves.ask.com/mysearch/BookmarkIt?v=1.2&t=webpages&url={url}&title={title}',
},
'technorati' => {
'name' => 'Technorati',
'link' => 'http://www.technorati.com/faves?add={url}',
},
'delicious' => {
'name' => 'del.icio.us',
'link' => 'http://del.icio.us/post?url={url}&title={title}',
},
'stumbleupon' => {
'name' => 'StumbleUpon',
'link' => 'http://www.stumbleupon.com/submit?url={url}&title={title}',
},
'squidoo' => {
'name' => 'Squidoo',
'link' => 'http://www.squidoo.com/lensmaster/bookmark?{url}'
},
'netscape' => {
'name' => 'Netscape',
'link' => 'http://www.netscape.com/submit/?U={url}&T={title}',
},
'slashdot' => {
'name' => 'Slashdot',
'link' => 'http://slashdot.org/bookmark.pl?url={url}&title={title}',
},
'reddit' => {
'name' => 'reddit',
'link' => 'http://reddit.com/submit?url={url}&title={title}',
},
'furl' => {
'name' => 'Furl',
'link' => 'http://furl.net/storeIt.jsp?u={url}&t={title}',
},
'blinklist' => {
'name' => 'BlinkList',
'link' => 'http://blinklist.com/index.php?Action=Blink/addblink.php&Url={url}&Title={title}',
},
'dzone' => {
'name' => 'dzone',
'link' => 'http://www.dzone.com/links/add.html?url={url}&title={title}',
},
'swik' => {
'name' => 'SWiK',
'link' => 'http://stories.swik.net/?submitUrl&url={url}'
},
'shoutwire' => {
'name' => 'Shoutwrie',
'link' => 'http://www.shoutwire.com/?p=submit&&link={url}',
},
'blinkbits' => {
'name' => 'Blinkbits',
'link' => 'http://www.blinkbits.com/bookmarklets/save.php?v=1&source_url={url}',
},
'spurl' => {
'name' => 'Spurl',
'link' => 'http://www.spurl.net/spurl.php?url={url}&title={title}',
},
'diigo' => {
'name' => 'Diigo',
'link' => 'http://www.diigo.com/post?url={url}&title={title}',
},
'tailrank' => {
'name' => 'Tailrank',
'link' => 'http://tailrank.com/share/?link_href={url}&title={title}',
},
'rawsugar' => {
'name' => 'Rawsugar',
'link' => 'http://www.rawsugar.com/tagger/?turl={url}&tttl={title}&editorInitialized=1',
},
'twitter' => {
'name' => 'Twitter',
'link' => "http://twitter.com/home?status=Check out "{title}" {url}",
},
}
def self.bookmarks
##bookmarks
end
def icon_loc(site)
"http://common-resources.---.net.s3.amazonaws.com#{#opts[:icon_folder]}/#{site}.#{#opts[:ext]}"
end
def link_url(site)
l = SocialBookmarkMaker.bookmarks[site]['link']
l.gsub! "{url}", URI::encode(#opts[:url])
l.gsub! "{title}", URI::encode(#opts[:title])
l
end
end
shared/social_bookmarks/standard.html.haml
- opts ||= {}
- opts.merge! :url => request.url
- opts.merge! :title => "---.net: #{#layout[:social_bookmark_title] || #layout[:title] || default_view_title}"
- b = SocialBookmarkMaker.new opts
- b.opts[:sites].each do |site|
= link_to(image_tag( b.icon_loc(site) ), b.link_url(site), :title => "Share on #{SocialBookmarkMaker.bookmarks[site]['name']}")
I then call this like this in my rails layout:
render :partial => "shared/social_bookmarks/standard", :locals => { :opts => {:icon_folder => "/images/icons/social_aquatic/48 X 48" }}

Either you change your string to look like
"http://twitter.com/home?status=Check out "%{title}" %{url}"
and then use printf with a Hash
s = "http://twitter.com/home?status=Check out "%{title}" %{url}"
# you can of course use #opts as the Hash here.
s = s % {:title => "abc", :url => "def"} # => "http://twitter.com/home?status=Check out "abc" def"
and accept that it only works with Ruby 1.9.2 and upwards, or you continue using gsub but using the block syntax to condense it:
s.gsub!(/\{(.+?)\}/) do |m|
#opts[$1.to_sym]
end

You can just embed the variables directly in the string
'link' => "http://twitter.com/home?status=Check out "#{title}" #{url}"

Related

Ruby hash of hashes, how to get key if there is a key value match into the nested hashes

I have a ruby hash with this structure:
jotform = {
'1' => {
'name' => 'theGreat',
'order' => '1',
'text' => 'xxxxx',
'type' => 'control_head'
},
'3' => {
'name' => 'clickTo',
'order' => '2',
'text' => '<p>Final date to apply is August 29</p>',
'type' => 'control_text'
},
'4' => {
'name' => 'personalDetails',
'order' => '3',
'text' => 'Personal Details',
'type' => 'control_head'
},
'5' => {
'name' => 'name',
'order' => '4',
'sublabels' =>
'{"prefix":"Prefix","first":"First Name","middle":"Middle Name","last":"Last Name","suffix":"Suffix"}',
'text' => 'Name',
'type' => 'control_fullname',
'answer' => {
'first' => 'Example',
'last' => 'Example'
},
'prettyFormat' => 'Example'
},
'9' => {
'name' => 'country',
'order' => '5',
'text' => 'Country',
'type' => 'control_dropdown',
'answer' => 'Germany'
},
'10' => {
'name' => 'email',
'order' => '6',
'text' => 'Email',
'type' => 'control_email',
'answer' => 'picco#example.com'
},
'15' => {
'name' => 'pageBreak',
'order' => '8',
'text' => 'Page Break',
'type' => 'control_pagebreak'
},
'16' => {
'name' => 'contributions',
'order' => '9',
'text' => 'Contributions',
'type' => 'control_head'
}
}
This is a payload that I receive from jotform and I have to process in my app.
The issue is that I don't know the field order: this hash has some keys ('1', '2', …) that are equivalent to the form answer.
I must get the name in Pretty Format and the email, so I'm trying to get these values.
Here the email has key '10' and the name has key '5' but they can change in the next form.
I try with
jotform.select { |_key, hash| hash['name'] == 'email' }
But it returns
{
'10' => {
'name' => 'email',
'order' => '6',
'text' => 'Email',
'type' => 'control_email',
'answer' => 'example#example.com'
}
}
I need to get the key ('10') if there is a match into this key's value but I cannot understand how.
From the result of your select call:
h = jotform.select{ |key, hash| hash["name"] == "email" }
You can get the key via:
h.keys.first
#=> "10"
And the value via:
h.values.first["answer"]
#=> "example#example.com"
first is needed because there could (in theory) be multiple entries for email.
Well, that's a weird format.
I'm not sure I understand it, but assuming that name is unique, you could reindex your hash and use name as key:
new_data = jotform.map do |id, h|
key = h.delete 'name'
[key, h.merge('id' => id)]
end.to_h
The new format looks like :
{"theGreat"=>
{"order"=>"1", "text"=>"xxxxx", "type"=>"control_head", "id"=>"1"},
"clickTo"=>
{"order"=>"2",
"text"=>"<p>Final date to apply is August 29</p>",
"type"=>"control_text",
"id"=>"3"},
"personalDetails"=>
{"order"=>"3",
"text"=>"Personal Details",
"type"=>"control_head",
"id"=>"4"},
"name"=>
{"order"=>"4",
"sublabels"=>
"{\"prefix\":\"Prefix\",\"first\":\"First Name\",\"middle\":\"Middle Name\",\"last\":\"Last Name\",\"suffix\":\"Suffix\"}",
"text"=>"Name",
"type"=>"control_fullname",
"answer"=>{"first"=>"Example", "last"=>"Example"},
"prettyFormat"=>"Example",
"id"=>"5"},
"country"=>
{"order"=>"5",
"text"=>"Country",
"type"=>"control_dropdown",
"answer"=>"Germany",
"id"=>"9"},
"email"=>
{"order"=>"6",
"text"=>"Email",
"type"=>"control_email",
"answer"=>"picco#example.com",
"id"=>"10"},
"pageBreak"=>
{"order"=>"8",
"text"=>"Page Break",
"type"=>"control_pagebreak",
"id"=>"15"},
"contributions"=>
{"order"=>"9", "text"=>"Contributions", "type"=>"control_head", "id"=>"16"}}
No information has been lost, and it should be easier to access. In order to get the email address, you can simply use:
new_data["email"]["answer"]
#=> "picco#example.com"

Default value for select in custom Modifier

I have a select field from a form defined like bellow. As you can see that select has two values, Yes and No. I'm looking to set a default value for this select.
"children" => [
"bc_offer_is_duration_count_fixed" => [
"arguments" => [
"data" => [
"config" => [
"dataType" => "select",
"formElement" => "select",
"visible" => "1",
"required" => "1",
"validation" => [
'required-entry' => "1"
],
"default" => null,
"label" => __('Is duration count fixed'),
"scopeLabel" => __('[GLOBAL]'),
"code" => "bc_offer_offer_durations",
"source" => "content",
"globalScope" => true,
"sortOrder" => 10,
"componentType" => "field",
"component" => "Project_OfferProducts/js/form/element/offer-is-duration-count-fixed",
'options' => [['label' => __('Yes'), 'value' => '1'], ['label' => __('No'), 'value' => '0']]
]
]
]
]
]
It's part of the modifyData method from a class defined here
use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier as CatalogAbstractModifier;
abstract class AbstractModifier extends CatalogAbstractModifier
Obviously I already tried to set "default" => "Yes" and "default" => "1" and "default" => 1
I also have an offer-js-duration-count-fixed.js file with that content
define([
'Magento_Ui/js/form/element/select',
'Project_OfferProducts/js/model/offer-configuration/context'
], function (Select, context) {
'use strict';
return Select.extend({
updatingDurationFromField: false,
initialize: function () {
this._super();
context.isDurationCountFixed.subscribe(function(newValue){
this.refreshInField(newValue);
}.bind(this));
this.value.subscribe(this.refreshInGrid.bind(this));
if(context.isDurationCountFixed())
{
this.value(1);
}
else
{
this.value(0);
}
return this;
},
refreshInGrid: function(){
this.updatingDurationFromField = true;
context.isDurationCountFixed(this.value());
this.updatingDurationFromField = false;
},
refreshInField: function(newValue){
if(!this.updatingDurationFromField)
{
this.value(context.isDurationCountFixed());
}
}
});});
I'm under Magento 2.
just what i think
change this
'options' => [['label' => __('Yes'), 'value' => '1'], ['label' => __('No'), 'value' => '0']]
to
'options' => [['label' => __('Yes'), 'value' => 1], ['label' => __('No'), 'value' => 0]]
and change
"default" => null,
to
"default" => "1",

How to post form with WWW::Mechanize (ajax)

I posted a few days ago about posting a form by changing the page size. Can someone help with the steps. I am including the dump of the form and the code I'm using to post it. Here is the code to get the first page, which defaults to a page size of 30 players, and then from there I am going to post the form to change page size to 500.
my $mech = WWW::Mechanize->new();
my $url = "https://www.fangraphs.com/projections.aspx?pos=all&stats=bat&type=steamer&team=0&lg=all&players=0";
$mech->get($url);
print Dumper($mech->forms());
$VAR1 = bless( {
'default_charset' => 'UTF-8',
'enctype' => 'application/x-www-form-urlencoded',
'accept_charset' => 'UNKNOWN',
'action' => bless( do{\(my $o = 'https://www.fangraphs.com/projections.aspx?pos=all&stats=bat&type=steamer&team=0&lg=all&players=0')}, 'URI::https' ),
'method' => 'POST',
'attr' => {
'id' => 'form1',
'method' => 'post'
},
'inputs' => [
bless( {
'readonly' => 1,
'/' => '/',
'value_name' => '',
'value' => '',
'name' => 'RadScriptManager1_TSM',
'id' => 'RadScriptManager1_TSM',
'type' => 'hidden'
}, 'HTML::Form::TextInput' ),
bless( {
'/' => '/',
'value' => '30',
'name' => 'ProjectionBoard1$dg1$ctl00$ctl02$ctl00$PageSizeComboBox',
'readonly' => 'readonly',
'value_name' => '',
'type' => 'text',
'class' => 'rcbInput radPreventDecorate',
'id' => 'ProjectionBoard1_dg1_ctl00_ctl02_ctl00_PageSizeComboBox_Input'
}, 'HTML::Form::TextInput' ),
bless( {
'tabindex' => '-1',
'class' => 'rcbActionButton',
'type' => 'button'
}, 'HTML::Form::SubmitInput' ),
bless( {
'readonly' => 1,
'/' => '/',
'value_name' => '',
'name' => 'ProjectionBoard1_dg1_ctl00_ctl03_ctl01_PageSizeComboBox_ClientState',
'id' => 'ProjectionBoard1_dg1_ctl00_ctl03_ctl01_PageSizeComboBox_ClientState',
'type' => 'hidden'
}, 'HTML::Form::TextInput' ),
]
}, 'HTML::Form' );
I then try to submit the form with the following:
$mech->submit_form(
form_id => 'form1',
with_fields => {
name => 'ProjectionBoard1$dg1$ctl00$ctl03$ctl01$PageSizeComboBox',
id => 'ProjectionBoard1_dg1_ctl00_ctl03_ctl01_PageSizeComboBox_Input',
value => 500,
},
);
but the response I get from the script is 'There is no form with the requested fields '
try something like that:
use WWW::Mechanize;
my $mech = WWW::Mechanize->new();
my $url = "https://www.fangraphs.com/projections.aspx?pos=all&stats=bat&type=steamer&team=0&lg=all&players=0";
$mech->get($url);
$mech->set_fields(
'RadScriptManager1_TSM' => '',
'ProjectionBoard1$dg1$ctl00$ctl02$ctl00$PageSizeComboBox' => '30'
'ProjectionBoard1_dg1_ctl00_ctl03_ctl01_PageSizeComboBox_ClientState' => ''
);
$mech->submit;
set the form fields using the syntax 'FIELD_NAME' => 'VALUE' and then submit

ruby-aws Amazon Mechanical Turk

I am trying to create a HIT with a pre-created form using the ruby-aws gem and keep getting a missing params error. I have limited the missing params to the params specific to my form.
It seems my request is not being formatted correctly and there are next to no examples from Amazon. My logs say the the following params are missing:
relationship, price, environmental_consciousness, age, occasion, gender, humor, experience, local, romance, additional_information
Any help is much appreciated!
Below is my current request:
hit = mturk.createHIT(
:Operation => 'CreateHIT',
:Title => 'Find a gift based on user scores',
:Description => 'Find a gift for an individual based on survey scores.',
:MaxAssignments => 3,
:Signature => signature,
:Timestamp => timestamp,
:Reward => { :Amount => 0.25, :CurrencyCode => 'USD' },
:HITLayoutId => '3AV6FF2M2GYMGLRQEKHZ7EBN4EZOJE',
:HitLayoutParameter => {'Name' => 'additional_information', 'Value' => 'TEST'},
:HitLayoutParameter => {'Name' => 'age', 'Value' => '22'},
:HitLayoutParameter => {'Name' => 'environmental_consciousness', 'Value' => '54'},
:HitLayoutParameter => {'Name' => 'experience', 'Value' => '32'},
:HitLayoutParameter => {'Name' => 'gender', 'Value' => 'male'},
:HitLayoutParameter => {'Name' => 'humor', 'Value' => '66'},
:HitLayoutParameter => {'Name' => 'local', 'Value' => '21'},
:HitLayoutParameter => {'Name' => 'occasion', 'Value' => '43'},
:HitLayoutParameter => {'Name' => 'price', 'Value' => '33'},
:HitLayoutParameter => {'Name' => 'relationship', 'Value' => '23'},
:HitLayoutParameter => {'Name' => 'romance', 'Value' => '23'},
:Keywords => 'data collection, gifting, gifts, shopping, gift listings, presents',
:AssignmentDurationInSeconds => 300,
:LifetimeInSeconds => 604800
)
I was able to resolive the issue - AWS has terrible naming conventions. The above example does use the correct format, however HitLayoutParameter must be HITLayoutParameter - Notice the CAPITAL HIT vs Hit.
Also, when submitting multiple parameters, the should only be one HITLayoutParameter that equals an array of Name/Value pairs. Working code below.
Hope this helps someone else!
Best,
~DFO~
hit = mturk.createHIT(
:Operation => 'CreateHIT',
:Title => 'Find a gift based on user scores',
:Description => 'Find a gift for an individual based on survey scores.',
:MaxAssignments => 3,
:Signature => signature,
:Timestamp => timestamp,
:Reward => { :Amount => 0.25, :CurrencyCode => 'USD' },
:HITLayoutId => '3AV6FF2M2GYMGLRQEKHZ7EBN4EZOJE',
:HITLayoutParameter => [
{:Name => 'additional_information', :Value => 'TEST'},
{:Name => 'age', :Value => '22'},
{:Name => 'environmental_consciousness', :Value => '54'},
{:Name => 'experience', :Value => '32'},
{:Name => 'gender', :Value => 'male'},
{:Name => 'humor', :Value => '66'},
{:Name => 'local', :Value => '21'},
{:Name => 'occasion', :Value => '43'},
{:Name => 'price', :Value => '33'},
{:Name => 'relationship', :Value => '23'},
{:Name => 'romance', :Value => '23'}
],
:Keywords => 'data collection, gifting, gifts, shopping, gift listings, presents',
:AssignmentDurationInSeconds => 300,
:LifetimeInSeconds => 604800
)

Recurrence with Google calendar ruby API V3

Using the following code, I've not been able to push any recurring events to google calendar. However, take off the 'recurrence' item from event and it works.
What am I doing wrong ?
event = {
'summary' => 'Appointment',
'location' => 'Somewhere',
'start' => {
'dateTime' => '2011-06-03T10:00:00.000-07:00'
},
'end' => {
'dateTime' => '2011-06-03T10:25:00.000-07:00'
},
'recurrence' => [
"RRULE:FREQ=DAILY;COUNT=5"
]
}
result = #client.execute(:api_method => #service.events.insert,
:parameters => {'calendarId' => 'hg9a7o16bm6dj0tmuo481499mc#group.calendar.google.com'},
:body_object => event,
:headers => {'Content-Type' => 'application/json'})
puts result.data.id.to_s
The timezone needs to be set in a seperate field as this
event = {
'summary' => 'Appointment',
'location' => 'Somewhere',
'start' => {
'dateTime' => '2011-06-03T10:00:00.000-07:00',
'timeZone' => 'America/Montreal'
},
'end' => {
'dateTime' => '2011-06-03T10:25:00.000-07:00',
'timeZone' => 'America/Montreal'
},
'recurrence' => [
"RRULE:FREQ=DAILY;COUNT=5"
]
}
Please try with "RRULE:FREQ=WEEKLY;UNTIL=20120701T160000Z";

Resources