Formtastic ~> 2.0.2 and enumerated_attribute gem, Rails 3.1.1 - formtastic

I used enumerated_attribute with formtastic ~> 1.2.3 with "monkey patch" for field :as => :enum and everything worked fine.
But when I updated formtastic to 2.0.2 version appeared an error with message "Formtastic::UnknownInputError".
For more details here is patch, that was added to /initialisers/formtastic.rb:
module Formtastic #:nodoc:
class SemanticFormBuilder #:nodoc:
def enum_input(method, options)
unless options[:collection]
enum = #object.enums(method.to_sym)
choices = enum ? enum.select_options : []
options[:collection] = choices
end
if (value = #object.__send__(method.to_sym))
options[:selected] ||= value.to_s
else
options[:include_blank] ||= true
end
select_input(method, options)
end
end
end
P.S. I tried to change SemanticFormBuilder to FormBuilder (as I understood from new formtastic documentation there was such change for all custom inputs), but I was still getting error
Maybe anybody already used these gems together successfully?

They way custom fields are defined has changed completely in Formtastic 2.x
You need to subclass the internal Formtastic classes to get what you want. A select input would look something like this:
module FormtasticExtensions
class EnumeratedInput < Formtastic::Inputs::SelectInput
def collection
# programmatically build an array of options in here and return them
# they should be in this format:
# [['name', 'value'],['name2', 'value2']]
end
end
end
Include the module in the Formtastic initializer:
include FormtasticExtensions
and this will give you a field :as => :enumerated and you should be good to go. In my case (some other custom field) it selects the current option, but you may need to tweak the code for yours to work.
You could also just pass the collection in:
f.input :thing, :as => :select, :collection => your_collection, :label_method => :your_name, :value_method => :your_id

Related

ActiveRecord::AssociationTypeMismatch ruby 1.8 without using spork

I have models specs, controllers spec and request spec. When I run:
rspec spec
models spec are run first, then request and then when controller specs are run the specs for the first controller are OK, but the next fail. But when I run only the controller specs they all pass. I am with rails 3.0.9, ruby 1.8, factory_girl 2.2.0. I have
config.cache_classes = true
in test.rb and I can't change the version of ruby or factory_girl. Can someone help me?
UPDATE:
This is the error:
96) UsersController reset_password: as non-master_admin: does not reset a user's password
Failure/Error: let!(:user) { Factory(:admin_user) }
ActiveRecord::AssociationTypeMismatch:
AdminUser(#-630697398) expected, got MerchantUser(#-629918188)
# ./app/models/activity.rb:33:in `log'
# ./config/initializers/add_activity_logging.rb:8:in `_callback_after_759'
# ./spec/controllers/users_controller_spec.rb:8
in spec/controllers/users_controller_spec.rb:8:
let!(:user) { Factory(:admin_user) }
in activity.rb:33:
create(:user => user, :title => title, :changeable_id => changeable.id,
:changeable_type => changeable.class.to_s, :data => attributes)
also there is:
belongs_to :user, :class_name => 'AdminUser'
in the class AdminUser there isn't has_many activities but when I tried to add it I couldn't add it correctly I guess.
Thanks for the help
UPDATE:
AdminUser and MerchantUser are descendants of User
POSIBLE FIX
The line that gave error was actually:
admin_user = Factory(:tech_admin)
I replaced it with:
admin_user = FactoryGirl.build_stubbed(:tech_admin)
This way the file activity.rb is not reached
FINAL FIX
Apparently the problem was with Factory(:reseller). I replaced it with FactoryGirl.create(:reseller) and it everything work. Though now I am wondering and searching what is the difference between the two uses

how to tell Rails RSpec that spec is "type helper"

I wrote *simple_form* input extension that is located in app/inputs/something_input.rb
I'm trying to write RSpec for this. When I put this spec inside spec/helpers/application_helper_spec.rb everything was working without single problem.
# spec/helpers/application_helper_spec.rb
require 'spec_helper'
describe ApplicationHelper do
it do
helper.simple_form_for #foo,:method=>'get', :url=>helper.users_path do |f|
f.input :created_at, :as =>:custom_datepicker
end.should =~ /something/
end
end
Now I'm trying to move that spec to spec/inputs/something_input_spec.rb so it will be similar name path.
# spec/imputs/something_input_spec.rb
require 'spec_helper'
describe SomethingInput do
it do
helper.simple_form_for #foo,:method=>'get', :url=>helper.users_path do |f|
f.input :created_at, :as =>:custom_datepicker
end.should =~ /something/
end
end
#
#ERROR: undefined local variable or method `helper' for #<RSpec::Core::ExampleGroup
the thing I want to tell RSpec to threat this file as type helper spec, so I will have helper method availible with all the RSpec::Rails::HelperExampleGroup functionality
... how can I do that ??
I was trying to extend/include it with RSpec::Rails::HelperExampleGroup nothing seems to work
Start the describe block with the :helper type:
describe SomethingInput, :type => :helper do
... tests ...
end

rails3 routing and yaml based API, using devise and cancan

I have an application that will have an API, with a /api/v1/ namespace:
namespace :api do
namespace :v1 do
resources :gateways do
resources :mappings do
# maybe more stuff
end
end
end
end
my application uses devise and cancan.
My mappings controller down in app/controllers/api/v1/mappings_controller.rb works correctly from rspec test cases if I leave out :format=>:yaml (asking for HTML, and getting a 406).
If I ask for :yaml, devise seems to think that my test user is not allowed.
My test case is stupid simple:
describe "Agent access to mappings" do
it "gets a list of mappings that includes test_user mapping" do
#test_agent = users(:firewallagent)
sign_in(#test_agent)
get :show, {:gateway_id => 1, :id => 2} #, :format => :yaml
assert_response 200
end
end
I can't see anything in devise/warden which would be format specific, but maybe I've missed it.
The fault was that :format=>:yaml needs to go into the first hash, rather than into the second hash for get. So:
get :show, {:gateway_id => 1, :id => 2, :format => :yaml}

NoMethodError - undefined method

I'm having problems displaying data from a separate controller. I have a number of users, each with many pages. I've followed this tutorial with a few minor adjustments.
The error that keeps appearing is:
NoMethodError in SitesController#show
undefined method `page' for #<ActionDispatch::Request:0x00000102452d30>
My routes.rb is as follows:
devise_for :users
resources :users, :only => [:index, :show] do
resources :pages, :shallow => true
end
match '/' => 'sites#show', :constraints => { :subdomain => /.+/ }
root :to => "home#index"
And I have a sites controller:
class SitesController < ApplicationController
def show
#site = Site.find_by_name!(request.page)
end
end
I've also tried:
def show
#site = Site.find_by_name!(params[:site])
end
Which gives a different error.
Am totally stuck trying to figure this out!
Looking forward to your assistance.
Bob
The problem is here: request.page
The request object is of the class ActionDispatch::Request, which does not have a page method.
To track down errors like this, you can try either looking at the docs or messing around in the debugger.
Try running your controller with --debugger enabled.
If you are running Ruby 1.8, install the ruby-debug gem.
If you are running Ruby 1.9, install the ruby-debug19 gem.
Add a debugger call here:
class SitesController < ApplicationController
def show
debugger
#site = Site.find_by_name!(request.page)
end
end
Run your server with the --debugger option.
See what p request.page does. I bet it will have an "undefined method" error, just you see when you try to view that controller action.
If you do a p request.class you can find out what class the object is, and then look up the docs to see how to use it.

How do i remove the authenticity_token from rails forms

I have worked out how to disable the authenticity_token in the controller but rails still creates the field in the forms. How do i turn this off as the server i am posting the form to needs a very specific set of field names.
In rails after 3.2.x you can pass a parameter into the form generator as suggested in another answer:
form_for #invoice, :url => external_url, :authenticity_token => false do |f|
...
<% end %>
In any rails version you can disable globally in config/application.rb, as in another answer:
config.action_controller.allow_forgery_protection = false
In rails 3.0.x you can disable on a page load basis in the controller by overriding the following method. Unfortunately, there seems to be no way to do this at the form level.
protected
def protect_against_forgery?
if ...
# results in the meta tag being ommitted and no forms having authenticity token
return false
else
# default implementation based on global config
return allow_forgery_protection
end
end
To disable it across your application, you can add this line to your config/application.rb:
config.action_controller.allow_forgery_protection = false
For external urls you can turn this of per form as follows:
<%= form_for #invoice, :url => external_url, :authenticity_token => false do |f|
...
<% end %>
Source: http://apidock.com/rails/ActionView/Helpers/FormHelper/form_for