Cannot find FakeInput - ruby-on-rails-3

I am trying add a fake input to simple_form using the following suggestion (rails simple_form fields not related to the model), but it does not work for me.
This is my HAML code for adding a fake input field.
= f.input :agrees_to_terms, :as => :fake
I put the following class in app/inputs/fake_input.rb
class FakeInput < SimpleForm::Inputs::StringInput
# This method only create a basic input without reading any value from object
def input
template.text_field_tag(attribute_name, nil, input_html_options)
end
end
I get the following runtime error
No input found for fake
I have two initializers that were generated by Rails Composer: simple_form.rb and simple_form_bootstrap.rb
How can I make Rails find my FakeInput class?

I had the same issue, and a server restart resolved it.

Related

Dynamic define_method throwing error in RSpec

I am pretty sure I am missing a basic mistake here, so I am hoping another set of eyes might help. I am using Rails 3, Ruby 1.9.2 and Rspec 2.
I would like to define dynamic class methods on a model so that I can return base roles for an assignable object (such as account) as they are added to the system. For example:
BaseRole.creator_for_account
Everything works fine via the console:
ruby-1.9.2-p180 :003 > BaseRole.respond_to?(:creator_for_account)
=> true
but when I run my specs for any of class methods, I get a NoMethodError wherever I call the method in the spec. I am assuming that something about how I am dynamically declaring the methods is not jiving with RSpec but I cannot seem to figure out why.
The lib dir is autoloaded path and the methods return true for respond_to?.
# /lib/assignable_base_role.rb
module AssignableBaseRole
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
BaseRole.all.each do |base_role|
role_type = RoleType.find(base_role.role_type_id)
assignable_name = base_role.assignable_type.downcase
method = "#{role_type.name}_for_#{assignable_name}"
define_method(method) do
self.where(:role_type_id => role_type.id,
:assignable_type => assignable_name).first
end
end
end
end
Then include the Module in BaseRole
# /models/base_role.rb
class BaseRole < ActiveRecord::Base
include AssignableBaseRole
belongs_to :role
belongs_to :role_type
......
......
end
Then in my spec:
it "adds correct authority for creator role" do
create_assignment
base_role = BaseRole.creator_for_account # <== NoMethodError here
user1 = Factory.create(:user)
account.users << user1
user1.roles_for_assignable(account).should include(base_role.role)
end
Did you have another class in your project or specs with the same name, but doesn't have the dynamic methods added? I had the exact same problem as you, and renaming one of the classes fixed it.
My guess is the other class is getting loaded first
It appears you are defining these methods based on values in the database:
BaseRole.all.each do |base_role|
.....
Could it be that "creator" doesn't exist in the test database as a role type, or "account" doesn't exist as assignable_type?
Presumably you are testing this in the console for development, not test, so the data could be mismatched. Might need to set up the data in a before hook.

Writing custom validator in Rails 3

