Ruby on Rails Date Field Validation - ruby-on-rails-3

I'm working on this project for a class and one of the requirements is "Validation on the date field type".
For example, I did:
rails g scaffold Tasks id:primary_key description:string due:date
What would I add to the model so I can validate the date?
I've tried multiple different "solutions" and nothing seems to be working.

In your model, you can define a custom method to handle your validations.
class Task < ActiveRecord::Base
validate :check_due_date
def check_due_date
# You can now check the "due" field here. For example, if you only want to allow due
# dates today and later:
if due < Date.today
errors.add(:due, "can only be today or later.")
end
end
end

You could use the simple "validates timeliness" plugin: https://github.com/adzap/validates_timeliness/
Then use the following syntax:
class Task < ActiveRecord::Base
validates_date :due
end
Unless plugins aren't allowed, in which case the other answer (creating your own validator) would be more suitable.

Related

Single Table Inheritance and 'type' value for namespaced classes

While working on Rails 2.3.18 to Rails 3.2.x migration I am facing name issue in type column
Here is the relation that is defined.
app/models/reservation.rb
class Reservation
end
class Reservation::Guest < Reservation
end
class Reservation::Event < Reservation
end
While saving Reservation::Guest Or Reservation::Event instance, the type value being saved is Reservation::Guest and Reservation::Event in Rails 3. But in Rails 2 it saves without namespace i.e., Guest or Event.
It requires lots of efforts to migrate existing data and change all the places which expects type without namespace.
Would it be possible to save type without namespace and rest work without making lots of modification across the application?
Take a look at sti_name and find_sti_class. (The methods responsible for setting and getting the sti_name)
You can customize them as follows:
class Reservation
def self.find_sti_class(type_name)
type_name = self.name
super
end
end
class Reservation::Guest < Reservation
def self.sti_name
"Guest"
end
end
class Reservation::Event < Reservation
def self.sti_name
"Event"
end
end
I know it's an old question, but maybe someone will use it.
Expanding on the answer by mohameddiaa27, the easiest way to get rid of namespace is to declare store_full_sti_class, since it's used by sti_name.
class Reservation
# don't include namespace in type column
def self.store_full_sti_class
false
end
end

New to Rails 4 Testing - Need help getting started (rSpec and Devise)

