template.path_without_format_and_extension Not working in rails 3.0.3. Getting undefined method template - ruby-on-rails-3

I am using i18n in rails 3.0.3 and user have functionality to edit text. If user save text then it comes from database instead of en.yml file. I have override t helper like below:
def c_t(key, options = {})
c_key = (scope_key_by_partial_custom(key)).gsub(".","_")
if $LAYOUT_CONTENTS[c_key].present?
$LAYOUT_CONTENTS[c_key]
else
t(key,options)
end
end
and then
def scope_key_by_partial_custom(key)
if key.to_s.first == "."
template.path_without_format_and_extension.gsub(%r{/_?}, ".") + key.to_s
else
key
end
end
I am calling this method from view:
<h1 <%= c_t '.title' %></h1>
It was working fine in rails 2.3 but after upgrading rails to 3.0.3 I am getting error
**undefined method `template' for Class

use this helper method in rails 3
view_context.instance_variable_get(:#_virtual_path)

Related

rails-translate-routes gem: Is it possible to translate routes but keep (some) original ones?

I'm using rails-translate-routes gem to translate "front" routes only.
I'm using carrierwave to upload some files in my admin. Here's an uploader:
class CheatsheetUploader < CarrierWave::Uploader::Base
[...]
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
[...]
end
As you see, the path is using the name of the model and the name of the field.
When I try to get the file:
link_to "my file", download.cheatsheet.url
The path is the default one:
http://localhost:3000/uploads/download/cheatsheet/1/a_really_nice_file.pdf
And Rails give me a nice Routing error:
No route matches [GET] "/uploads/download/cheatsheet/1/a_really_nice_file.pdf"
Any way to handle this?
You can pass keep_untranslated_routes: true in your call to ActionDispatch::Routing::Translator.translate_from_file.
For example:
ActionDispatch::Routing::Translator.translate_from_file(
'config/locales/routes.yml',
no_prefixes: true,
keep_untranslated_routes: true)

Accessing Route helpers in rails 3.2

I'm migrating a rails 2.3 app to rails 3.2.
I have an object used to manage the caching of a few stats I collect from different sources.
As the collection process is quite long, It couldn't be done with the traditional fragment caching.
I had to fill the cache asynchronously.
the AsynchCache object, get data from Google Analytics and stores the content of a partial in the cache.
include Rails.application.routes.url_helpers
class AsynchCache
def self.get_popular_races_from_google_analytics(lang='en')
# getting info form GA using Garb.
end
def self.set_popular_races(language=nil)
av = ActionView::Base.new(Rails.configuration.paths['app/views'])
language_list = Global.instance.languages_UI.map{|a| a[0]}
for lang in language.nil? ? language_list : [language]
output = av.render(
:partial => "home/popular_races",
:locals => {:lang => lang}
)
Rails.cache.delete("popular_races_#{lang}")
Rails.cache.write("popular_races_#{lang}",output)
end
end
def self.get_popular_races(lang='en')
Rails.cache.read("popular_races_#{lang}")
end
end
The partial I used for the display is as follows
"> tmp_race.name -%>
When I want to display the content, I just have to use :
<div id="popular_races"> <%# AsynchCache.get_popular_races(params[:locale])-%> </div>
It works fine when I first load the page, or in irb, but if I try to reload the page or set in development.rb config.cache_classes = true, I get an error :
stack level too deep
Rails.root: /Users/macbook/Sites/marathons
Application Trace | Framework Trace | Full Trace
actionpack (3.2.1) lib/action_dispatch/middleware/reloader.rb:70
If I remove include Rails.application.routes.url_helpers, i don't get the error, but of course, I don't have acccess to the routes.
Is there a new way to get the route methods from a model in rails 3.2?
I had the same problem as you. What I did was, instead of including the helpers, I used them like this every time:
Rails.application.routes.url_helpers.object_path(...)

encoding error with ajax upload (qqfile) and paperclip

I'm trying to get an ajax upload working with rails 3.1.3 and paperclip.
I found this solution to my problem Rails 3 get raw post data and write it to tmp file, but using this, I get an 'encoding undefined conversion error "\xFF" from ASCII-8BIT to UTF-8.
The error occurs at the line #user.photo = #user.photo = QqFile.parse(params[:qqfile], request)
I have not edited the code supplied in the previous answer, but I'll include it here so you don't have to switch back and forth.
the gem list paperclip, returns 2.5.2, 2.4.5, 2.3.8
my controller
def create
#user = User.new(params[:user])
#user.photo = QqFile.parse(params[:qqfile], request)
if #user.save
return render :json => #user
else
return render :json => #user.errors
end
end
qq_file.rb
# encoding: utf-8
require 'digest/sha1'
require 'mime/types'
# Usage (paperclip example)
# #asset.data = QqFile.new(params[:qqfile], request)
class QqFile < ::Tempfile
def initialize(filename, request, tmpdir = Dir::tmpdir)
#original_filename = filename
#request = request
super Digest::SHA1.hexdigest(filename), tmpdir
fetch
end
def self.parse(*args)
return args.first unless args.first.is_a?(String)
new(*args)
end
def fetch
self.write #request.raw_post
self.rewind
self
end
def original_filename
#original_filename
end
def content_type
types = MIME::Types.type_for(#request.content_type)
types.empty? ? #request.content_type : types.first.to_s
end
end
This was an encoding error related to Ruby 1.9.2 (or I believe Ruby 1.9+).
this github post lead to the answer
https://github.com/lassebunk/webcam_app/issues/1
You must specify raw_post.force_encoding("UTF-8") when reading an upload as far as I could tell (I'm not a great programmer).

Error when saving a Backbone.js model with Rails

I have Backbone.js collection and model for a project object:
window.Project = Backbone.Model.extend();
window.Projects = Backbone.Collection.extend({
model: Project,
url: '/projects'
});
I have setup a rails controller to respond to the Backbone.js collection:
class ProjectsController < ApplicationController
def index
render :json => Project.all
end
def create
project = Project.create! params
render :json => project
end
end
Index works fine and I get a list of projects in my web app. The problem is if I try and create a model on the Projects collection I get a 500 error from the server.
The error message on the server is as follows:
Started POST "/projects" for 127.0.0.1 at 2011-08-21 08:27:56 +0100
Processing by ProjectsController#create as JSON
Parameters: {"title"=>"another test"}
Completed 500 Internal Server Error in 16ms
ActiveRecord::UnknownAttributeError (unknown attribute: action):
app/controllers/projects_controller.rb:8:in `create'
I am not sure what the unknown attribute: action is referring to.
For info I have set up the projects_controller as resources :projects. I have also set rails to ActiveRecord::Base.include_root_in_json = false.
Yes, Rails always adds the action and controller to params. The parameters come from ActionDispatch::Http::Parameters:
def parameters
#env["action_dispatch.request.parameters"] ||= begin
params = request_parameters.merge(query_parameters)
params.merge!(path_parameters)
encode_params(params).with_indifferent_access
end
end
And path_parameters:
Returns a hash with the parameters used to form the path of the request. Returned hash keys are strings:
{'action' => 'my_action', 'controller' => 'my_controller'}
So you shouldn't be doing project = Project.create! params. You could go the update_attributes route:
project = Project.new
project.update_attributes params[:model_name]
But this assumes that you have what you need in a sub-hash of params and it won't call your validators. Backbone won't namespace your attributes by default but you could override Backbone.sync and do it yourself. Still, you probably want your validations so update_attributes should generally be avoided.
Your best bet is to pull exactly the attributes out of params that you're expecting to be there. This is even the Backbone recommended practise:
*(In real code, never use update_attributes blindly, and always whitelist the attributes you allow to be changed.)*
You can enable parameter wrapping. Add a file in the initializer directory with:
ActiveSupport.on_load(:action_controller) do
wrap_parameters format: [:json]
end
and, for json request, you post params will now be wrapped with the model name.

