Is Rails 3.1 Edge breaking XmlMarkup::Builder? - ruby

There are a number of examples on the Web (such as http://techoctave.com/c7/posts/32-create-an-rss-feed-in-rails) showing how to make a nice RSS feed using Builder. The canonical template is something like this:
xml.instruct! :xml, :version => "1.0"
xml.rss :version => "2.0" do
xml.channel do
xml.title "Your Blog Title"
xml.description "A blog about software and chocolate"
xml.link posts_url
for post in #posts
xml.item do
xml.title post.title
xml.description post.content
xml.pubDate post.posted_at.to_s(:rfc822)
xml.link post_url(post)
xml.guid post_url(post)
end
end
end
This works fine in Rails 3.0.7. In Rails 3.1 Edge, every command seems to produce...
Rendered home/index.rss.builder (25.2ms)
Completed 500 Internal Server Error in 875ms
ActionView::Template::Error (wrong number of arguments (1 for 0)):
1: xml.instruct!(:xml, :encoding => "UTF-8")
2:
3: xml.rss :version => "2.0" do
4: xml.channel do
app/views/home/index.rss.builder:1:in `_app_views_home_index_rss_builder___2123990471_2215695900'
app/controllers/home_controller.rb:17:in `index'
app/controllers/home_controller.rb:11:in `index'

Rails 3.1.0.rc1 broke for me with this bug too, but only when using Ruby 1.8.7 - turns out it's a problem with .instruct!
As a temporary solution you could monkeypatch xchar.rb with the following (as suggested by the author of this post http://lists.alioth.debian.org/pipermail/pkg-ruby-extras-maintainers/2010-June/005411.html):
--- /home/prahal/xmlbase.rb.orig 2010-06-03 11:18:38.000000000 +0200
+++ /home/prahal/xmlbase.rb.new 2010-06-03 11:18:53.000000000 +0200
## -131,7 +131,11 ##
end
else
def _escape(text)
- text.to_xs((#encoding != 'utf-8' or $KCODE != 'UTF8'))
+ begin
+ text.to_xs((#encoding != 'utf-8' or $KCODE != 'UTF8'))
+ rescue
+ text.to_xs()
+ end
end
end

You will also get this error if you have both Builder 3.0 and fast_xs 0.8.0 installed (note that hpricot bundles fast_xs 0.8.0 also)
You can work around this with the following monkey patch in application.rb:
class String
alias_method :orig_fast_xs, :fast_xs
def fast_xs(ignore)
orig_fast_xs
end
end

Related

Open-Uri Alternative - Getting a response from a website

The following code works in Ruby 1.9.3p-551
require "open-uri"
res = open("http://example.com/version").read
p res => {"buildNumber": 2496, "buildDate": "2015-09-29 11:18:02 +0200", "timestamp": 1443639212 }
In any Ruby version higher than 1.9.3 I get the following error;
from /Users/imac/.rbenv/versions/2.1.0/lib/ruby/2.1.0/net/http/response.rb:357:in `finish': incorrect header check (Zlib::DataError)
I need to use a higher version as this will be used in a Rails 4 app.
Any ideas for alternatives?
Turns out the gzip encoding is not accepted by default. Or at least that's what I'm guessing.
The following works.
res = open("http://someurl.com/version", "Accept-Encoding" => "plain").read
Interesting how this changed from Ruby 2.0.0+
Another neat solution for this.
require 'rest-client'
url = "http://example.com/version"
def get_response(url)
begin
return RestClient.get(url, {:accept => :json})
rescue RestClient::GatewayTimeout
"GatewayTimeout"
rescue RestClient::RequestTimeout
"RequestTimeout"
rescue SocketError
"SocketError"
end
end
p get_response(url)
# => "{\"buildNumber\": 2535, \"buildDate\": \"2015-09-30 17:41:42 +0200\", \"timestamp\": 1444085042 }"

net ldap - Encoding::UndefinedConversionError

folks! I get the following error message and I have no idea what to do. Is this a already known net-ldap bug? I tried to update my gems and I already looked for further informations in the internet. The first part is ok, I get ally my data from my ldap database but this error occurs in the end.
/usr/local/lib/ruby/gems/1.9.1/gems/net-ldap-0.3.1/lib/net/ber/core_ext/string.rb:23:in
encode': "\x8E" from ASCII-8BIT to UTF-8
(Encoding::UndefinedConversionError) from
/usr/local/lib/ruby/gems/1.9.1/gems/net-ldap-0.3.1/lib/net/ber/core_ext/string.rb:23:in
raw_utf8_encoded' from
/usr/local/lib/ruby/gems/1.9.1/gems/net-ldap-0.3.1/lib/net/ber/core_ext/string.rb:15:in
to_ber' from
/usr/local/lib/ruby/gems/1.9.1/gems/net-ldap-0.3.1/lib/net/ldap.rb:1396:in
block in search' from
/usr/local/lib/ruby/gems/1.9.1/gems/net-ldap-0.3.1/lib/net/ldap.rb:1367:in
loop' from
/usr/local/lib/ruby/gems/1.9.1/gems/net-ldap-0.3.1/lib/net/ldap.rb:1367:in
search' from
/usr/local/lib/ruby/gems/1.9.1/gems/net-ldap-0.3.1/lib/net/ldap.rb:637:in
`search'
and here my code:
require 'rubygems'
require 'net/ldap'
ldap = Net::LDAP.new
ldap.host = 'xxxxxx'
ldap.authenticate "cn=admin, dc=xxxx, dc=xxxxx, dc=de", "xxxxx!"
#puts ldap.bind
if ldap.bind
# authentication succeeded
else
# authentication failed
# p ldap.get_operation_result
end
filter = Net::LDAP::Filter.eq("uid", "*")
treebase = "xxxxx, dc=xxxxxx, dc=de"
ldap.search(:base => treebase, :filter => filter) do |entry|
puts "DN: #{entry.dn}"
entry.each do |attribute, values|
puts " #{attribute}:"
values.each do |value|
puts " --->#{value}"
end
end
end
There are many encoding issues in v0.3.1 of net-ldap [1],[2],[3],[4]. Several patches are already merged, but sadly, this great project seems semi-abandoned and the changes aren't pushed out to rubygems. Using it directly from github has been working well for me, and if you're using bundler, it is as easy sticking something like this in your Gemfile:
gem "net-ldap", :git => "git://github.com/ruby-ldap/ruby-net-ldap.git", :ref => '8a182675f4'
1 - https://github.com/ruby-ldap/ruby-net-ldap/pull/41
2 - https://github.com/ruby-ldap/ruby-net-ldap/pull/44
3 - https://github.com/ruby-ldap/ruby-net-ldap/pull/64
4 - https://github.com/ruby-ldap/ruby-net-ldap/pull/55

Ruby+Anemone Web Crawler: regex to match URLs ending in a series of digits

Suppose I was trying crawl a website a skip a page that ended like so:
http://HIDDENWEBSITE.com/anonimize/index.php?page=press_and_news&subpage=20060117
I am currently using Anemone gem in Ruby to build the crawler. I am using the skip_links_like method but my pattern never seems to match. I am trying to make this as generic as possible so it isn't dependent on subpage but just =2105925 (the digits).
I have tried /=\d+$/ and /\?.*\d+$/ but it doesn't seem to be working.
This similar to Skipping web-pages with extension pdf, zip from crawling in Anemone but I can't make it worth with digits instead of extensions.
Also, testing on http://regexpal.com/ with the pattern =\d+$ will successfully match http://misc.com/test/index.php?page=news&subpage=20060118
EDIT:
Here is the entirety of my code. I wonder if anyone can see exactly what's wrong.
require 'anemone'
...
Anemone.crawl(url, :depth_limit => 3, :obey_robots_txt => true) do |anemone|
anemone.skip_links_like /\?.*\d+$/
anemone.on_every_page do |page|
pURL = page.url.to_s
puts "Now checking: " + pURL
bestGuess[pURL] = match_freq( manList, page.doc.inner_text )
puts "Successfully checked"
end
end
My output something like this:
...
Now checking: http://MISC.com/about_us/index.php?page=press_and_news&subpage=20110711
Successfully checked
...
Anemone.crawl(url, :depth_limit => 3, :obey_robots_txt => true, :skip_query_strings => true) do |anemone|
anemone.on_every_page do |page|
pURL = page.url.to_s
puts "Now checking: " + pURL
bestGuess[pURL] = match_freq( manList, page.doc.inner_text )
puts "Successfully checked"
end
end
Actually the /\?.*\d+$/ works:
~> irb
> all systems are go wirble/hirb/ap/show <
ruby-1.9.2-p180 :001 > "http://hiddenwebsite.com/anonimize/index.php?page=press_and_news&subpage=20060117".match /\?.*\d+$/
=> #<MatchData "?page=press_and_news&subpage=20060117">

ruby on rails: request.body.read shows error

I have implemented AJAX based upload in my rails project.
This is my example code. (I followed the tutorial from here.. https://github.com/valums/file-uploader)
********** Javascript Code **********
function createUploader(){
var uploader = new qq.FileUploader({
element: document.getElementById('file-uploader'),
action: '/product/upload',
});
}
window.onload = createUploader;
********** Server side **********
def upload
#filename = params['qqfile']
f = File.open('home/files/' + #filename, "wb")
str = request.body.read
f.write(str)
f.close
render :text => '{success:true}'
end
When i run my code i got the following error message in the line "str = request.body.read"
NoMethodError (undefined method `body' for #<ActionController::CgiRequest:0xb6cd71a0>):
error details More: http://www.heypasteit.com/clip/01NE
My configuration:
[mrblack# home]# ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [i686-linux]
[mrblack# home]# rails -v
Rails 1.2.1
[mrblack# home]# gem -v
1.8.6
Can you please clear me, what did i wrong?
Becasue in Rails 1.2.1 neither ActionController::CgiRequest nor its parent ActionController::AbstractRequest contains 'body' method. You can see it if you look at these pages: cgi_process.rb and request.rb. Why do you use such old rails version??
UPDATE
#Mr. Black. You wrote "Can you please tell me any alternate way to read the incoming request similar to this request object".
You're using 'file-uploader' library from github. As I can see, that library can upload files to server side by two ways. If user has old FF, Chrome browsers or any IE version that library make a post request to iframe. If user has modern FF or Chrome version library prepares async post xmlHttpRequest. Therefore, in our rails controller we have to handle both situation. For example, for simplicity we want to write sended file data to some hard-coded place on disk.
******** app/controllers/greetings_controller.rb ********
class GreetingsController < ApplicationController
def upload
begin
is_xhr = params[:qqfile].is_a? String
data = is_xhr ? request.body : params[:qqfile]
File.open("/some_place_on_disk/bar.txt", "w") { |f| f.write(data.read) }
#result = {success: true}
if is_xhr
render :json => #result
end
# else render view
rescue Exception => e
logger.info e
#result = {error: "Error has been encountered during the processing"}
end
end
end
******** app/views/upload.html.erb ********
<%= #result.to_json %>
******** config/routes.rb ********
.....
match '/upload' => 'greetings#upload', :via => :post
.....
You can use demo.htm from github project, but you have to place it into public folder. Don't forget about fileuploader.css and fileuploader.js! :) You must change 'action' in createUploader function to action path, in my case that would be '/upload'

Is there a pluralize function in Ruby NOT Rails?

I am writing some Ruby code, not Rails, and I need to handle something like this:
found 1 match
found 2 matches
I have Rails installed so maybe I might be able to add a require clause at the top of the script, but does anyone know of a RUBY method that pluralizes strings? Is there a class I can require that can deal with this if the script isn't Rails but I have Rails installed?
Edit: All of these answers were close but I checked off the one that got it working for me.
Try this method as a helper when writing Ruby, not Rails, code:
def pluralize(number, text)
return text.pluralize if number != 1
text
end
Actually all you need to do is
require 'active_support/inflector'
and that will extend the String type.
you can then do
"MyString".pluralize
which will return
"MyStrings"
for 2.3.5 try:
require 'rubygems'
require 'active_support/inflector'
should get it, if not try
sudo gem install activesupport
and then the requires.
Inflector is overkill for most situations.
def x(n, singular, plural=nil)
if n == 1
"1 #{singular}"
elsif plural
"#{n} #{plural}"
else
"#{n} #{singular}s"
end
end
Put this in common.rb, or wherever you like your general utility functions and...
require "common"
puts x(0, 'result') # 0 results
puts x(1, 'result') # 1 result
puts x(2, 'result') # 2 results
puts x(0, 'match', 'matches') # 0 matches
puts x(1, 'match', 'matches') # 1 match
puts x(2, 'match', 'matches') # 2 matches
I personally like the linguistics gem that is definitely not rails related.
# from it's frontpage
require 'linguistics'
Linguistics.use :en
"box".en.plural #=> "boxes"
"mouse".en.plural #=> "mice"
# etc
This works for me (using ruby 2.1.1 and actionpack 3.2.17):
~$ irb
>> require 'action_view'
=> true
>> include ActionView::Helpers::TextHelper
=> Object
>> pluralize(1, 'cat')
=> "1 cat"
>> pluralize(2, 'cat')
=> "2 cats"
require 'active_support'
require 'active_support/inflector'
inf = ActiveSupport::Inflector::Inflections.new
to get the inflector, not sure how you use it
my solution:
# Custom pluralize - will return text without the number as the default pluralize.
def cpluralize(number, text)
return text.pluralize if number != 1
return text.singularize if number == 1
end
So you can have 'review' returned if you call cpluralize(1, 'reviews')
Hope that helps.
I've defined a helper function for that, I use it for every user editable model's index view :
def ovyka_counter(array, name=nil, plural=nil)
name ||= array.first.class.human_name.downcase
pluralize(array.count, name, plural)
end
then you can call it from the view :
<% ovyka_counter #posts %>
for internationalization (i18n), you may then add this to your locale YAML files :
activerecord:
models:
post: "Conversation"

Resources