RoR nested optgroups - ruby-on-rails

I have successfully implemented the dynamic select menus for city and area models in my app.
now I have the following models:
class Pet < ActiveRecord::Base
belongs_to :pet_type
belongs_to :pet_category
belongs_to :pet_breed
end
class PetType < ActiveRecord::Base
has_many :pet_categories, through: :pet_type_categories
has_many :pet_type_categories
end
class PetCategory < ActiveRecord::Base
has_many :pet_types, through: :pet_type_categories
has_one :pet_type_category
end
class PetTypeCategory < ActiveRecord::Base
belongs_to :pet_type
belongs_to :pet_category
has_many :pet_breeds
end
class PetBreed < ActiveRecord::Base
belongs_to :pet_type_category
belongs_to :pet_Type
belongs_to :pet_category
end
migrations:
class CreatePetTypes < ActiveRecord::Migration
def change
create_table :pet_types do |t|
t.string :name
t.timestamps
end
end
end
class CreatePetCategories < ActiveRecord::Migration
def change
create_table :pet_categories do |t|
t.string :name
t.timestamps
end
end
end
class CreatePetTypeCategories < ActiveRecord::Migration
def change
create_table :pet_type_categories do |t|
t.references :pet_type, index: true
t.references :pet_category, index: true
t.timestamps
end
end
end
class CreatePetBreeds < ActiveRecord::Migration
def change
create_table :pet_breeds do |t|
t.string :name
t.references :pet_type_category, index: true
t.timestamps
end
end
end
The pet_type_category table is a join table for pet_types that share the same pet_categories.
So my question is how do I create 3 dynamic select menus of pet_type, pet_category and pet_breed in the create form?
Thanks
Edit: I managed to get the pet type collection_select and pet category grouped_collection_select done once I updated the relationships, now the 3rd one (pet breed) is what I'm stuck at..

I understand now after a bit of a research that it is not possible to have nested groups though surely It should be possible using some kind of helper, however for a lack of a better solution, I added to the PetTypeCategory model:
def pet_type_category_names
"#{self.pet_type.name} #{self.pet_category.name}"
end
and in my view now I have:
<div class="field">
<%= f.collection_select :pet_type_id, PetType.all, :id, :name, {prompt: "Choose your pet's type"} %>
</div>
<div class="field">
<%= f.grouped_collection_select :pet_category_id, PetType.all, :pet_categories, :name, :id, :name, {prompt: "Choose your pet's category"} %>
</div>
<div class="field">
<%= f.grouped_collection_select :pet_breed_id, PetTypeCategory.all, :pet_breeds, :pet_type_category_names, :id, :name, {prompt: "Choose your pet's breed"} %>
</div>
so for the 3rd select instead of having:
Dog
Small
Breed
I have:
Dog Small
Breed

Related

Rails form_with to select values from model1 for model2 with has_and_belongs_to_many relationship

I am new to Rails and working on a blog project.
I have articles and categories. Each article can have multiple categories and each category can belong to multiple articles.
I also have a join table articles_categories
My migrations:
class CreateArticles < ActiveRecord::Migration[5.2]
def change
create_table :articles do |t|
t.string :title
t.text :body
t.timestamps
end
end
end
class CreateCategories < ActiveRecord::Migration[5.2]
def change
create_table :categories do |t|
t.string :name
t.timestamps
end
end
end
class CreateArticlesCategoriesJoinTable < ActiveRecord::Migration[5.2]
def change
create_join_table :articles, :categories do |t|
t.index :article_id
t.index :category_id
end
end
end
My model associations:
class Article < ApplicationRecord
has_and_belongs_to_many :categories
end
class Category < ApplicationRecord
has_and_belongs_to_many :articles
end
This all makes sense so far.
What I am struggling with now, is how do I add categories when creating a new Article? I want to be able to select pre-defined categories from a list (stored in Category table) through a form.
What model and/or URL (if any) do I use in the form_with helper?
Is the following anywhere close?
<% form_with model: ???, url: ??? do |f| %>
<%= f.collection_select :category_id, Category.order(:name), :id, :name %>
<% end %>

