I have model with virtual attributes, for use in simple_form:
class Sms < ActiveRecord::Base
attr_accessor :delayed_send, :send_time_date, :send_time_time
I have form for /smses/new:
= simple_form_for([:admin, resource]) do |f|
...
.clear
.field.grid_3
= f.input :delayed_send, :as => :boolean, :label => "Отложенная отправка на:"
.clear
.field.grid_3
= f.input :send_time_date, :as => :string, :input_html => { :class => 'date_picker' }, :disabled => true, :label => "Дату:"
.clear
.field.grid_1
= f.input :send_time_time, :as => :string, :disabled => true, :label => "Время:", :input_html => { :value => (Time.now + 1.minute).strftime("%H:%M") }
.clear
.actions.grid_3
= f.submit "Отправить"
And i wanna validate all that virtual attributes inside my SmsesController, in create action, and if it invalid - show error. But that doesn't work:
class Admin::SmsesController < Admin::InheritedResources
def create
#sms.errors.add(:send_time, "Incorrect") if composed_send_time_invalid?
super
end
How should i add my custom errors, if i using inherited_resources?
If there's not a specific reason you're validating in the controller, the validation should be in the model:
class Sms < ActiveRecord::Base
#two ways you can validate:
#1.use a custom validation routine
validate :my_validation
def my_validation
errors.add(:send_time, "Incorrect") if composed_send_time_invalid?
end
#OR 2. validate the attribute with the condition tested in a proc.
validates :send_time, :message=>"Incorrect", :if=>Proc.new{|s| s.composed_send_time_invalid?}
end
In the controller, a save (or call to object.valid?) will trigger these validations to run. You can then handle the response in your controller to re-render the action if warranted.
Related
I have a variable "time_to_succeed" which represents the time for a team to succeed in a mission. This variable will be added/edited in activeadmin. I need minutes and seconds as the game duration is under an hour. Problem is, activeadmin allows me to add/edit only hours and minutes of this variable. Adding ", :as => :time_picker" did not solve my issue.
Maybe the datatype is not correct but I could not find one more suitable than time.
A bit of code might be helpful :
class PurchaseOrder < ActiveRecord::Base
scope :today, -> { where("booking_date >= ?", Date.today).where("booking_date < ?", Date.tomorrow) }
scope :tomorrow, -> { where("booking_date >= ?", Date.tomorrow).where("booking_date < ?", Date.tomorrow+1) }
before_save :default_values
def default_values
self.price_ttc = self.paid_by_card.to_f + self.paid_in_cash.to_f + self.paid_by_check.to_f
self.price_ht = self.price_ttc / 1.2
end
has_attached_file :team_picture, styles: { small: "64x64>", medium: "150x150>", large: "300x300>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :team_picture, :content_type => ["image/jpg", "image/jpeg", "image/png"]
just_define_datetime_picker :booking_date
end
ActiveAdmin.register PurchaseOrder do
permit_params :first_name, :last_name, :email, :phone, :booking_date,
:time_to_succeed, :number_of_players, :team_name, :paid_by_card, :paid_in_cash, :paid_by_check, :level, :status, :team_picture,
:booking_date_date, :booking_date_time_hour, :booking_date_time_minute, :scenario_id
scope :today
scope :tomorrow
scope :all
index do
column "Prénom", :first_name
column "Nom", :last_name
column :email
column "Réservation", :booking_date
column :number_of_players
column :time_to_succeed
actions
end
show do
h3 purchase_order.last_name
attributes_table do
row :first_name
row :last_name
row :email
row :phone
row :booking_date
row :scenario_id
row :time_to_succeed
row :number_of_players
row :price_ttc
row :price_ht
row :status
row :created_at
row :paid_by_card
row :paid_in_cash
row :paid_by_check
row :level
row :team_name
row :team_picture do
image_tag purchase_order.team_picture.url(:medium)
end
end
active_admin_comments
end
form :html => { :enctype => "multipart/form-data" } do |f|
f.inputs "Details" do
f.input :first_name
f.input :last_name
f.input :email
f.input :phone
f.input :booking_date, :as => :just_datetime_picker
f.input :scenario_id, :label => 'Scenario', :as => :select, :collection => Scenario.all.map{|u| ["#{u.name}", u.id]}
f.input :time_to_succeed, :as => :time_picker
f.input :number_of_players
f.input :status
f.input :paid_by_card
f.input :paid_in_cash
f.input :paid_by_check
f.input :level, :label => 'Niveau', :as => :select, :collection => ["détente", "expert"]
f.input :team_name
f.input :team_picture, :as => :file, :hint => f.object.team_picture.present? \
? image_tag(f.object.team_picture.url(:small))
: content_tag(:span, "no image")
end
f.actions
end
end
Couldn't find anything on Google. Any help would be greatly appreciated.
Thanks
I have a simple_field and I pass an object to a partial file. I do this in the partial :
<%= f.input :address,
:as => :hidden,
:label => "Address :",
:input_html=>{
:required => false,
:class => "address"
} %>
I want to use :as => hidden depending on a certain condition. I mean the field should be hidden if a condition is true. Is that possible to do?
You could make your options hash separately and then add the hidden parameter if necessary
options = {
:label => "Address :",
:input_html=>{
:required => false,
:class => "address"
}
}
if condition_is_true? then options[:as] = "hidden" end
<%= f.input :address, options %>
I'm trying to make a create product page in rails. This includes adding multiple images and text fields. I have one model for products and one for photos. I'm using the paperclip gem for photo upload. But I get this error when I try to create a new product. P.S. I use HAML.
NoMethodError in Products#new
Showing /some_app/app/views/products/new.html.haml where line #33 raised:
undefined method `photo' for :product:Symbol
Extracted source (around line #33):
33: = f.file_field :product.photo, multiple: 'multiple'
products/new.html.haml
%h1
create item
= form_for #product, :html => { :multipart => true } do |f|
- if #product.errors.any?
.error_messages
%h2 Form is invalid
%ul
- for message in #product.errors.full_messages
%li
= message
%p
= f.label :name
= f.text_field :name
%p
= f.file_field :product.photo, multiple: 'multiple'
%p.button
Products controller
class ProductsController < ApplicationController
def new
#product = Product.new
#photo = Photo.new
end
def create
#photo = current_user.photos.build(params[:photo])
5.times { #product.photos.build }
#product = current_user.products.build(params[:product])
if #product.save
render "show", :notice => "Sale created!"
else
render "new", :notice => "Somehting went wrong!"
end
end
Product model
class Product < ActiveRecord::Base
attr_accessible :description, :name, :price, :condition, :ship_method, :ship_price, :quantity, :photo
has_attached_file :photo
belongs_to :user
validates :user_id, presence: true
validates :name, presence: true, length: { minimum: 5 }
end
Photo model
class Photo < ActiveRecord::Base
attr_accessible :product_id
belongs_to :product
has_attached_file :image,
:styles => {
:thumb=> "100x100#",
:small => "300x300>",
:large => "600x600>"
}
end
The syntax isn't correct - change:
= f.file_field :product.photo, multiple: 'multiple'
To:
= f.file_field :photo, multiple: 'multiple'
In controller i have such code:
#bank_exchangers = ExchangerList.find(:all, :conditions => {:bank_id => params[:id]})
#currency_list = CurrencyList.all
#currencies = []
#currency_list.each do |c|
#currencies << CurrencyValue.find(:all, :conditions => {:currency_list_id => c.id}, :order => :updated_at)
end
#currencies.flatten!
and i have such models:
class CurrencyList < ActiveRecord::Base
attr_accessible :code, :country, :name
has_many :currency_values
end
class CurrencyValue < ActiveRecord::Base
attr_accessible :currency_list_id, :direction_of_exchange_id, :value
belongs_to :currency_list
belongs_to :exchanger_list
end
class ExchangerList < ActiveRecord::Base
attr_accessible :address, :bank_id, :exchanger_type_id, :latitude, :location_id, :longitude, :name
has_many :currency_values
end
i need to display for each ExchangerList it's CurrencyValue with some conditions, as i provided below... But main trouble is with rabl output:
i have such code:
collection #bank_exchangers, :root => "bank_exchangers", :object_root => false
attributes :id, :name, :address, :location_id, :latitude, :longitude, :exchanger_type_id
child #currencies do
attribute :value
end
as you can see, here for each #bank_exchangers i create node with it's #currencies... But i need to display node only for this #bank_exchangers iterator, if i would write in controller i would write something like:
#currencies << CurrencyValue.find(:all, :conditions => {:currency_list_id => c.id, :exchanger_list_id => param}, :order => :updated_at)
How to set something like this in view?
Becouse now my output is like:
{"bank_exchangers":[{"id":3,"name":"Банк *** ЦБУ №1","address":"г. Минск, ул. Московская, 13","location_id":8,"latitude":null,"longitude":null,"exchanger_type_id":1,"location_name":"Минск","exchanger_type_name":"normal","currency_values":[{"currency_value":{"value":8620.0}},{"currency_value":{"value":8620.0}},{"currency_value":{"value":8700.0}},{"currency_value":{"value":8700.0}},{"currency_value":{"value":8620.0}},{"currency_value":{"value":8700.0}},{"currency_value":{"value":11500.0}},{"currency_value":{"value":11100.0}}]},{"id":4,"name":"Банк ***","address":"г. Минск, Мясникова, 32","location_id":8,"latitude":null,"longitude":null,"exchanger_type_id":1,"location_name":"Минск","exchanger_type_name":"normal","currency_values":[{"currency_value":{"value":8620.0}},{"currency_value":{"value":8620.0}},{"currency_value":{"value":8700.0}},{"currency_value":{"value":8700.0}},{"currency_value":{"value":8620.0}},{"currency_value":{"value":8700.0}},{"currency_value":{"value":11500.0}},{"currency_value":{"value":11100.0}}]}]}
as you can see, for each bank_exchangers i create node with all currency_values data, but i need to put for each bank_exchangers in node only currency_values for this bank_exchangers parent....
How could i do this?
Sorry if something is not clear... i'm new...
Just how to set for my child #currencies in view some condition?
You can take advantage of the relation between ExchangerList and CurrencyValues:
child :currency_values do
attribute :value
end
If you have conditions, you can include these using a lambda:
if => lambda { |child| child.something? })
child(:currency_values, if => lambda { |currency_value| currency_value.something? }) do
attribute :value
end
You may also want to define a view for just the one ExchangerList object (i.e. show):
object #bank_exchanger, :object_root => false
attributes :id, :name, :address, :location_id, :latitude, :longitude, :exchanger_type_id
child(:currency_values, if => lambda { |currency_value| currency_value.something? }) do
attribute :value
end
Then simply have the collection extend this:
collection #bank_exchangers, :root => "bank_exchangers", :object_root => false
extends 'bank_exchangers/show'
Alternatively, if you add a 'currencies' method to to the ExchangerList model, you can call the method directly as an attribute via RABL. Some test code I wrote:
def test
test_array = []
1.upto(3) do |i|
test_array << {qty: i, px: 2*i}
end
return test_array
end
You can then simply call this as an attribute:
object #object
attribute :test
This results in the following JSON, which I believe is similar to the format you are trying to achieve:
test: [
{
qty: 1,
px: 2
},
{
qty: 2,
px: 4
},
{
qty: 3,
px: 6
}
],
I have a form on index.html.erb (User views):
<%= form_tag( '', :method => :get ) do %>
<% #company = Position.all.map { |p| [ p.company, p.company ] } %>
<%= select_tag "company", options_for_select((#company), params[:position_id]), { :include_blank => true, :reject_if => #company.blank? } %>
<% #industry = Position.all.map { |p| [ p.industry, p.industry ] } %>
<%= select_tag "industry", options_for_select((#industry), params[:position_id]), { :include_blank => true, :reject_if => #industry.blank? } %>
<%= submit_tag 'Filter', class: 'btn btn-large btn-primary' %>
<% end %>
and a controller (User controller):
def index
if params[:company] && params[:industry]
#users = User.companies(params[:company]).industries(params[:industry])
elsif params[:company]
#users = User.companies(params[:company])
elsif params[:industry]
#users = User.companies(params[:industry])
else
#users = User.all
end
end
A User has many companies and industries through positions:
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation, :first_name, :last_name, :position_ids
has_many :positions
has_many :companies, :through => :positions
has_many :industries, :through => :positions
has_one :current_position, :class_name => "Position", :conditions => { :is_current => true }
scope :companies, lambda { |*company| {:include => :positions, :conditions => ["positions.company = ?", company]} }
scope :industries, lambda { |*industry| {:include => :positions, :conditions => ["positions.industry = ?", industry]} }
end
Despite the if statement in my user controller, I cannot get my view to ignore blank entries in either the company or industry field. For instance, a blank company and "Internet" industry filter returns this url:
...users?utf8=%E2%9C%93&company=&industry=Internet&commit=Filter
how do I modify my code to ignore a blank company field so that the url excludes 'company=&' entirely? In this case, I get the returned results that I want:
...users?utf8=%E2%9C%93&industry=Internet&commit=Filter
thanks!
What you need to do is check to see if the parameters are blank.
if !params[:company].blank? && !params[:industry].blank?
#users = User.companies(params[:company]).industries(params[:industry])
elsif !params[:company].blank? && params[:industry].blank?
#users = User.companies(params[:company])
elsif !params[:industry].blank? && params[:company].blank?
#users = User.companies(params[:industry])
else
#users = User.all
end
When you submit the form, the variables are being set. Just that, they have blank values. So you need to check if they are blank instead of whether they exist.