Need to alter and cache outbound links in Rails - html

v. Rails 2.3.8
What I'm looking to achieve is to dynamically modify outbound links in Rails so that the changes are cached using fragment caching. How would you go about doing this?
Note: This time I am intentionally not including my own ideas and source code here, as I'd like to hear suggestions without bias.
Thanks.

Here is the solution:
In ActionController::Caching::Fragments.fragment_for, change these lines:
pos = buffer.length
block.call
write_fragment(name, buffer[pos..-1], options)
to this:
pos = buffer.length
fragment = Nokogiri::HTML::fragment(block.call)
fragment.css('a').each do |a|
unless a['href'].nil?
a.set_attribute('rel', 'nofollow') unless (a['href'].starts_with?('/') || a['href'].starts_with?("http://#{ENV['BASE_URL']}"))
end
end
buffer[pos..-1] = fragment.to_html
write_fragment(name, buffer[pos..-1], options)
Please note that:
I use ENV['BASE_URL'] to store the base URL of the site (loaded from
database during initialization).
You must have the Nokogiri gem installed.
This solution works for Rails 2.3.8 - I have not tested in version 3.

Related

How do I get Rails 4.x streaming to work with MySQL when testing?

I created a new Rails 4.2.1 test project to try out the new streaming feature (the 'Live' one which I read about here). This project is set up to use MySQL for the database (I also tried Sqlite but couldn't repro the issue with it). The project is simple, consisting only of: 1) a model Test with 2 attributes (both strings). 2) a simple route resources :tests and 3) a simple controller tests_controller with one action index. The model and controller were generated by the standard rails generators, and only the controller was modified, as follows:
class TestsController < ApplicationController
include ActionController::Live
def index
response.headers['Content-Type'] = 'application/json'
response.stream.write('{"count": 5, "tests": [')
Test.find_each do |test|
response.stream.write(test.to_json)
response.stream.write(',')
end
response.stream.write(']}')
response.stream.close
end
end
When I run rails s and test by hand everything seems fine. But when I added a test (shown below) I get a strange error:
1) Error:
TestsControllerTest#test_index:
ActiveRecord::StatementInvalid: Mysql2::Error: This connection is in use by: #<Thread:0x007f862a4a7e48#/Users/xxx/.rvm/gems/ruby-2.2.2/gems/actionpack-4.2.1/lib/action_controller/metal/live.rb:269 sleep>: ROLLBACK
The test is:
require 'test_helper'
class TestsControllerTest < ActionController::TestCase
test "index" do
#request.headers['Accept'] = 'application/json'
get :index
assert_response :success
end
end
Note that the error is intermittent, coming up only about half the time. Also, even though testing by hand doesn't cause any errors I'm worried that when multiple clients hit the API at the same time that errors will occur. Any suggestions as to what's going on here would be much appreciated.
Pretty old, but you need to actually checkout a new database connection since ActionController::Live executes the action in a new thread:
The final caveat is that your actions are executed in a separate thread than the main thread. Make sure your actions are thread safe, and this shouldn't be a problem (don't share state across threads, etc).
https://github.com/rails/rails/blob/861b70e92f4a1fc0e465ffcf2ee62680519c8f6f/actionpack/lib/action_controller/metal/live.rb
You can even use an around_filter/around_action for this.

How can I avoid duplicated symbol errors when I use static libraries with Cocoapods?

I've got a executable target called Foobar, a static library holding some common code called FoobarCommon, and a test target specifically for the common code called FoobarCommonSpecs.
Unsurprisingly, I have made both Foobar and FoobarCommonSpecs depend on the FoobarCommon library.
The Podfile looks something like the below:
target 'FoobarCommon' do
pod 'ReactiveCocoa'
...
end
target 'Foobar' do # links against to FoobarCommon in Xcode
...
end
target 'FoobarCommonSpecs' do # links against to FoobarCommon in Xcode
pod 'LLReactiveMatchers', :git => 'https://github.com/lawrencelomax/LLReactiveMatchers.git'
end
LLReactiveMatchers is a Pod that depends on ReactiveCocoa.
Note that in this situation, ReactiveCocoa is prsent in both FoobarCommon and also in FoobarCommonSpecs
The Problem
Whenever I run FoobarCommonSpecs, I get many duplicate symbol errors for ReactiveCocoa.
I want to say to Cocoapods that it should just IGNORE LLReactiveMatcher's dependency on ReactiveCocoa. It should just let Xcode do its job and it should link with the copy of ReactiveCocoa found in FoobarCommon. How do I do that?
Does the link_with directive have anything to do with anything?

Running multi-queries in MySQL (for SphinxQL)

