I have created following class just to have validation and custom validation for parameters for my ajax message:
class Message
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :attributes
validates_inclusion_of :temp_inside, :in => 0..30
validates_inclusion_of :temp_outside, :in => -50..20
validates_presence_of :isol
validates_inclusion_of :height, :length, :width, :in => 1..500
validate :temp_outside_cannot_be_greater_than_temp_inside
def temp_outside_cannot_be_greater_than_temp_inside
errors.add(:temp_outside, "can't be greater than total value") if
temp_outside > temp_inside
end
def initialize(attributes = {})
#attributes = attributes
end
def read_attribute_for_validation(key)
#attributes[key]
end
def persisted?
false
end
end
and getting following error inside "temp_outside_cannot_be_greater_than_temp_inside"
NoMethodError (undefined method `>' for :temp_outside:Symbol):
any idea?
You need to check the value of temp_outside, as it seems to be a symbol in this case, not a number
Related
I have created class using Active Model,it is working as expected ,but am having few requirements
1) I want to use all method for that class.
2) Same way i want to use some query methods like where method for that class.
3) I want to create ActiveRecord::Relation so that i can do method chaining.
See my class:
require 'active_model'
require 'active_record'
class Message
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :name, :email, :content
validates_presence_of :name
validates_length_of :content, :maximum => 500
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end
def persisted?
false
end
end
m = Message.new(:email => "test",:name => "test")
puts m.name #=> test
puts m.class #=> Message
puts m.valid? #=> true
Message.all
Message.where(:name => "test")
some more methods:
where
limit
having
group
select
order
uniq
Could you please help me to achieve this or give some guide lines.
Keep getting Syntax Error in Controller due to custom validations. Wondering how exactly I would implement custom validations within Refinery.
Error
/Users/bklane/Documents/code/codery/syrsp_two/vendor/extensions/quotes/app/models/refinery/quotes/quote.rb:18: syntax error, unexpected tIDENTIFIER, expecting keyword_end
validate :in_future?
quote.rb
module Refinery
module Quotes
class Quote < Refinery::Core::BaseModel
# require 'postmaster'
self.table_name = 'refinery_quotes'
attr_accessible :company, :due_by, :email, :f_name, :l_name, :phone, :pickup, :ship_city, :ship_line_1, :ship_line_2, :ship_contact, :ship_company, :ship_state, :ship_zip, :email_sent, :note, :position
alias_attribute :message, :note
alias_attribute :name, :company
# Add some validation here if you want to validate the user's input
# We have validated the first string field for you.
validates_presence_of :email, :phone, :f_name, :l_name
validates_inclusion_of :pickup, in: [true, false]
validates_format_of :email, :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i\
# validations not working below
validate :in_future?
# validate :parse_phone
# validate :validate_address
def in_future?
errors.add(:due_by, "Order cannot be due in the past") unless (due_by.present? && (1 === (due_by <=> Date.today)))
end
end
end
end
The trailing \ in your regular expression on line 17 is the cause of the syntax error.
There is a contact page, which offers to enter name, telephone, email and message, after that it sends to an administrator's email. There is no reason to store message in DB.
Question. How to:
Use Rails validations in controller, not using model at all, OR
Use validations in model, but without any DB relations
UPD:
Model:
class ContactPageMessage
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :name, :telephone, :email, :message
validates :name, :telephone, :email, :message, presence: true
validates :email, email_format: { :message => "Неверный формат E-mail адреса"}
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end
def persisted?
false
end
end
controller:
def sendmessage
cpm = ContactPageMessage.new()
if cpm.valid?
#settings = Setting.first
if !#settings
redirect_to contacts_path, :alert => "Fail"
end
if ContactPageMessage.received(params).deliver
redirect_to contacts_path, :notice => "Success"
else
redirect_to contacts_path, :alert => "Fail"
end
else
redirect_to contacts_path, :alert => "Fail"
end
end
end
you should use model without inheriting from ActiveRecord::Base class.
class ContactPageMessage
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :whatever
validates :whatever, :presence => true
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end
def persisted?
false
end
end
Through this you will able to initialize new object and able to call validations on that object.
I think you have a different class name with same name, in your controller code, I can see this :
if ContactPageMessage.received(params).deliver
redirect_to contacts_path, :notice => "Success"
else
if this is your mailer class change its name to ContactPageMessageMailer. you will no loger get that error.
Hope it will help. Thanks
I would still advice you to use model, rails models doesn't have to inherit from ActiveRecord::Base.
For example:
class Contact
include ActiveModel::Validations
attr_accessor :name, :telephone, :email, :message
validates_presence_of :name, :telephone, :email, :message
validates_format_of :email, with: EMAIL_REGEXP
end
and you can use it in your controller with:
contact = Contact.new
# ...
if contact.valid?
# do something
else
# do something else
end
In your model you can add the below which will just set getter and setter method for message and you can have validation on message without having a column in the db
attr_accessor :message
validates :message, presence: true
How do I get ActiveRecord attributes method functionality? I have this class:
class PurchaseForm
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :name,
:surname,
:email
validates_presence_of :name
validates_format_of :email, :with => /^[-a-z0-9_+\.]+\#([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
def initialize(attributes = {}, shop_name)
if not attributes.nil?
attributes.each do |name, value|
send("#{name}=", value)
end
end
def persisted?
false
end
end
What I need to do, to have an attributes method to list all names and values from PurchaseForm object?
Here is the refactored variant:
class PurchaseForm
include ActiveModel::Model
def self.attributes
[:name, :surname, :email]
end
attr_accessor *self.attributes
# your validations
def to_hash
self.class.attributes.inject({}) do |hash, key|
hash.merge({ key => self.send(key) })
end
end
end
Now you can easily work with this class:
irb(main):001:0> a = PurchaseForm.new({ name: 'Name' })
=> #<PurchaseForm:0x00000002606b50 #name="Name">
irb(main):002:0> a.to_hash
=> {:name=>"Name", :surname=>nil, :email=>nil}
irb(main):003:0> a.email = 'user#example.com'
=> "user#example.com"
irb(main):004:0> a
=> #<PurchaseForm:0x00000002606b50 #name="Name", #email="user#example.com">
irb(main):005:0> a.to_hash
=> {:name=>"Name", :surname=>nil, :email=>"user#example.com"}
Even more, if you want to make this behaviour reusable, consider extraction of .attributes and #to_hash methods into separate module:
module AttributesHash
extend ActiveSupport::Concern
class_methods do
def attr_accessor(*args)
#attributes = args
super(*args)
end
def attributes
#attributes
end
end
included do
def to_hash
self.class.attributes.inject({}) do |hash, key|
hash.merge({ key => self.send(key) })
end
end
end
end
Now, just include it to your model and you're done:
class PurchaseForm
include ActiveModel::Model
include AttributesHash
attr_accessor :name, :surname, :email
# your validations
end
#instance_values could do the job:
class PurchaseForm
attr_accessor :name, :email
def attributes
instance_values
end
end
Output sample:
purchase.attributes #=> {"name"=>"John", "email"=>"john#example.com"}
I've managed to solve problem with this code:
class PurchaseForm
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :attributes,
:name,
:surname,
:email
validates_presence_of :name
validates_format_of :email, :with => /^[-a-z0-9_+\.]+\#([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
def initialize(attributes = {})
#attributes = attributes
end
def persisted?
false
end
end
Let's try this
self.as_json
=> {:name=>"Name", :surname=>nil, :email=>"user#example.com"}
would it not be better to use
include ActiveModel::Serialization
def attributes
JSON.parse(self.to_json)
end
After searching for a tableless model example I came across this code which seems to be the general consensus on how to create one.
class Item < ActiveRecord::Base
class_inheritable_accessor :columns
self.columns = []
def self.column(name, sql_type = nil, default = nil, null = true)
columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
end
def all
return []
end
column :recommendable_type, :string
#Other columns, validations and relations etc...
end
However I would also like it to function, as a model does, representing a collection of object, so that I can do Item.all.
The plan is to populate Items with files and each Item's properties will be extracted from the files.
However currently if I do Item.all I get a
Mysql2::Error Table 'test_dev.items' doesn't exist...
error.
I found an example at http://railscasts.com/episodes/219-active-model where I can use model features and then override static methods like all (should have thought of this before).
class Item
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :name, :email, :content
validates_presence_of :name
validates_format_of :email, :with => /^[-a-z0-9_+\.]+\#([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
validates_length_of :content, :maximum => 500
class << self
def all
return []
end
end
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end
def persisted?
false
end
end
Or you could do it like this (Edge Rails only):
class Item
include ActiveModel::Model
attr_accessor :name, :email, :content
validates_presence_of :name
validates_format_of :email, :with => /^[-a-z0-9_+\.]+\#([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
validates_length_of :content, :maximum => 500
end
By simply including ActiveModel::Model you get all the other modules included for you. It makes for a cleaner and more explicit representation (as in this is an ActiveModel)