I'm relatively new to testing and very new to Rails 4 and rSpec. I am trying to test a controller that uses Devise for authentication and I am stuck. All of the examples I can find are for Rails 3.
I'm using Rails 4.0.3, Devise 3.2.3, rSpec 2.14.1 and FactoryGirl 4.4.0.
class LessonPlansController < ApplicationController
before_action :authenticate_user!
# GET /lesson_plans
def index
#lesson_plans = current_user.lesson_plans.to_a
end
.
.
.
private
# Use callbacks to share common setup or constraints between actions.
def set_lesson_plan
#lesson_plan = LessonPlan.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def lesson_plan_params
params[:lesson_plan]
end
def lesson_plan_params
params.require(:lesson_plan).permit(:title, :synopsis)
end
end
Here are my factory definitions: (Maybe I don't need to define user_id in the lesson_plan factory?)
FactoryGirl.define do
factory :user do
sequence( :username ) { |n| "user#{n}" }
sequence( :email ) { |n| "foo#{n}#example.com" }
password 'foobarbaz'
password_confirmation 'foobarbaz'
created_at Time.now
updated_at Time.now
end
end
FactoryGirl.define do
factory :lesson_plan do
user_id 1
title "The French Revolution"
synopsis "Background and events leading up to the French Revolution"
end
end
And the test part is where I get stuck.
describe LessonPlansController do
let(:valid_attributes) { { } }
let(:valid_session) { {} }
# describe "GET index" do
it "assigns all lesson_plans as #lesson_plans" do
user=FactoryGirl.create(:user)
sign_in user
lesson_plan = LessonPlan.create! valid_attributes
get :index, {}, valid_session
assigns(:lesson_plans).should eq([lesson_plan])
end
end
I'm not sure what to put in valid_attributes and valid_session (or if I even need them). The test will get as far as signing in the user, but will fail on creation of the lesson_plan. Admittedly this is the default/generated test for rSpec, but I am not sure how to proceed.
Examples I have seen use a before block to set up the user. I haven't been able to find anything on the Devise wiki page covering how to write basic rSpec tests for a controller that requires the user to be logged in. Any pointers would be greatly appreciated!
"I'm not sure what to put in valid_attributes and valid_session (or if I even need them)."
Well that depends what you're testing for.. Say you're testing validations & want to ensure that a record not be created if x column is set to null... then you could try to specifically create a record with invalid attributes (e.g. column: nil) and expect the result to not return true; maybe you want to ensure that it IS created with valid attributes.
You can btw, use `attributes_for(:factory_name)`` since you're using FactoryGirl. And no you don't necessarily need to specify the user's id in your lesson plan factory; unless you always want it to reference user 1. You can simply reference user with no value. Check out http://everydayrails.com/2012/03/12/testing-series-intro.html and especially parts 3-5 for an introduction to testing with RSPec.. I found this a pretty easy to follow guide when I was getting started.

Rspec, FactoryGirl unable to find ActiveRecord method

I am trying to learn Rspec in a very simple CRUD Rails 3.2.8 app. I'm following the general pattern of Michael Hartl's examples and have been moderately successful with cucumber for the outside in portion. Now I want to test a Twilio SMS feature and cannot seem to get to first base, mostly because I'm not asking the right questions, so I expect to be corrected here and get back on track.
My app has two models, commodity and price and they interact with each other in my cucumber tests, so it appears. I'm aware, like in cucumber, I need an object to start to test its interactions. In my prices controller, I see that I can get the commodity's prices with the below in my prices#create method:
#price = #commodity.prices.build(params[:price])
I ultimately want to generate a factory that will have many prices for a given commodity. But I want to get to base first. Following thoughtbot's examples on their Readme I'm attempting the following in rails console:
FactoryGirl.create(:commodity) do |price|
Commodity.prices.build(attributes_for(:price))
end
The result is: NoMethodError: undefined method `prices' for #
Hmm, I must not be understanding either Rspec or Factory Girl. Here is my basic factories.rb:
FactoryGirl.define do
factory :commodity do
name "corn"
end
sequence :price do |n|
price
date { Time.now }
end
end
Here are my two models:
class Commodity < ActiveRecord::Base
attr_accessible :description, :name
has_many :prices
end
MOST_RECENT = 5
class Price < ActiveRecord::Base
attr_accessible :buyer, :date, :price, :quality, :commodity_id
scope :most_recent, lambda { order("id desc").limit(MOST_RECENT) }
belongs_to :commodity
end
My attempt to understand this is to do it simply in Rails console but the error also appears when I run rspec as well. But why would FactoryGirl, or Rspec, not seem to use the prices method I get with Active Record? Clearly, I'm not understanding something or I would have found the answer on Stack, thanx, sam
In your FactoryGirl.create there are a couple problems. First, the block argument should be commodity, not price. create passes the created object into the block. Second, you're trying to run prices on the Commodity class. In your object relationship, prices is an accessor associated with a specific instance. There is no Commodity#prices method, but any given instance of Commodity will have prices. You can probably use build like that, but I think the canonical way is to use the shift operator to add a Price.
Putting this together gets you:
FactoryGirl.create(:commodity) do |commodity|
commodity.prices << FactoryGirl.create(:price, commodity: commodity)
end
I'm not sure what you're doing with the sequence in your Commodity factory definition. If you're trying to make sure that Commodities are created with Prices by default (without adding them as above), check out some of the tips at http://icelab.com.au/articles/factorygirl-and-has-many-associations/.

What's a reliable why to create a custom id for an associated item in rails

I have a nested resource like this
resources :projects do
resources :tasks
end
The tasks have a field named number. Whenever I create a task I would like to give it a squential number within the parent project.
This is my model class
class Task < ActiveRecord :: Base
belongs_to :project
validate_presence_of :title
before_create :generate_number
private
def generate_number
if project.tasks.nil? || project.tasks.count < 1
self.number = 1
else
self.number = list.topics.count+1
end
end
end
I am not sure about certain things:
Does this logic belongs in my Task Model or in my Project model or in a seperate class/module?
What is the best before filter. (before_create, before_validation, validation)?
Because there are many ways how to create a task. With a list, in a list, alone and then attach it to a list...
And which filter would work in my tests so that I could setup some Fakes for example with factory girl... Because right now FactoryGirl does not always executes generate number...
This is my factory
FactoryGirl.define do
factory :project do
name "Hello world"
end
trait :with_tasks do
ignore do
number_of_tasks 3
end
after :create do |project,evaluator|
#project.Factory.create_list :taks, evaluator.number_of_tasks, :project => project
end
end
end
What would be the best. reliable way to generate a sequential custom taks number depending on the project which works in my specs as well as in production?
Any best practise tips would be appreciated.
I would keep the before_create callback in the Task model, which would call the generate_number function. This should work in Factory girl where it would add the number if you use Factory.create, but not when you use Factory.build.

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.