Currently we're relying on Sphinx's PHP library to manage our faceted search, which depends on the ability to use Sphinx's multi-queries feature.
The latest Sphinx search documentation describes how to perform the same multi-query procedure in SphinxQL, via MySQL. It gives an example using PHP.
http://sphinxsearch.com/docs/manual-2.0.4.html#sphinxql-multi-queries
Do any MySQL gems exist for ruby that support multi-queries in this way?
I'm looking at the mysql2 gem, which seems to be the latest thing, but it doesn't appear to support it. Am I still at a loss when it comes to Sphinx multi-queries in ruby?
I'm going to write a client that supports them in the next few days at work anyway if not, but obviously SphinxQL would make this much easier. I'd also rather not have to make my gem connect to two different protocols for RT indexes (which can only be written to via SphinxQL). It seems like SphinxQL is basically where it's at.
It appears the ruby-mysql gem supports this: https://github.com/tmtm/ruby-mysql/blob/master/lib/mysql.rb#L406-419
I assume it is processing this correctly. It says 'execute', but in reality it appears to simply be fetching the next set of results from a query that was already executed.
# execute next query if multiple queries are specified.
# === Return
# true if next query exists.
def next_result
return false unless more_results
check_connection
#fields = nil
nfields = #protocol.get_result
if nfields
#fields = #protocol.retr_fields nfields
#result_exist = true
end
return true
end
There is reference to it here too: http://zetcode.com/db/mysqlrubytutorial/ (Under 'Multiple Statements')
I ended up writing my own gem, which includes a little wrapper around MySQL. Not a fully-fledged mysql client, but a minimal bridge in order to support SphinxQL.
You can see the gem here: https://github.com/d11wtq/oedipus
And the C extension here: https://github.com/d11wtq/oedipus/blob/master/ext/oedipus/oedipus.c

can't update the attribute with ActiveRecord

I want to swap the content in answers table with ActiveRecord.
code 1:
Archieve::Answer.find_each do |answer|
str = answer.content
dosomething() #change the value
answer.update_attribute(:content,str)
end
But It doesn't change the value of content.
code 2:
Archieve::Answer.find_each do |answer|
str = answer.content
dosomething() #change the value
answer.reload
answer.update_attributes(
:content => str
)
end
Before update the :content attributes, I reload the record every time.
It can indeed change the the value.
Why?
What's the difference between code 1 & code 2?
Source Code
###1 Post Debug Message:
Updated Post:
Changed?: false
valid?: true
errors: #<ActiveModel::Errors:0xa687568>
errors: #<ActiveModel::Errors:0xa687568 #base=#<Archieve::Answer id: 9997190932758339, user_id: 4163690810052834, question_id: 3393286738785869, content: "狗狗生病,好可怜呀,", is_correct: false, votes_count: 0, comments_count: 0, created_at: "2011-11-06 18:38:53", updated_at: "2011-11-06 18:38:53">, #messages={}>
possible ActiveRecord 3.1.1 bug
The OP mentioned to me that he uses require "active_record" in a stand alone script (not using rails runner).
There is no separate Rails application for his task, he just uses a script. This is not necessarily bad, and has worked in earlier ActiveRecord versions, e.g. 2.x AFAIK -- maybe this is a regression in Rails 3.1 due to a new dependency?
# the OP's require statements:
require 'rubygems'
require 'logger'
require 'yaml'
require 'uuidtools'
require 'active_record'
complete code here: https://raw.github.com/Zhengquan/Swap_Chars/master/lib/orm.rb
maybe a dependency is missing, or problem with AR 3.1.1 when initialized stand alone?
It could be a bug actually
It could be that update_attribute() triggers a bug in the dirty-tracking of attributes, which then incorrectly assumes that the object has not changed, and as a result it will not be persisted, although the implementation of update_attribute() calls save() (see code fragment below).
I've seen something like this with an older version of Mongoid -- could be that there is a similar hidden bug in your ActiveRecord version for update_attribute()
In the Rails Console monkey-patch update_attribute like this:
class ActiveRecord::Base
def update_attribute(name, value) # make sure you use the exact code of your Rails Version here
send(name.to_s + '=', value)
puts "Changed?: #{changed?}" # this produced false in the OP's scenario
puts "valid?: #{valid?}"
puts "errors: #{errors.inspect}"
save
end
end
then try to run your Code 1 again...
you shouldn't see "Changed?: false".. if it returns false, although you changed the attribute, then there is a bug in your ActiveRecord version and you should report it.
Code 1:
NOTE: check the definition of update_attribute() (singular) here:
(please read the fine-print regarding validations -- it doesn't sound like a good idea to use that method)
http://ar.rubyonrails.org/classes/ActiveRecord/Base.html#M000400
See also:
Rails: update_attribute vs update_attributes
The source code for update_attribute() looks like this:
2260: def update_attribute(name, value)
2261: send(name.to_s + '=', value)
2262: save
2263: end
it could fail if there is a bug with the dirty-tracking of attributes...
Code 2:
The second code looks correct.
There are a couple of things to also consider:
1) which attributes did you define as accessible, via attr_accessible ?
e.g. only accessible attributes will be updated via update_attributes()
http://apidock.com/rails/ActiveRecord/Base/update_attributes
2) which validations do you use?
are you sure the validations pass for the record when you call update_attribute?
See also:
http://guides.rubyonrails.org/active_record_querying.html
http://m.onkey.org/active-record-query-interface
http://api.rubyonrails.org/classes/ActiveRecord/Base.html

Turn a partial into a json variable in the controller

Hi I need to turn the html of a partial into a json object (NOT TO BE RENDERED), but to be stored in a seperate format.
Something like this:
#json = (:partial => "/answers/likers" ,:type => :html)
Although the above obviously does not work, but hope you get the point, thanks!
Try render_to_string. It takes the same arguments as render, and just returns a string instead of outputting the data.
It looks like it's being deprecated but I can't find any new method that provides that same functionality for Rails 3. I tested it on a local Rails 3 setup, though, and it works for me. If anyone knows the "new" way to do this in Rails 3 please let me know, I'm interested now :)
Rails has a .to_json function. However, I never used this together with a partial ...