I am using a PostgreSQL database and Rails 5.0.6.
I try to build a course allocation WebApp for the school where I am working. For each course the teachers are able to select which forms are allowed to visit the course.
Migration file:
def up
create_table :courses do |t|
t.integer :number, null: false
t.string :name, null: false
t.text :description, null: false
t.decimal :level, array: true, default: []
t.integer :max_visitor, null: false
t.integer :min_visitor
t.integer :pos_visit
t.timestamps
end
end
In my Controller:
params.require(:course).permit(:number, :name, :description, :level [], :max_visitor, :min_visitor, :pos_visits)
I already read this post: Rails 5 strong params with an Array within check boxes values. But the Syntax params.require(:product).permit(:id, **category_ids: []**) doesnt work for me even though I am using rails 5 as well. I am not sure if :level [] really works but it seems to be correct syntax.
This is my Form:
<%= form_for #course do |t| %>
<%= t.text_field :number, class: 'form-control' %>
<%= t.text_field :name, class: 'form-control' %>
<%= t.text_area :description, class: 'form-control' %>
<%= t.check_box :level[], 1%>
<%= t.check_box :level[], 2%>
<%= t.check_box :level[], 3%>
<%= t.check_box :level[], 4%>
<%= t.text_field :max_visitor, class: 'form-control' %>
<%= t.text_field :min_visitor, class: 'form-control' %>
<%= t.text_field :pos_visit, class: 'form-control' %><br/>
<%= t.submit "bestätigen", class: "btn btn-success"%>
<% end %>
This check_box syntax seems to be wrong.
May anyone help me with the right syntax of the check_boxes?
Thanks for help.
There's a collection_check_boxes helper method for this:
<%= form_for #course do |f| %>
<%= f.collection_check_boxes(:level, { 'One': 1, 'Two': 2, 'Three': 3 }, :last, :first) %>
<% end %>
The third argument is the method used to get the value from the "collection", and the fourth is the method used to get the label from the "collection". This helper method automatically converts the Hash into an array, that's why I'm using last and first here.
It's also possible to style it the way you want e.g. using Bootstrap:
<%= f.collection_check_boxes(:level, { 'One': 1, 'Two': 2, 'Three': 3 }, :last, :first) do |b| %>
<div class="form-check form-check-inline">
<%= b.check_box class: 'form-check-input' %>
<%= b.label class: 'form-check-label' %>
</div>
<% end %>
<%= check_box_tag 'level[]', 1%>
<%= check_box_tag 'level[]', 2%>
<%= check_box_tag 'level[]', 3%>
<%= check_box_tag 'level[]', 4%>
But when you use check_box_tags in form_for, then the parameters level[], will be outside off the strong parameters array you usually use in the controller#new function.
Parameters: {"course"=>{"number"=>"12", "name"=>"tanzen", "description"=>"efwefggw", "max_visitor"=>"12", "min_visitor"=>"5", "pos_visit"=>"2"}, "level"=>["1", "3", "4"], "commit"=>"bestätigen"}
So I added the level manually
#course = Course.new(course_params)
#course.level = params[:level]
Related
I am trying to do the seemingly innocuous task of passing an array of tags to a new subscriber form, based on which page it's rendered on.
My Subscriber table looks like this in schema.rb:
create_table "subscribers", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.string "phone"
t.string "email"
t.text "tags", default: [], array: true
t.text "admin_notes"
t.boolean "unsubscribe"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
My partial is rendered like this:
<%= render partial: "layouts/new_subscriber", locals: { tags: "buyer, LM-house-tour-checklist" } %>
Which brings up this _new_subscriber.html.erb partial:
<%= simple_form_for(#new_subscriber) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.label :first_name %>
<%= f.text_field :first_name, required: true, class: "form-control" %>
<%= f.label :last_name %>
<%= f.text_field :last_name, required: true, class: "form-control" %>
<%= f.label :phone %>
<%= f.text_field :phone, required: true, class: "form-control" %>
<%= f.label :email %>
<%= f.text_field :email, required: true, class: "form-control" %>
<%= f.hidden_field :tags, value: tags %>
</div>
<div class="form-actions text-center">
<%= f.submit "Get My Checklist", class: "btn" %>
</div>
<% end %>
I have tested using the Chrome code inspector that "buyer, LM-house-tour-checklist" is getting passed into the hidden field value.
However, when I submit, it creates the subscriber with a :tags attribute of ["uyer"]. This is super weird and unexplainable to me.
Some other info:
There is nothing in my subscriber model.
#new_subscriber is defined in my ApplicationController using before_action :new_subscriber and def new_subscriber #new_subscriber = Subscriber.new end
I have tried the method described here, but to no avail
Can anyone help me do this in the "Railsiest" way possible? It dosn't seem like that unusual of an ask, but I can't get it to work properly.
Maybe because it's sent as string.
Try to add attr_accessor :plain_tags in model
Instead of tags field use this attribute.
And in before_create callback write something like
before_create :populate_tags
def populate_tags
return if self.tags_plain.blank?
self.tags = self.tags_plain.split(",")
end
I am making an online library system with Ruby on Rails. Currently users can sign up, but to do so they must first choose a type of subscription plan.
In the end, the best way I found to do this, was to pass a plan_id like so:
config/routes.rb
get 'subscribe/paperback2u', to: 'members#new', :plan_id => 1
get 'subscribe/paperback4u', to: 'members#new', :plan_id => 2
get 'subscribe/paperback6u', to: 'members#new', :plan_id => 3
Then, members/new.html.erb pulls the form partial, which looks like this:
<%= form_with(model: member, local: true) do |form| %>
<% plan_id = params[:plan_id] %>
<div class="field form-group">
<%= form.label :first_name, "First Name" %>
<%= form.text_field :first_name,
id: :member_first_name,
:class => "form-control",
:required => true %>
</div>
<div class="field form-group">
<%= form.label :last_name, "Last Name" %>
<%= form.text_field :last_name,
id: :member_last_name,
:class => "form-control",
:required => true %>
</div>
<div class="field form-group">
<%= form.label :address_line_1, "Address Line 1" %>
<%= form.text_field :address_line_1,
id: :member_address_line_1,
:class => "form-control",
:required => true %>
</div>
<div class="field form-group">
<%= form.label :address_line_2, "Address Line 2" %>
<%= form.text_field :address_line_2,
id: :member_address_line_2,
:class => "form-control" %>
</div>
<div class="field form-group">
<%= form.label :town %>
<%= form.text_field :town,
id: :member_town,
:class => "form-control",
:required => true %>
</div>
And the other fields for the member model.
Then we get to:
98 <%= form.hidden_field :plan_id, value: params[:plan_id] %>
100 <% if form.object.new_record? %>
101 <%= render 'stripe-form' %>
102 <% end %>
I don't think line 98 is doing anything, to be honest.
Then the stripe-form partial looks like this:
1 <div class="text-center">
2 <script src="https://checkout.stripe.com/checkout.js" class="stripe-button btn-primary"
3 data-key="<%= Rails.configuration.stripe[:publishable_key] %>"
4 data-description="Subscribe to ReadAll Library"
5 data-amount=<%= (Plan.find(params["plan_id"].to_i).display_price) * 100 %>
6 data-currency="gbp"
7 data-panelLabel="Subscribe for"
8 data-label="Subscribe"
9 data-locale="auto"></script>
10 </div>
The error I am getting is:
Error:
MembersControllerTest#test_should_get_new:
ActionView::Template::Error: Couldn't find Plan with 'id'=1
app/views/members/_stripe-form.html.erb:5:in `_app_views_members__stripe_form_html_erb___374722773566915779_70180218242520'
app/views/members/_form.html.erb:101:in `block in _app_views_members__form_html_erb__2640496602018942691_70180179508500'
app/views/members/_form.html.erb:1:in `_app_views_members__form_html_erb__2640496602018942691_70180179508500'
app/views/members/new.html.erb:5:in `_app_views_members_new_html_erb___3025732295195500162_70180218177380'
test/controllers/members_controller_test.rb:16:in `block in <class:MembersControllerTest>'
The error I get if I add puts response.body in the tests is: "Plan must exist". Which it does! I have 3 different plans in my plans table. Each one has an ID, and everything works when I actually run it. It's just the test that doesn't work. I'd scrap the test if I could, but I need it as documentation for a project.
Finally, here's my Plan.rb and Member.rb
`plan.rb`
class Plan < ApplicationRecord
has_many :members
end
`member.rb`
class Member < User
1 require 'stripe'
2
3 before_save :set_type
4
5 belongs_to :plan
6
7
8 def set_type
9 self.type = "Member"
10 end
11
12 end
And the schema for the two:
create_table "plans", force: :cascade do |t|
t.string "stripe_id"
t.string "nickname"
t.decimal "display_price"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "product"
end
create_table "users", force: :cascade do |t|
bunch of user attributes (first_name, address, etc)
t.string "type" (members is a users type)
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "remember_digest"
t.string "customer_id"
t.bigint "plan_id"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["plan_id"], name: "index_users_on_plan_id"
end
I'm out of ideas. I appreciate any help you guys can give me. Cheers.
In your view, if you want that your user choose from the form, you could add the select input and let the user select what plan they want. But it's all possible that you pass this information through URL, as you already did.
View:
<%= form_with(model: member, local: true) do |form| %>
<div class="field form-group">
<%= form.label :first_name, "First Name" %>
<%= form.text_field :first_name,
id: :member_first_name,
:class => "form-control",
:required => true %>
</div>
<div class="field form-group">
<%= form.label :plan, "Choose your plan" %>
<%= form.select :plan_id,
Plan.all {|p| [ p.name, p.id ]},
{ include_blank: false, selected: form.object.plan_id }, class: 'form-control' %>
</div>
<%= f.submit "Salvar", class: "btn btn-primary" %>
<% end %>
I believe the rest you already did it. In the controller you add to the white list of params the plan_id, and in your model you add model relations as has_many and belong. P.s: I didn't test this.
I've been trying Ruby on Rails for a few months now, re-engineering a desktop application. This application has a form for updating take-off and landing points, whose coordinates must be confirmed. Well, I tried validates_confirmation_of method however it works only with String attributes, and I have Integer and Decimal types. Hence I created an alternative method by borrowing an excerpt from the helper (confirmation.rb), which is working fine. But I wonder if there is another way to do it or whether this solution can be improved. Below follows a compact version of the source files. Thanks in advance!
Migration:
class CreateWaypoints < ActiveRecord::Migration[5.0]
def change
create_table :waypoints do |t|
t.string :name
t.integer :latitude_in_degrees
t.integer :latitude_in_minutes
t.decimal :latitude_in_seconds, precision: 5, scale: 2
t.timestamps
end
add_index :waypoints, [:name], unique: true
end
end
View:
<%= simple_form_for(#waypoint) do |f| %>
<%= f.error_notification %>
<div class="form-inline">
<%= f.input :name %>
</div>
<div class="form-inline">
<%= f.input :latitude_in_degrees %>
<%= f.input :latitude_in_minutes %>
<%= f.input :latitude_in_seconds %>
</div>
<div class="form-inline">
<%= f.input :latitude_in_degrees_confirmation, as: :numeric, label: false %>
<%= f.input :latitude_in_minutes_confirmation, as: :numeric, label: false %>
<%= f.input :latitude_in_seconds_confirmation, as: :numeric, label: false %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
Model:
class Waypoint < ApplicationRecord
...
validates_each :latitude_in_degrees, :latitude_in_minutes, :latitude_in_seconds do |record, attribute, value|
if record.send("#{attribute}_changed?")
confirmed = record.send("#{attribute}_confirmation")
if confirmed.to_s != value.to_s
human_attribute_name = record.class.human_attribute_name(attribute)
record.errors.add(:"#{attribute}_confirmation", "Doesn't match #{human_attribute_name}")
end
end
end
end
I have created a valuation table which contain
class CreateValuations < ActiveRecord::Migration
def change
create_table :valuations do |t|
t.text :location
t.integer :number_of_bedroom
t.integer :number_of_bath
t.integer :age_of_building
t.text :other_details
t.string :name
t.string :email
t.integer :contact_number
t.timestamps null: false
end
end
end
And later i added a column :building of type text in it using rails generate migration add_building_to_valuations building:text. I have created a form
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#valuation) do |val| %>
<%= val.label :building, "Name of Building/Builder" %>
<%= val.text_field :building, class: 'form-control' %>
<%= val.label :location, "Location" %>
<%= val.text_field :location, class: 'form-control' %>
<%= val.label :number_of_bedroom, "Number of Bedroom" %>
<%= val.text_field :number_of_bedroom, class: 'form-control' %>
<%= val.label :number_of_washroom, "Number of Washroom" %>
<%= val.text_field :number_of_bath, class: 'form-control' %>
<%= val.label :age_of_building, "Age of Building" %>
<%= val.text_field :age_of_building, class: 'form-control' %>
<%= val.label :name, "Name" %>
<%= val.text_field :name, class: 'form-control' %>
<%= val.label :email, "Email" %>
<%= val.text_field :email, class: 'form-control' %>
<%= val.label :contact_number, "Contact Number" %>
<%= val.text_field :contact_number, class: 'form-control' %>
<%= val.submit "Evaluate my property", class: "btn btn-primary" %>
<% end %>
</div>
</div>
When i fill all the field and submit via Evaluate my property, Then no data is being saved in :building.
I checked this using following commands
$ rails console
$ Valuation.all
and received output are following output
#<Valuation id: 1, location: "Chandivali, Powai",
number_of_bedroom: 3, number_of_bath: 3,
age_of_building: 9, other_details: nil, name: "Shravan",
email: "shravan.xxx#gmail.com",
contact_number: "9876543210",created_at: "2015-11-14 09:47:26",
updated_at: "2015-11-14 09:47:26", building: nil>,
You should update your valuation_params Which is most likely a private function
private
def valuation_params
params.require(:valuation).permit(:building,
:location,
:number_of_bedroom,
:number_of_bath,
:age_of_building,
:name, :email, :contact_number)
end
end
I have created a table name tenants which have following column
class CreateTenants < ActiveRecord::Migration
def change
create_table :tenants do |t|
t.text :company_name
t.text :work_area
t.text :second_pref
t.text :third_pref
t.integer :who_are_you
t.integer :number_of_bedroom
t.text :other_specs
t.string :budget
t.string :name
t.string :email
t.string :contact_number
t.timestamps null: false
end
end
end
And i am entering the data into in table by following form
<%= form_for Tenant.new do |val| %>
<%= val.label :company_name, "Company Name" %>
<%= val.text_field :company_name, class: 'form-control' %>
<%= val.label :work_area, "Work Area" %>
<%= val.text_field :work_area, class: 'form-control' %>
<%= val.label :second_pref, "Second Preference" %>
<%= val.text_field :second_pref, class: 'form-control' %>
<%= val.label :third_pref, "Third Preference" %>
<%= val.text_field :third_pref, class: 'form-control' %>
<%= val.label :who_are_you, "Are you Family/Bachelor?" %>
<%= val.text_field :who_are_you, class: 'form-control' %>
<%= val.label :number_of_bedroom, "Number of Bedroom" %>
<%= val.text_field :number_of_bedroom, class: 'form-control' %>
<%= val.label :other_specs, "Other Requirments" %>
<%= val.text_field :other_specs, class: 'form-control' %>
<%= val.label :budget, "Your Budget" %>
<%= val.text_field :budget, class: 'form-control' %>
<%= val.label :name, "Name" %>
<%= val.text_field :name, class: 'form-control' %>
<%= val.label :email, "Email" %>
<%= val.text_field :email, class: 'form-control' %>
<%= val.label :contact_number, "Contact Number" %>
<%= val.text_field :contact_number, class: 'form-control' %>
<%= val.submit "Submit", class: "btn btn-primary" %>
<% end %>
When i fill all the required filled and click submit, i see the following output in rails server log.
Started POST "/tenants" for ::1 at 2015-11-15 11:41:27 +0530
Processing by TenantsController#create as HTML
Parameters: {
"utf8"=>"✓", "authenticity_token"=>"26KYMFmofF+A1UrF+eWu21nEGbVO3n2bUSPl8340k8hY1JQhYF2kfhOHLmlF+r1Tj5UB7h6H+IJ7MY+Rx+o4CA==",
"tenant"=>
{
"company_name"=>"Housing.com",
"work_area"=>"Hiranandani Business Park",
"second_pref"=>"Chandivali",
"third_pref"=>"Vikhroli",
"who_are_you"=>"Bachelor",
"number_of_bedroom"=>"3",
"other_specs"=>"Gym, Swimming Pool",
"budget"=>"55000",
"name"=>"Shravan Kumar Gond",
"email"=>"shravan.ma.iitkgp#gmail.com",
"contact_number"=>"9475593772"
},
"commit"=>"Submit"
}
Unpermitted parameter: budget
(0.1ms) begin transaction
(0.1ms) rollback transaction
Can anyone tell me, why this happening ?
It seems you are missing :budget in strong parameters of your tenants_controller.rb file. It should be something like this.
private
def tenant_params
params.require(:tenant).permit(:company_name,
:work_area,
:second_pref,
:third_pref,
:who_are_you,
:number_of_bedroom,
:other_specs,
:budget,
:name,
:email,
:contact_number)
end
Unpermitted parameter: budget
This is your error - it means you're passing parameters to your controller, but it cannot save them in your model.
The fix is to set the strong params method (as shravan40 suggested).
Since you're calling Tenant.new in your #new action, I would recommend using the following in your controller:
#app/controllers/tenants_controller.rb
class TenantsController < ApplicationController
def new
#tenant = Tenant.new
end
def create
#tenant = Tenant.new tenant_params
#tenant.save
end
private
def tenant_params
params.require(:tenant).permit(:company_name, :work_area, :second_pref, :third_pref, :who_are_you, :number_of_bedroom, :other_specs, :budget, :name, :email, :contact_number)
end
end
There's also something you can do to polish up your form...
<%= form_for #tenant do |val| %>
<% vals = [[:company_name],[:work_area],[:second_pref, "Second Preference"], [:third_pref, "Third Preference"],[:who_are_you, "Are you Family/Bachelor?"], [:number_of_bedroom], [:other_specs, "Other Requirements"],[:budget, "Your Budget"], [:name], [:email], [:contact_number]] %>
<% vals.each do |value| %>
<% value[1] ||= value[0].to_s.gsub("_", " ") %>
<%= val.label value[0], value[1] %>
<%= val.text_field value[0], class: 'form-control' %>
<% end %>
<%= val.submit "Submit", class: "btn btn-primary" %>
<% end %>