CarrierWave undefined method `image_url' or broken image

I have many images(add_images_to_steps) belonging to steps which belongs to diys. All information saves correctly as DB browser shows, but i have problem viewing images.
with
views/diys/show.html.erb
<p id="notice"><%= notice %></p>
<h2><%= #diy.summary %></h2>
<% #steps.each do |step| %>
<p><%= step.step_content %></p>
<% step.add_images_to_steps.each do |i| %>
<%= image_tag i.image_url.to_s %>
<% end %>
<% end %>
I get NoMethodError in Diys#Show
undefined method `image_url' for #
and if I change
to
I get this
-----------------------------------------------------------------------
Heres My migrations, models and controllers.
-----------------------------------------------------------------------
diys_controller.rb
class DiysController < ApplicationController
before_action :set_diy, only: [:show, :edit, :update, :destroy]
def show
#diy = Diy.find(params[:id])
#steps = #diy.steps.all
#diy.add_images_to_steps.all
end
def new
#diy = Diy.new
#step = #diy.steps.new
#step.add_images_to_steps.new
end
...
def diy_params
params.require(:diy).permit(:title, :summary, :tip, :warning, steps_attributes: [:step_content, add_images_to_steps_attributes: [:image]])
end
models/diy.rb
class Diy < ActiveRecord::Base
has_many :steps, dependent: :destroy
accepts_nested_attributes_for :steps, reject_if: :all_blank
has_many :add_images_to_steps, :through => :steps, dependent: :destroy
accepts_nested_attributes_for :add_images_to_steps
end
models/step.rb
class Step < ActiveRecord::Base
belongs_to :diy
has_many :add_images_to_steps, dependent: :destroy
accepts_nested_attributes_for :add_images_to_steps
mount_uploader :image, ImageUploader
end
models/add_images_to_step.rb
class AddImagesToStep < ActiveRecord::Base
belongs_to :step
end
Diy migration
class CreateDiys < ActiveRecord::Migration
def change
create_table :diys do |t|
t.string :title
t.text :summary
t.text :tip
t.text :warning
t.timestamps null: false
end
end
end
Steps migration
class CreateSteps < ActiveRecord::Migration
def change
create_table :steps do |t|
t.belongs_to :diy
t.text :step_content
t.timestamps null: false
end
end
end
add_images_to_step migration
class CreateAddImagesToSteps < ActiveRecord::Migration
def change
create_table :add_images_to_steps do |t|
t.belongs_to :step
t.string :image
t.timestamps null: false
end
end
end
I figured it out!!
Had to add
mount_uploader :image, ImageUploader
to ../models/add_images_to_step.rb
change def store_dir to
"#{Rails.root}/public/uploads/"
in ../app/uploaders/image_uploader.rb
and
"<%= image_tag i.image_url.to_s %>"
was right for show view.

question mark after variable/object name in rails

I'm very new to ruby on rails. Thanks for your patience in advance.
<div class="field">
<%= #pin.image_url if #pin.image? %>
<%= f.file_field :image %>
<%= f.hidden_field :image_cache %>
</div>
What does #pin.image? do?
There is not image? method in my controller. I'm guessing it's one of the helper functions provided by rails for every controller? Is that right?
What is f ?
here is my model for pin
class Pin < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
belongs_to :board
end
and its schema
class CreatePins < ActiveRecord::Migration
def change
create_table :pins do |t|
t.string :name
t.string :image
t.integer :board_id
t.timestamps null: false
end
end
end
class AddImageToPins < ActiveRecord::Migration
def change
add_column :pins, :image, :string
end
end
There is not image? method in my controller.
You don't call this method on your controller, but on your object assigned to #pin variable, which is probably your Pin model. And your model does have image? method.
What is f ?
It's the form builder object, passed into form_for block.

Can't delete the HATBM relationship in ruby on rails

