Creating a form with nested attributes and prompt (has_many association) - ruby-on-rails

So the issue is i have these classes.
class Post < ActiveRecord::Base
belongs_to :category
has_many :text_fields
has_many :integer_fields
accepts_nested_attributes_for :text_fields
accepts_nested_attributes_for :integer_fields
end
class Category < ActiveRecord::Base
has_many :fields
end
class TextField < ActiveRecord::Base
belongs_to :post
end
class IntegerField < ActiveRecord::Base
belongs_to :post
end
Category has many Fields, every field (not to confuse with TextField or IntegerField) has a column "type" (to specify if it is Text or Integer field) and description (eg. "how many pets do you have" for integerField). When User want to create a new post, first he chooses category. then, based on what Fields each category has, proper TextFields and IntegerFields should be build and rendered.
I hope my point is clear, i want to have Post generator which generate different fields based on category, simple as that.
Post form (without steps for now)
= simple_form_for #poster do |f|
= f.input :category_id, collection: Category.all, prompt: "Choose category"
= f.input :title
= f.simple_fields_for :text_fields do |ftf|
= ftf.input :description
= f.simple_fields_for :integer_fields do |fif|
= fif.input :integer_number
= f.submit
And heres whats wrong. i dont know how to give each field a proper prompt. each TextField or IntegerField is there just because Category requires it (based on fields). But can i make it has a proper prompt, not just 'integer number' every time?
Here's how i build those fields, its open for changes:
def build_fields_based_on_category
category.fields.each do |field|
self.send("#{field.kind}_fields").build
##### 'kind' can be integer or 'text'
end
end

Related

how to save a belongs_to relationship?

I have two models
class Course < AR::B
belongs_to :teacher
end
class Teacher < AR::B
has_one :course
end
So my table courses has one field teacher_id. I've a dropdown on courses to choose the teacher that works like a charm.
But I want to add a dropdown on the EDIT TEACHER screen also to change the course. I've tried with f.collection_select :course, Courses.all, :id, :name. This displays the dropdown, and on the controller:
teacher_params[:course] = Course.find(teacher_params[:course])
Beacause I was receiving an error Expecting Course got String. If i just try with #teacher.save. But this don't works neither
What is the right way to accomplish this?
In your form, be sure you are setting the database column (not the association)
= f.collection_select :course_id, Courses.all, :id, :name
^^^^^
on the edit page you should find the course by id and either assign the teacher_id directly, or find the teacher model as well and set it to Course#teacher.
assuming your params come back with something like
{ course: { id: 1, teacher_id: 5 } }
for option 1, your controller might look like
#course = Course.find(teacher_params[:id])
#course.teacher_id = teacher_params[:teacher_id]
or for option 2
#course = Course.find(teacher_params[:id])
#teacher = teacher_params[:teacher_id]
#course.teacher = #teacher
now saving the course should be fine
use:
class Teacher < AR::B
has_one :courses
end
you are using :course, it must be plural
and second thing f.collection_select :course, Courses.all, :id, :name
this is wrong here is correct way
f.collection_select :course, Course.all, :id, :name

How to display associated model's attribute in Active Admin index with belongs_to/has_many relationship (Rails 3.2/Active Admin)

I'm building a daily deal Rails app to learn RoR.
I am facing a problem for the past few hours : i can't get a model's attribute of an other associated model on active admin. Let me show you exactly the problem :
I have two models: Brand (i.e the brand of the deal) and Deal. A deal belongs to a Brand but a Brand can have many Deals.
models/deal.rb is like this:
class Deal < ActiveRecord::Base
belongs_to :brand
and we have models/brand.rb:
class Brand < ActiveRecord::Base
has_many :deals
attr_accessible :name
And i did the t.belongs_to in my migrations so this is ok.
In Active Admin's Deals' create form , i type, as admin, which brand the deal is associated with:
admin/game.rb
ActiveAdmin.register Deal do
# -- Form -----------------------------------------------------------
form do |f|
f.inputs "Brand (i.e. client)" do
f.input :brand_id, :label => "Select a brand:", :as => :select, :collection => Brand.all
end
it works great, and i can create Deals with a certain brand.
but I CAN'T manage to display the NAME of the Brand in my list of Deals:
ActiveAdmin.register Deal do
index do
selectable_column
# id_column
column :title
column :deal_amount
column :brand do |deal|
link_to deal.brand.name
end
...doesn't work.
How can I do that ?
I tried everything but i basically don't know how to fetch the name of a Brand given it matches the brand_id in the Deal's table.
Any help appreciated.
show do |f|
panel "Subject" do
attributes_table_for f, :name, :description, :is_visible
end
panel "Pages in List View" do
table_for(f.pages) do |page|
column :name
column :permalink
column :is_visible
end
end
panel "Pages in View " do
div_for(f.pages) do |page|
panel page.name do
attributes_table_for page, :name, :description, :is_visible
end
end
end
end
end
You can do nested relations in same style as parent model
A couple things seem missing:
class Deal < ActiveRecord::Base
belongs_to :brands, foreign_key: :brand_id, class_name: 'Brand'
end
This is assuming that you mean partner to be a Brand and your schema uses brand_id for that relationship.
In your form, you can simply use:
form do |f|
f.inputs "Brand (i.e. client)" do
f.input :partner, label: 'Select a brand:'
end
end
Your link_to call won't actually link to a url the way you have it.
column :brand do |deal|
link_to deal.partner.name, admin_brand_path(deal.partner)
# or simpler
auto_link deal.partner
end
I would highly recommend trying to be consistent in your naming, as it will make things a lot less confusing and will require less code to make things work. i.e.
class Deal < ActiveRecord::Base
belongs_to :brand
end
f.input :brand, label: 'Select a brand:'
auto_link deal.brand
And your DB column can still be named brand_id.