How do I write a Rails 3.1 engine controller test in rspec?

I have written a Rails 3.1 engine with the namespace Posts. Hence, my controllers are found in app/controllers/posts/, my models in app/models/posts, etc. I can test the models just fine. The spec for one model looks like...
module Posts
describe Post do
describe 'Associations' do
it ...
end
... and everything works fine.
However, the specs for the controllers do not work. The Rails engine is mounted at /posts, yet the controller is Posts::PostController. Thus, the tests look for the controller route to be posts/posts.
describe "GET index" do
it "assigns all posts as #posts" do
Posts::Post.stub(:all) { [mock_post] }
get :index
assigns(:posts).should eq([mock_post])
end
end
which yields...
1) Posts::PostsController GET index assigns all posts as #posts
Failure/Error: get :index
ActionController::RoutingError:
No route matches {:controller=>"posts/posts"}
# ./spec/controllers/posts/posts_controller_spec.rb:16
I've tried all sorts of tricks in the test app's routes file... :namespace, etc, to no avail.
How do I make this work? It seems like it won't, since the engine puts the controller at /posts, yet the namespacing puts the controller at /posts/posts for the purpose of testing.
I'm assuming you're testing your engine with a dummy rails app, like the one that would be generated by enginex.
Your engine should be mounted in the dummy app:
In spec/dummy/config/routes.rb:
Dummy::Application.routes.draw do
mount Posts::Engine => '/posts-prefix'
end
My second assumption is that your engine is isolated:
In lib/posts.rb:
module Posts
class Engine < Rails::Engine
isolate_namespace Posts
end
end
I don't know if these two assumptions are really required, but that is how my own engine is structured.
The workaround is quite simple, instead of this
get :show, :id => 1
use this
get :show, {:id => 1, :use_route => :posts}
The :posts symbol should be the name of your engine and NOT the path where it is mounted.
This works because the get method parameters are passed straight to ActionDispatch::Routing::RouteSet::Generator#initialize (defined here), which in turn uses #named_route to get the correct route from Rack::Mount::RouteSet#generate (see here and here).
Plunging into the rails internals is fun, but quite time consuming, I would not do this every day ;-) .
HTH
I worked around this issue by overriding the get, post, put, and delete methods that are provided, making it so they always pass use_route as a parameter.
I used Benoit's answer as a basis for this. Thanks buddy!
module ControllerHacks
def get(action, parameters = nil, session = nil, flash = nil)
process_action(action, parameters, session, flash, "GET")
end
# Executes a request simulating POST HTTP method and set/volley the response
def post(action, parameters = nil, session = nil, flash = nil)
process_action(action, parameters, session, flash, "POST")
end
# Executes a request simulating PUT HTTP method and set/volley the response
def put(action, parameters = nil, session = nil, flash = nil)
process_action(action, parameters, session, flash, "PUT")
end
# Executes a request simulating DELETE HTTP method and set/volley the response
def delete(action, parameters = nil, session = nil, flash = nil)
process_action(action, parameters, session, flash, "DELETE")
end
private
def process_action(action, parameters = nil, session = nil, flash = nil, method = "GET")
parameters ||= {}
process(action, parameters.merge!(:use_route => :my_engine), session, flash, method)
end
end
RSpec.configure do |c|
c.include ControllerHacks, :type => :controller
end
Use the rspec-rails routes directive:
describe MyEngine::WidgetsController do
routes { MyEngine::Engine.routes }
# Specs can use the engine's routes & named URL helpers
# without any other special code.
end
– RSpec Rails 2.14 official docs.
Based on this answer I chose the following solution:
#spec/spec_helper.rb
RSpec.configure do |config|
# other code
config.before(:each) { #routes = UserManager::Engine.routes }
end
The additional benefit is, that you don't need to have the before(:each) block in every controller-spec.
Solution for a problem when you don't have or cannot use isolate_namespace:
module Posts
class Engine < Rails::Engine
end
end
In controller specs, to fix routes:
get :show, {:id => 1, :use_route => :posts_engine}
Rails adds _engine to your app routes if you don't use isolate_namespace.
I'm developing a gem for my company that provides an API for the applications we're running. We're using Rails 3.0.9 still, with latest Rspec-Rails (2.10.1). I was having a similar issue where I had defined routes like so in my Rails engine gem.
match '/companyname/api_name' => 'CompanyName/ApiName/ControllerName#apimethod'
I was getting an error like
ActionController::RoutingError:
No route matches {:controller=>"company_name/api_name/controller_name", :action=>"apimethod"}
It turns out I just needed to redefine my route in underscore case so that RSpec could match it.
match '/companyname/api_name' => 'company_name/api_name/controller_name#apimethod'
I guess Rspec controller tests use a reverse lookup based on underscore case, whereas Rails will setup and interpret the route if you define it in camelcase or underscore case.
It was already mentioned about adding routes { MyEngine::Engine.routes }, although it's possible to specify this for all controller tests:
# spec/support/test_helpers/controller_routes.rb
module TestHelpers
module ControllerRoutes
extend ActiveSupport::Concern
included do
routes { MyEngine::Engine.routes }
end
end
end
and use in rails_helper.rb:
RSpec.configure do |config|
config.include TestHelpers::ControllerRoutes, type: :controller
end