Not sure how to delete the associate between 'fly' and 'invoice'. What I've tried so far deletes the fly from the database
<table class="table table-condensed">
<thead>
<tr>
<th>Invoice Flies</th>
</thead>
<tbody>
<% #invoice.flies.each do |fly| %>
<tr>
<td><%= fly.name %></td>
<td><%= link_to "delete", ??????, method: :delete,
data: { confirm: "You sure?" } %></td>
</tr>
<% end %>
</tbody>
</table>
Invoice Model:
class Invoice < ActiveRecord::Base
attr_accessible :active
validates :user_id, presence: true
belongs_to :user
has_many :categorizations
has_many :flies, through: :categorizations
end
Invoice migration:
class CreateInvoices < ActiveRecord::Migration
def change
create_table :invoices do |t|
t.boolean :active
t.integer :user_id
t.timestamps
end
add_index :invoices, :user_id
end
end
Categorization Model:
class Categorization < ActiveRecord::Base
attr_accessible :fly_id, :user_id
belongs_to :invoice
belongs_to :fly
end
Categorization migration:
class CreateCategorizations < ActiveRecord::Migration
def change
create_table :categorizations do |t|
t.integer :user_id
t.integer :fly_id
t.timestamps
add_index :categorizations, :user_id
add_index :categorizations, :fly_id
end
end
end
Fly Model:
class Fly < ActiveRecord::Base
attr_accessible :description, :name
validates :description, :name, presence: true
has_many :categorizations
has_many :invoices, through: :categorizations
end
Fly migration:
class CreateFlies < ActiveRecord::Migration
def change
create_table :flies do |t|
t.string :name
t.string :description
t.timestamps
end
end
end
You can use dependent: :destroy like this:
class Fly
has_many :categorizations, dependent: :destroy
...
end
This will destroy the categorizations related to that Fly.
Also, remember to use Fly.destroy(:id) (DO NOT USE Fly.delete(:id), or it won't remove the categorizations dependent on that Fly)

Creating object by Polymorphic association rails

I need (or I think) implement polymorphic association in my model but I have something wrong. Let see my situation, it's a simple question/answers system, and the logic is the following:
- a question can be ansewered by N answers.
- An answer can be only a "text" XOR (one or other, not both) a "picture".
Migrations:
class CreateAnswers < ActiveRecord::Migration
def change
create_table :answers do |t|
t.integer :question_id
t.references :answerable, :polymorphic => true
t.timestamps
end
end
end
class CreateAnswerTexts < ActiveRecord::Migration
def change
create_table :answer_texts do |t|
t.text :content
t.timestamps
end
end
end
class CreateAnswerPictures < ActiveRecord::Migration
def change
create_table :answer_pictures do |t|
t.string :content
t.timestamps
end
end
end
Models
*answer.rb*
class Answer < ActiveRecord::Base
belongs_to :user_id
belongs_to :question_id
belongs_to :answerable, :polymorphic => true
attr_accessible :answerable_type
end
answer_text.rb
class AnswerText < ActiveRecord::Base
TYPE = "text"
has_one :answer, :as => :answerable
attr_accessible :content
end
answer_picture.rb
class AnswerPicture < ActiveRecord::Base
TYPE = "picture"
has_one :answer, :as => :answerable
attr_accessible :content
end
Controller
answers_controller.rb:
...
def create
post = params[:answer]
create_answerable(post[:answerable_type], post[:answerable])
#answer = #answerable.answer.new()
end
private
def create_answerable(type, content)
#answerable = ('Answer' + type.capitalize).classify.constantize.new(:content => content)
#answerable.save
end
...
And view form (Only have these fields):
...
<div class="field">
<%= f.label :answerable_type %><br />
<%= select("answer", "answerable_type", Answer::Types, {:include_blank => true}) %>
</div>
<div class="field">
<%= f.label :answerable %><br />
<%= f.text_field :answerable %>
</div>
...
So, the problem is when I submit form I get this error:
undefined method new' for nil:NilClass
app/controllers/answers_controller.rb:52:increate'
Answers? :)
on a has_one relationship, you have to use :
#answerable.build_answer
or
#answerable.create_answer
instead of
#answerable.answer.new
see the reference for more info.

Resources