I've got a problem with selecting enum value in form
here is a form
=form_for #ticket , remote: true do |f|
.errors
p
= f.label :name, class: 'label_hidden'
= f.text_field :name, placeholder:'Input your name', class:'form-control'
p
= f.label :email, class: 'label_hidden'
= f.email_field :email, placeholder:'Input your email', class:'form-control'
p
= f.label :department, class: 'label_hidden'
= f.select :department, Ticket.departments.keys , class:'form-control'
p
= f.submit 'Submit', class:'btn btn-default custom'
In my db I have a field department that is string type, also in a model I have
class Ticket < ActiveRecord::Base
enum department: [:issue, :qa, :promotion]
validates :name, :email, :subject, :body, :department, presence: true
end
When i send this form - in params everything is ok( the department param is there), also I have permitted this param in controller. Still I recieve "department can't be blank". Where I am wrong?
I suppose that you receive enum as a String, so you should convert it with setter method:
def department=(val)
self[:department] = val.to_sym
end
Related
So basically I tried to create a record in a parent model for few hours. I'm clearly missing something here. My goal is to create a bill in the Bills table and, with basic guest info in the same form, create another record in the Guests table. View my code down below (sorry if the format is not adequate, it's my first post on stackoverflow)
bill.rb
class Bill < ApplicationRecord
belongs_to :guest, inverse_of: :bills
accepts_nested_attributes_for :guest
guest.rb
class Guest < ApplicationRecord
has_many :bills, inverse_of: :guest
bills_controller.rb
def new
#bill = Bill.new
#bill.build_guest
...
def create
#bill = Bill.new(bill_params)
if #bill.save
...
def bill_params
params.require(:bill).permit(:special_req, guest_attributes: [:first_name, :last_name, :email])
_form.html.haml
=form_with(model: [:admin, #bill], local: true) do |form|
.form-group.row
.col-3
= form.label :room_id, class: "col-form-label text-dark"
.col-9
= form.collection_select :room_id, #availabilities, :id, :door_no, class: "col-form-label text-dark"
= form.fields_for :guests do |guest_form|
.form-group.row
.col-3
= guest_form.label :first_name, class: "col-form-label text-dark"
.col-9
= guest_form.text_field :first_name, class: "form-control rounded", placeholder: "Tom"
.form-group.row
.col-3
= guest_form.label :last_name, class: "col-form-label text-dark"
.col-9
= guest_form.text_field :last_name, class: "form-control rounded", placeholder: "Jedusor"
.form-group.row.margin-bottom
.col-3
= guest_form.label :email, class: "col-form-label text-dark"
.col-9
= guest_form.text_field :email, class: "form-control rounded", placeholder: "nagano#inn.com"
.form-group.row.align-items-center
.col-6
= link_to "[ Cancel operation ]", admin_bills_path, class: "text-info"
.col-6.text-right
= form.submit "Send", class: "btn btn-outline-success btn-lg"
A guest can have multiple bills, but a bill can only have one guest. Account registration is not a question for now, it's just there to serve some record purposes. This is just an exercise, so there is no real world deployment. Still, I need to go through that step.
The form view using form.fields_for :guests do |guest_form| looks correct.
Pretty sure you need to add :id in guest_attributes: [:first_name, :last_name, :email]
For Example:
params.require(:bill).permit(:special_req, guest_attributes: [:id, :first_name, :last_name, :email])
I have problem. I'm trying to get an email member from wallet_id which that relation not direct to member instead to investor account first like the sample model below.
member.rb
class Member < ActiveRecord::Base
has_one :investor_account, dependent: :destroy
end
investor_account.rb
class InvestorAccount < ActiveRecord::Base
belongs_to :member
has_many :wallets, dependent: :destroy
end
wallet.rb
class Wallet < ActiveRecord::Base
belongs_to :investor_account
end
top_up.rb
belongs_to :wallet
/top_ups/_form.html.slim
= simple_form_for [:transaction, #top_up] do |f|
.form-group
= f.input :wallet_id, collection: #wallet, input_html: { class: 'form-control' }, include_blank: "Select..."
.form-group
= f.input :amount, input_html: { min: 0, value: 0 }
/controllers/top_ups_controller.rb
def new
#top_up = TopUp.new
#wallet = Wallet.joins(:investor_account).where(investor_accounts: {approval_status: 'approved'})
end
The data on "f.input :wallet_id ...." was showed up, but it is not as email of the member instead it showing #<Wallet:0x007fd6d795e808> on all wallet dropdown, previously I also write code like below.
= f.input :wallet_id, collection: #wallet, :id, :email, input_html: { class: 'form-control' }, include_blank: "Select..."
But it throwing problem the email not found. My question was how do I pass the member on that #wallet = ... variable to get email member showing on my form? Is there better way to get that?
You can use label_method and value_method params (docs):
= f.input :wallet_id, collection: #wallet, value_method: :id, label_method: :email, input_html: { class: 'form-control' }, include_blank: "Select..."
Also if you need only id and email, there is no need to fetch all the other data from the DB, you can use pluck:
# controller
def new
#top_up = TopUp.new
#wallet = Wallet.joins(:investor_account).where(investor_accounts: {approval_status: 'approved'}).pluck(:id, :email)
end
# form
= f.input :wallet_id, collection: #wallet, value_method: :first, label_method: :last, input_html: { class: 'form-control' }, include_blank: "Select..."
I have a product model which has a many to many association with a category model through join model category_product
I have a product/new.html.slim
=simple_form_for #product, html: { multipart: true } do |t|
= t.error_notification
div class="form-group"
= t.input :name, label: 'Nom',equired: true, input_html: { class: 'form-control' }
div class="form-group"
= t.input :description, label: 'Description', required: true, input_html: { class: 'form-control' }
div class="form-group"
= t.input :price, label: 'Prix', required: true, input_html: { class: 'form-control' }
div class="form-group"
= t.input :weight, label: 'Poids', required: true, input_html: { class: 'form-control' }
div class="form-group"
= t.association :categories, as: :check_boxes, label: "Catégories"
= t.button :submit, value: "Valider", class: "btn-success marge-bas"
when I submit my form I get the following error :
found unpermitted parameter: category_ids
though in my ProductController I have permitted category_ids :
def product_params
params.require(:product).permit(
:category_ids,
:name,
:price,
:description,
:weight,
:picture,
:picture1,
:picture2,
:picture3,
)
end
When I check my params category_ids is an array of strings
"category_ids"=>["1", "2", "5", ""]
What am I doing wrong ?
Try rewriting product_params to:
def product_params
params.require(:product).permit(:name, ... :picture3, :category_ids => [])
end
Setting the category_ids to be an array at the end of your list of permitted params should resolve this error.
Hope it helps!
I ran into this "Unpermitted parameter: category_ids" error when working through the book, "Rails, Up And Running" and adding category_ids => [] fixed it. Thank you, Zoran!
An organization has many members, and a relationship has been created between both models. A member of an organization is allowed to create additional members for that specific organization. This works fine. A system admin can go to the profile of any organization and then click 'create new member' to create a new member that organization. However, currently for the admin the organization_id does not save with the newly created member, thereby causing errors. Does anyone have an idea why the organization_id does not save?
Members controller:
def new
if current_user.admin?
if params[:organization_id].nil?
flash[:danger] = "Please select an organization first"
redirect_to organizations_path
else
#organization = Organization.find(params[:organization_id])
#member = #organization.members.build
end
else
#member = current_organization.members.build
end
end
def create
if current_user.admin?
#member = Member.new(new_params)
else
#member = current_organization.members.build(new_params)
end
if #member.save
#member.send_activation_email
flash[:success] = "A confirmation email will be sent to the new user."
redirect_to member_url(#member)
else
render 'new'
end
end
private
def new_params
params.require(:member).permit(:email,
:username,
:password,
:password_confirmation)
end
Members new view:
<%= form_for(#member) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<% if current_user.admin? %>
<%= f.text_field :organization_id, placeholder: 'Organization id', autocomplete: 'off', class: 'form-control', disabled: "disabled" %>
<% end %>
<%= f.email_field :email, placeholder: 'Email', autocomplete: 'off', class: 'form-control' %>
<%= f.text_field :username, maxlength: 15, placeholder: 'Username', autocomplete: 'off', class: 'form-control' %>
<%= f.password_field :password, placeholder: 'Password', autocomplete: 'off', class: 'form-control' %>
<%= f.password_field :password_confirmation, placeholder: 'Confirm password', autocomplete: 'off', class: 'form-control' %>
<%= f.submit "Sign up", class: "formbutton btn btn-default" %>
<% end %>
The organization profile view contains the following link to the member new view:
<%= link_to image_tag("add.png", title: "add member", height: '15'), new_member_path(organization_id: #organization.id) %>
Part of the members model:
belongs_to :organization
default_scope -> { includes(:organization).order('organizations.org_name , username') }
attr_accessor :remember_token, :activation_token, :reset_token
before_save :downcase_email, :downcase_username
before_create :create_activation_digest
#validates :organization_id, presence: true # Commented this out because of a joined form that doesn't work with this validation.
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
validates :email, presence: true,
length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
VALID_USERNAME_REGEX = /\A[a-zA-Z0-9_-]+\z/i
validates :username, presence: true,
length: { in: 6..15 },
format: { with: VALID_USERNAME_REGEX },
uniqueness: { case_sensitive: false }
In your def new_params, you are not permitting :organization_id.
If this is for security reasons, you can update your create action as follows:
def create
if current_user.admin?
#member = Member.new(new_params)
#member.organization_id = params[:member][:organization_id]
else
....
end
Also in your form, if you disable a field, it won't be sent as a params. You should add a hidden_field for :organization_id.
<% if current_user.admin? %>
<%= f.text_field :organization_id, placeholder: 'Organization id', autocomplete: 'off', class: 'form-control', disabled: "disabled" %>
<%= f.hidden_field :organization_id, value: #organization.id %>
<% end %>
The problem turned out to be disabled: "disabled" in the form. A disabled field does not get send on submit. Changing it to readonly: "readonly" solved it. See: What's the difference between disabled="disabled" and readonly="readonly" for HTML form input fields?
heres my model thats handling my form
class Form
include ActiveModel::Validations
include ActiveModel::Conversion
include ActiveModel::Translation
extend ActiveModel::Naming
attr_accessor :config, :client, :subject, :email, :custom_field, :phone_number_28445, :company_28445, :description
validates_presence_of :subject, :message => '^Please enter your name'
validates_presence_of :description, :message => '^Question(s), and/or feedback can not be blank'
validates :email, presence: true
validates_format_of :email, :with => /^[-a-z0-9_+\.]+\#([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
self.config = YAML.load_file("#{Rails.root}/config/fresh_desk.yml")[Rails.env]
self.client = Freshdesk.new(config[:url], config[:api_key], config[:password])
end
def post_tickets
client.post_tickets({
:subject => "Web Inquiry From, #{subject}",
:email => email,
:custom_field => {:phone_number_28445 => phone_number_28445},
:description => description
})
end
def persisted?
false
end
end
in my post_tickets method it works fine....the problem is with the
:custom_field_phone_number_28445 => custom_field_phone_number_28445
I know this because as soon as i take that out the form posts.......when i add it back in i get a
Completed 500 Internal Server Error in 1222ms
Freshdesk::ConnectionError (Connection to the server failed. Please check hostname):
lib/freshdesk.rb:77:in `rescue in block in fd_define_post'
lib/freshdesk.rb:70:in `block in fd_define_post'
app/models/form.rb:25:in `post_tickets'
app/controllers/website/contacts_controller.rb:8:in `create'
config/initializers/quiet_assets.rb:8:in `call_with_quiet_assets'
heres whats getting posted when it works
Parameters:
{"utf8"=>"✓", "authenticity_token"=>"g91E0jYezX+5gFAe6R/hUPs9b+UqS1uMqki4rE6xU28=",
"contacts"=>{"subject"=>"ricky ahn ",
"email"=>"ricky#onehouse.net",
"custom_field"=>{"phone_number_28445"=>"123-123-1234"},
"description"=>"test"},
"commit"=>"Submit"}
Redirected to http://localhost:3000/contacts/new
Completed 302 Found in 2142ms (ActiveRecord: 0.0ms)
heres what gets posted when it doesent work
Parameters: {"utf8"=>"✓", "authenticity_token"=>"g91E0jYezX+5gFAe6R/hUPs9b+UqS1uMqki4rE6xU28=",
"contacts"=>{"subject"=>"ricky ahn ",
"email"=>"ricky#onehouse.net",
"custom_field"=>{"phone_number_28445"=>"123-123-1234"},
"description"=>"test"}, "commit"=>"Submit"}
Completed 500 Internal Server Error in 841ms
i dont know what i'm doing wrong right here....
here is the html/haml
= form_for(:contacts, url: contacts_path) do |f|
= f.error_messages
= f.label :subject, "Name"
%span{style: 'color: red'} *
= f.text_field :subject, class: "text_field width_100_percent"
%br
%br
= f.label "Email"
%span{style: 'color: red'} *
%br
= f.email_field :email, class: "text_field width_100_percent"
%br
%br
= f.label "Phone"
%br
= f.fields_for :custom_field do |custom_field|
= custom_field.text_field :phone_number_28445, class: "text_field width_100_percent"
%br
%br
= f.label "Question(s), and/or feedback"
%span{style: 'color: red'} *
%br
= f.text_area :description, class: "text_field width_100_percent", style: 'height: 100px;'
%br
%br
= f.submit "Submit", class: 'btn btn-warning'
Did you specify this name for a reason? The value that's causing a problem is the only one w/an overridden form name.
= f.text_field :custom_field_phone_number_28445,
name: 'contacts[custom_field][phone_number_28445]',
class: "text_field width_100_percent"
Shouldn't it just be:
= f.text_field :custom_field_phone_number_28445,
class: "text_field width_100_percent"
All the other attributes aren't nested into a sub-name on the form... I'm guessing that value isn't being set in the form model, ends up nil, and something down the chain is mad about that.