Rails and has_many through association - how to properly set the form?

I am not sure I am setting my models correctly, so I would like to show you my idea:
I have the model Car that belongs to Company. Then I have a model called Color. In this DB table are stored all colors (red, blue, ...). And then there is the 4th model, called CarColor. This model contains two columns - job_id and color_id.
In the view, I would like to allow visitors to pick out colours with using checkboxes.
Form partial
= form_for #car do |f|
.field
= f.label :name
= f.text_field :name
.field
= f.label :location
= f.text_field :location
.field
= fields_for #car_colors do |cc|
...
.field
= fields_for #company do |c|
.field
= c.label :name
= c.text_field :name
.actions
= f.submit 'Save'
Models
class Company < ActiveRecord::Base
has_many :cars
end
class Car < ActiveRecord::Base
belongs_to :company
has_many :car_colors
has_many :c_colors, :through => :car_colors
end
class Color < ActiveRecord::Base
has_many :car_colors
has_many :cars, :through => :car_colors
end
class CarColor < ActiveRecord::Base
belongs_to :car
belongs_to :color
end
Saving Cars + Company works well, but I don't know how to add the checkboxes with colours in the view.
EDIT:
Regarding to the thread in the comment, I made a progress. However, I found an error that I don't know how to solve.
I am using model structure shown above and this is how look like the view:
- Color.order('name').each do |clr|
= check_box_tag :c_color_ids, clr.id, #car.car_colors.include?(clr), :name => 'car[c_color_ids][]'
= label_tag :c_color_ids, clr.name
This is the error I got:
PG::Error: ERROR: relation "car_colors" does not exist
What am I missing? How the relation cannot exist?
Ok, I spent a day of solving this issue. The scheme about is correct, the problem in my case was, that I have create a migration with table name car_color instead of car_colors...

Problems Using collection_select to store value in the database

I have two models:
Project.rb
class Project < ActiveRecord::Base
belongs_to :customer
end
and Customer.rb
class Customer < ActiveRecord::Base
has_many :projects
end
Inside the _form.html.erb I have:
<p>
<label>Select Customer</label>
<%= f.collection_select :customer_id, Customer.all, :id, :name, :include_blank => true %>
</p>
Which should Collect the Customers from the Customer model and display all the customers, finally it should assign the value to the customer_id which is in projects table.
Rite now the everything is passing when i check the log. When I select the first customer with value=1, it passes customer_id = "1" in my log but it doesn't get stored in the table. It shows customer_id = nil in the projects table.
Can someone help. Thanks :)
Do check that you added customer_id in attr_accessible method like,
class Project
attr_accessible :your_other_attributes, :customer_id
end

Is there an easier way of creating/choosing related data with ActiveAdmin?

Imagine I have the following models:
class Translation < ActiveRecord::Base
has_many :localizations
end
class Localization < ActiveRecord::Base
belongs_to :translation
end
If I do this in ActiveAdmin:
ActiveAdmin.register Localization do
form do |f|
f.input :word
f.input :content
end
end
The association for word will only allow me to choose from existing words. However, I'd like to have the option of creating a new word on the fly. I thought it may be useful to accept nested attributes in the localization model ( but then, I will only have the option of creating a Word, not selecting from existing ones ). How can I solve this problem?
I think you can try using virtual attribute for this
Example(not tested)
class Localization < ActiveRecord::Base
attr_accessor :new_word #virtual attribute
attr_accessible :word_id, :content, :new_word
belongs_to :translation
before_save do
unless #new_word.blank?
self.word = Word.create({:name => #new_word})
end
end
end
The main idea is to create and store new Word instance before saving localization and use it instead of word_id from drop-down.
ActiveAdmin.register Localization do
form do |f|
f.input :word
f.input :content
f.input :new_word, :as => :string
end
end
There is great rails-cast about virtual attributes http://railscasts.com/episodes/167-more-on-virtual-attributes

Resources