Write Web call for iphone in ruby on rail. I want to get json formate and send response but formate of json is incorrect - iphone

I have a bug in the following Rails code which I cannot find. Any help would be appreciated.
class Api::ItemsController < ApplicationController
respond_to :json
def create
begin
#puts "params: #{params}"
if params[:item_post][:user][:uid] && params[:item_post][:user][:provider]
#user = User.find_by_provider_and_uid(params[:item_post][:user][:provider], params[:item_post][:user][:uid])
elsif params[:item_post][:user][:token]
#user = User.create_with_token(params[:item_post][:user][:token])
elsif params[:item_post][:user][:email]
#user = User.find_by_email(params[:item_post][:user][:email])
end
if #user
#item = #user.items.new(params[:item_post][:item])
else
#item = Item.new(params[:item_post][:item])
#item.reply_email = params[:item_post][:user][:email]
end
if #item.save
if params[:item_post][:item_images]
params[:item_post][:item_images].each_value do |item_image|
#item.images.create(item_image)
end
end
respond_with(#item)
else
#puts "Errors 1: #{#item.errors}"
respond_with(#item.errors)
end
rescue => e
#puts "Errors 2: #{e.message}"
respond_with(e.message.to_json, :status => :unprocessable_entity)
end
end
end
Problem:
I have been looking into the parameters received by the server. And I've tried to find the code where the parameters are built. Where can I find it?
In the server logs I can see the post as:
{"item_post":"{\"item\":{\"title\":\"Apple TV\",\"price\":\"45.50\",\"description\":\"Dual-Shielded High Speed HDMI Cable with Ethernet 2M are sold yesterday\",\"zipcode\":\"94102\"},\"user\":{\"email\":\"user#email.com\"}}}
I was expecting the post to look like this:
{\"item_post\":{\"item\":{\"title\":\"Apple TV\",\"price\":\"45.50\",\"description\":\"Dual-Shielded High Speed HDMI Cable with Ethernet 2M are sold yesterday\",\"zipcode\":\"94102\"},\"user\":{\"email\":\"user#email.com\"}}}
It seems to me that the 'item_post' block is being wrapped in unnecessary quotes, making it a string instead of a JSON hash:
I think this:
{"item_post":"{
should look like (no quote) this:
{"item_post":{
I am only guessing to what the problem could be.

I think you need avoid the to_json in your rescue
respond_with(e.message.to_json, :status => :unprocessable_entity)
put
respond_with(e.message, :status => :unprocessable_entity)
In your case the to_json before the to_json in the respond_with return a String it's why you have a String convert in JSON and not your Hash convert in JSON

Related

Adding language variable into WWW::Mailchimp (subscription)

I'm trying to work out how I can use WWW::Mailchimp ( http://search.cpan.org/~arcanez/WWW-Mailchimp/ ) to sign someone up to our list, but also assign the language of the person (i.e english, french, german, spanish, etc).
Here is what I have thus far:
my $mailchimp = WWW::Mailchimp->new(apikey => 'xxxx' );
$mailchimp->listSubscribe( id => "xxx", email_address => $in->{Email}, merge_vars => [ FNAME => $name[0], LNAME => $name[1], mc_language => "fr", LANG => "fr", LANGUAGE => "fr" ] );
mc_language => "fr", LANG => "fr", LANGUAGE => "fr" doesn't seem to do anything (been trying all the params I see laying around, in the vain hope one of them works!)
While it works (and asks you to confirm your subscription), all the language variables are ignored. Looking at their documents, I'm a bit confused as to what to use:
https://apidocs.mailchimp.com/api/2.0/lists/subscribe.php
The code "fr" is ok, but I'm unsure what params to pass along to it.
Has anyone had any experience with this before? Apart from the language, it works fine (but I need to be able to send the confirmation emails in their own language, and then also filter down when doing mailings)
UPDATE: Ok, so it looks like its not going to be a simple case of updating to the newer API. I've been looking into the v3.0 API, and its a total overhaul of the older one (new function names, new ways of sending requests, etc). What I'm going to do is look into a "Curl" method, so we can at least get it going with that. Once I've got that going, I'll probably have a look at coding something to work with LWP::UserAgent, as that'd be cleaner than doing lots of curl requests. Shame there isn't anything out there already for Perl and MailChimp (with the new API, or even version 2.0!)
From looking at the source, it defaults to API 1.3:
has api_version => (
is => 'ro',
isa => Num,
lazy => 1,
default => sub { 1.3 },
);
The documentation for that shows you need to use MC_LANGUAGE:
string MC_LANGUAGE Set the member's language preference. Supported
codes are fully case-sensitive and can be found here.
It looks like the module just shoves whatever data structure you provide into JSON and POSTs it to Mailchimp, so the appropriate Mailchimp API doc version for the API you target should be referenced as a primary source.
Ok, so I got there in the end! I have been talking with MailChimp support, and they were very helpful. Turns out it was a double issue.
1) Auto-Translate needed to be enabled for the list in question. This was their answer around that:
After taking a look at the call, it appears to be set up properly now, so you are all good on that front. That being said, I am seeing
that the Auto-translate option doesn't seem to be enabled for any of
your lists. In order for the Confirmation and all other response
emails to automatically translate, this will need to be enabled for
all of the lists being used.
We have a bit of additional information on that, here, if you'd like to check that out:
http://kb.mailchimp.com/lists/signup-forms/translate-signup-forms-and-emails#Auto-Translate-Forms
2) When making the request via the API, you need to specifically set the Accept-Language: xx value. For example, en, fr, es, de, etc.
Here is a working function for anyone who needs it in the future. Just be sure to update the apikey,listId and endpoint URL.
do_register_email_list('foo#bar.com','Andrew Test',"en")
sub do_register_email_list {
# (email,name,lang)
use WWW::Curl::Easy;
use Digest::MD5;
use JSON;
my #name = split /\s+/, $_[1];
my $apikey = 'xxxx-us6';
my $listid = 'xxxx';
my $email = $_[0];
my $endpoint = "https://us6.api.mailchimp.com/3.0/lists";
my $lang = $_[2]||'en';
my $json = JSON::encode_json({
'email_address' => $email,
'status' => 'pending',
'language' => $lang,
'merge_fields' => {
'FNAME' => $name[0]||'',
'LNAME' => $name[1]||''
}
});
my $curl = WWW::Curl::Easy->new;
my $url = "$endpoint/$listid/members/" . Digest::MD5::md5(lc($email));
$curl->setopt(CURLOPT_HEADER,1);
$curl->setopt(CURLOPT_URL, $url);
# $curl->setopt(CURLOPT_VERBOSE, 1);
$curl->setopt(CURLOPT_USERPWD, 'user:' . $apikey);
$curl->setopt(CURLOPT_HTTPHEADER, ['Content-Type: application/json',"Accept-Language: $lang"]);
$curl->setopt(CURLOPT_TIMEOUT, 10);
$curl->setopt(CURLOPT_CUSTOMREQUEST, 'PUT');
$curl->setopt(CURLOPT_SSL_VERIFYPEER, 0);
$curl->setopt(CURLOPT_POSTFIELDS, $json);
# A filehandle, reference to a scalar or reference to a typeglob can be used here.
my $response_body;
$curl->setopt(CURLOPT_WRITEDATA,\$response_body);
# Starts the actual request
my $retcode = $curl->perform;
#print "FOO HERE";
# Looking at the results...
if ($retcode == 0) {
print "Transfer went ok\n";
my $response_code = $curl->getinfo(CURLINFO_HTTP_CODE);
print "Received response: $response_body\n";
} else {
# Error code, type of error, error message
print "An error happened: $retcode ".$curl->strerror($retcode)." ".$curl->errbuf."\n";
}
}
Hopefully this saves someone else from all the grief I had with it :) (the MailChimp support lady also said she will get their team to add something about this in the developer notes, so its made a bit clearer!)

databasedotcom error on no record found

Just started using databasedotcom gem and now stuck.
When trying to find a record in Salesforce by Id, if the id/record doesn't exist, it produces the following error:
"Provided external ID field does not exist or is not accessible:"
If the Id does exist I am able to continue with my page fine.
Here's my code:
def search
#account = Account.find(params[:id])
if #account.Id
redirect_to new_user_registration_path(:id => #account.Id)
elsif params[:id].to_s.present? and #account.nil?
flash[:alert] = "Couldn't find that one. Please check and re-submit your number."
redirect_to search_path
end
end
How can I overcome this?
Thank you.
Changed the code to the following and it works fine now - thank you Danny Burkes. It captures the exception and routes accordingly.
def search
begin
#account = Account.find(params[:id])
if #account.Id
redirect_to new_user_registration_path(:id => #account.Id)
end
rescue Exception => e
flash[:alert] = "Couldn't find that one. Please check and re-submit your number."
redirect_to search_path
end
end

rhomobile prepopulated DB and reset

Hi I am prepopulating the db as said here
http://docs.rhomobile.com/faq#how-to-pre-populate-client-database
but I have a problem, that when I make reset DB with default code
def do_reset
Rhom::Rhom.database_full_reset
SyncEngine.dosync
#msg = "Database has been reset."
redirect :action => :index, :query => {:msg => #msg}
end
then I am losing the data. How can I make that the prepopulated database alsways will be loaded, when I make reset.
Cheers
I come up with such solution
in view do_reset.erb
<%
Antwort.delete_all()
file_name = File.join(Rho::RhoApplication::get_model_path('app','Settings'), 'antwort.txt')
file = File.new(file_name,"r")
aid=0
file.each_line("\n") do |row|
col = row.split("|")
aid=aid+1
#antwort=Antwort.create(
{"aid" => aid, "qid" => col[0],"antwort"=>col[1],"richtig"=>col[2]}
)
qty=file.lineno
break if file.lineno > 3000
end
Questions.delete_all()
file_name = File.join(Rho::RhoApplication::get_model_path('app','Settings'), 'questions.txt')
file = File.new(file_name)
file.each_line("\n") do |row|
col = row.split("|")
#question=Questions.create(
{"id" => col[0], "question" => col[1],"answered"=>'0',"show"=>'1',"tutorial"=>col[4]}
)
break if file.lineno > 1500
end
file.close
#msg="OK"
%>
But only problem I have now is single quotes aka ' in the texts. They are then displayed in app as a triangle with ? inside like � one. What to do?
You can seed the database using a pipe delimited text file, as explained here.
So, in the instance you are using the Property Bag model definitions, you will have a file called object_values.txt and load up whichever sources, properties, and values necessary.

How to allow custom flash keys in a redirect_to call in Rails 3

In Rails 3, you can pass has attributes directly to redirect_to to set the flash. For example:
redirect_to root_path, :notice => "Something was successful!"
However, this only works with the :alert and :notice keys; if you want to use custom keys, you have to use a more verbose version:
redirect_to root_path, :flash => { :error => "Something was successful!" }
Is there any way to make it so that custom keys (such as :error, above) can be passed to redirect_to without specifying it in :flash => {}?
In Rails 4 you can do this
class ApplicationController < ActionController::Base
add_flash_types :error, ...
and then somewhere
redirect_to root_path, error: 'Some error'
http://blog.remarkablelabs.com/2012/12/register-your-own-flash-types-rails-4-countdown-to-2013
I used the following code, placed in lib/core_ext/rails/action_controller/flash.rb and loaded via an initializer (it's a rewrite of the built-in Rails code):
module ActionController
module Flash
extend ActiveSupport::Concern
included do
delegate :alert, :notice, :error, :to => "request.flash"
helper_method :alert, :notice, :error
end
protected
def redirect_to(options = {}, response_status_and_flash = {}) #:doc:
if alert = response_status_and_flash.delete(:alert)
flash[:alert] = alert
end
if notice = response_status_and_flash.delete(:notice)
flash[:notice] = notice
end
if error = response_status_and_flash.delete(:error)
flash[:error] = error
end
if other_flashes = response_status_and_flash.delete(:flash)
flash.update(other_flashes)
end
super(options, response_status_and_flash)
end
end
end
You can, of course, add more keys besides just :error; check the code at http://github.com/rails/rails/blob/ead93c/actionpack/lib/action_controller/metal/flash.rb to see how the function looked originally.

Twitter RSS feed, [domdocument.load]: failed to open stream:

i'm using the following:
<?php
$doc = new DOMDocument();
$doc->load('http://twitter.com/statuses/user_timeline/XXXXXX.rss');
$arrFeeds = array();
foreach ($doc->getElementsByTagName('item') as $node) {
$itemRSS = array (
'title' => $node->getElementsByTagName('title')->item(0)->nodeValue,
'desc' => $node->getElementsByTagName('description')->item(0)->nodeValue,
'link' => $node->getElementsByTagName('link')->item(0)->nodeValue,
'date' => $node->getElementsByTagName('pubDate')->item(0)->nodeValue
);
array_push($arrFeeds, $itemRSS);
}
for($i=0;$i<=3;$i++) {
$tweet=substr($arrFeeds[$i]['title'],17);
$tweetDate=strtotime($arrFeeds[$i]['date']);
$newDate=date('G:ia l F Y ',$tweetDate);
if($i==0) { $b='style="border:none;"'; }
$tweetsBox.='<div class="tweetbox" ' . $b . '>
<div class="tweet"><p>' . $tweet . '</p>
<div class="tweetdate">#' . $newDate .'</div>
</div>
</div>';
}
return $tweetsBox;
?>
to return the 4 most recent tweets from a given timeline (XXXXX is the relevant feed)
It seems to work fine but i've recently been getting the following error sporadically:
PHP error debug
Error: DOMDocument::load(http://twitter.com/statuses/user_timeline/XXXXXX.rss) [domdocument.load]: failed to open stream: HTTP request failed! HTTP/1.1 502 Bad Gateway
I've read that the above code is dependant on Twitter beign available and I know it gets rather busy sometimes. Is there either a better way of receiving twits, or is there any kind of error trapping i could do to just to display "tweets are currently unavailable..." ind of message rather than causing an error. I'm usnig ModX CMS so any parse error kills the site rather than just ouputs a warning.
thanks.
I know this is old, but I was just searching for the same solution for a nearly identical script for grabbing a twitter timeline. I ended up doing this, though I haven't been able to thoroughly test it.
I defined the twitter url as a variable ($feedURL), which I also used in $doc_load. Then, I wrapped everything except for the $feedURL into this conditional statement:
$feedURL = "http://twitter.com/statuses/user_timeline/XXXXXXXX.rss"
$headers = #get_headers($feedURL);
if (preg_match("/200/", $headers[0])){
//the rest of you original code in here
}
else echo "Can't connect user-friendly message (or a fake tweet)";
So, it's just checking the headers of the the feed's page, and if its status is 200 (OK), then the rest of the script will execute. Otherwise, it'll echo a message of your choice.
(reference: http://www.phptalk.com/forum/topic/3940-how-to-check-if-an-external-url-is-valid-andor-get-file-size/ )
ETA: Or even better, save a cached version of the feed (which will also ensure you don't go over your API limit of loads):
<?php
$cache_file = dirname(__FILE__).'/cache/twitter_cache.rss';
// Start with the cache
if(file_exists($cache_file)){
$mtime = (strtotime("now") - filemtime($cache_file));
if($mtime > 600) {
$cache_rss = file_get_contents('http://twitter.com/statuses/user_timeline/75168146.rss');
$cache_static = fopen($cache_file, 'wb');
fwrite($cache_static, $cache_rss);
fclose($cache_static);
}
echo "<!-- twitter cache generated ".date('Y-m-d h:i:s', filemtime($cache_file))." -->";
}
else {
$cache_rss = file_get_contents('http://twitter.com/statuses/user_timeline/75168146.rss');
$cache_static = fopen($cache_file, 'wb');
fwrite($cache_static, $cache_rss);
fclose($cache_static);
}
//End of caching
?>
Then use $cache_file in your $doc->load($cache_file) statement instead of the actual feed url.
(Adapted from here: http://snipplr.com/view/8156/twitter-cache/).