I'm trying to write a custom validator that will check for the number of words entered into a text field.
I was trying to follow the example in railscasts episode 211 - http://railscasts.com/episodes/211-validations-in-rails-3
So I made a file /lib/word_limit_validator.rb and copied in the same code from the tutorial. I know that this code doesn't count the number of words, I am just trying to use it because I know how it is supposed to behave.
class WordLimitValidator < ActiveModel::EachValidator
def validate_each(object, attribute, value)
unless value =~ /^([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
object.errors[attribute] << (options[:message] || "is not formatted properly")
end
end
end
Here's the line I used in my validation:
validates :body, :presence => true,
:word_limit => true
When I tried to load the form I got the following error:
Unknown validator: 'word_limit'
How do I get rails to recognize my validator?
System spec:
Mac OS 10.6.7
Rails 3.0.4
ruby 1.9.2p136
You could also create an app/validators directory in your rails project and put your custom validators there. This way they will automatically be loaded.
Files in lib/ aren't autoloaded anymore in Rails. So, you have a few options.
You can add lib to your autoload paths in your application.rb:
config.autoload_paths += %W( #{config.root}/lib )
You can include by adding file with something like this to config/initializers:
require File.join( Rails.root, 'lib', 'word_limit_validator')
If you only need it one place, you can just put it in the same file as your model.

Rails 3 Custom Validator Problem

I need to apply validation to a Model so that 2 integer values in the record, minimum and maximum, form an inclusive range (ex. 2 and 3 are ok, but 4 and 1 are not). From what I understand, since I need to validate 2 values against each other in the same record, I have to use ActiveModel::Validator (and not ActiveModel::EachValidator). So, I try the following:
Model (app/models/position.rb):
class Position < ActiveRecord::Base
validates_with InclusiveRangeValidator
end
Validator (app/lib/validators/inclusive_range_validator.rb):
class InclusiveRangeValidator < ActiveModel::Validator
def validate(record)
record.errors[:base] << "#{record.minimum} and #{record.maximum} do not form a valid inclusive range." unless record.minimum < record.maximum
end
end
I've read that Rails 3.0.5 doesn't automatically load the lib directory anymore, so I added this line in config/application.rb:
config.autoload_path += %W({config.root}/lib)
And then I reset the rails server so it'll take the change to config/application.rb. I run my unit tests, which tries to exercise the model to prove this validation works. I get this error:
uninitialized constant: Position::InclusiveRangeValidator (NameError)
What I think is happening is that Rails is not recognizing/finding my custom validator class, and so it assumes InclusiveRangeValidator is a constant in the class that it's referenced in. But, I thought the change I made to config/application.rb would put my validator in the load path so that it would be available.
I've gone through the other posts on StackOverflow and didn't come up with a solution, and I've read the API docs on validators, to no avail. I've got to be doing something simple and stupid, but I can't see what the issue is. Any help?
EDIT:
After more searching, I discovered that I don't need a custom validator at all, as I can accomplish the same goal with this:
validates :minimum, :numericality => {:greater_than_or_equal_to => 0 }
validates :maximum, :numericality => {:greater_than => :minimum }
However, the question still remains as to why Rails can't locate the custom validation class.
Once, I changed the line in application.rb to:
config.autoload_paths += %W[#{config.root}/lib/validators/]
Rails was able to find the right path to load my custom validator. I made the mistake of assuming Rails would automatically recurse the directory structure, this is evidently not the case.

Rails 3 namespacing requires model to be defined twice?

I'm pulling my hair out trying to understand namespacing in Rails 3. I've tried following a few different tutorials, and the only way I can get my models to work is if I define my model in both the base directory and my namespace directory.
If I only define the model in the namespace directory it expects it to define both Model and Namespace::Model, as below:
LoadError (Expected .../app/models/plugins/chat.rb to define Chat):
or
LoadError (Expected .../app/models/plugins/chat.rb to define Plugins::Chat):
I'm sure I'm missing something obvious, but I could really use a pointer in the right direction.
Here are the relevant excerpts.
/models/plugins/chat.rb
class Plugins::Chat
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
...
end
/controllers/plugins/chats_controller.rb
class Plugins::ChatsController < Plugins::ApplicationController
load_and_authorize_resource
...
end
/config/routes.rb
namespace :plugins do
resources :chats
end
/config/application.rb
config.autoload_paths += Dir["#{config.root}/app/models/**/"]
Edit
This is some kind of bad interaction with CanCan, the gem we're using for permissions. The line load_and_authorize_resource is somehow at fault. Will keep digging...
I noticed a reference to load_and_authorize_resource in your controller. This method is used by the CanCan gem to create an instance of your model and then test if the user has access to it. If you are using a namespaced model you will need to specify the class:
class Plugins::ChatsController < Plugins::ApplicationController
load_and_authorize_resource :class "Plugins::Chat"
...
end
It sounds like at some point you're referencing the Chat constant \by itself before it's loaded. Rails then tries to find that by looking at models/chat.rb, can't find it, and complains. Check your constant usage (the backtrace should tell you where it's being invoked from), and clean it up, and Rails should be less complain-y.

How to slugify a parent model with fields from a child model?

I'd like to slugify the urls for a model in Rails 3, using Mongoid. The problem is the fields I want to use in the slug are located in a child model. I am using mongoid-slug gem to find a solution to this and my attempt so far is this:
class Building
references_one :address
def to_param
address.to_param
end
end
class Address
referenced_in :building
field :houseno
field :street
slug :houseno, :street
end
While this allows me to form the correct url by calling building_path(building), the page does not contain the correct values. Error message complains that object id is incorrect, and I'm not sure how to get Rails to listen and find the record by to_param.
For the curious, here is how I solved my own problem. I realized that I needed to use change the show action from
#building = Building.find(params[:id])
to
#building = Address.find_by_slug(params[:id]).building
And voila! It works.