Ruby on Rails: many-to-many association undefined methode on creation - ruby-on-rails

I have set up members and teams models using has_many through association.
member.rb
has_many :teams, :through => :team_members
has_many :team_members
team.rb
has_many :members, :through => :team_members
has_many :team_members
team_member.rb
belongs_to :member
belongs_to :team
When I try to create a new team, I get this error:
undefined method `name' for nil:NilClass
params are:
{"utf8"=>"✓",
"authenticity_token"=>"aXpMxWxGlhogfn9EbBWciSjoMrYXbPxG8Kzha14na58=",
"team"=>{"name"=>"Ruby",
"email"=>"email#email.com",
"language"=>"En",
"link"=>"",
"logo"=>#<ActionDispatch::Http::UploadedFile:0xb3907f0 #original_filename="You-Are-Great-.gif",
#content_type="image/gif",
#headers="Content-Disposition: form-data; name=\"team[logo]\"; filename=\"You-Are-Great-.gif\"\r\nContent-Type: image/gif\r\n",
#tempfile=#<File:/tmp/RackMultipart20120723-1907-m3bi79>>},
"commit"=>"Create Team"}
The create method in teams_controller.rb is:
#team = Team.new(params[:team])
The team doesn't get created unless I assign the attributes manually one by one like
#team = Team.new(:name => params[:team][:name], :email => params[:team][:email]...)
and so! any ideas why?
EDIT:
teams_controller.rb:
class TeamsController < ApplicationController
# GET /teams
# GET /teams.json
def index
#teams = Team.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #teams }
end
end
# GET /teams/1
# GET /teams/1.json
def show
#team = Team.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #team }
end
end
# GET /teams/new
# GET /teams/new.json
def new
#team = Team.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #team }
end
end
# GET /teams/1/edit
def edit
#team = Team.find(params[:id])
end
# POST /teams
# POST /teams.json
def create
raise params.to_yaml
#team = Team.new(params[:team])
respond_to do |format|
if #team.save
#team_member = TeamMember.new(:team_id => #team.id, :member_id => current_member.id,
:accepted => true, :leader => true, :joined => Time.now)
if #team_member.save
format.html { redirect_to team_path(#team), notice: 'Team was successfully created.' }
format.json { render json: #team, status: :created, location: #team }
else
#team.destroy
format.html { render action: "new" }
format.json { render json: #team.errors, status: :unprocessable_entity }
end
else
format.html { render action: "new" }
format.json { render json: #team.errors, status: :unprocessable_entity }
end
end
end
# PUT /teams/1
# PUT /teams/1.json
def update
#team = Team.find(params[:id])
respond_to do |format|
if #team.update_attributes(params[:team])
format.html { redirect_to #team, notice: 'Team was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #team.errors, status: :unprocessable_entity }
end
end
end
# DELETE /teams/1
# DELETE /teams/1.json
def destroy
#team = Team.find(params[:id])
#team.destroy
respond_to do |format|
format.html { redirect_to teams_url }
format.json { head :no_content }
end
end
end
team.rb model:
class Team < ActiveRecord::Base
attr_accessible :name, :email, :language, :link, :logo, :team_leader
validates_presence_of :name
validates_presence_of :email
validates_presence_of :language
validates_uniqueness_of :name
has_many :leaders, :class_name => "TeamMember", :conditions => { :leader => true }
has_many :members, :through => :team_members
has_many :team_members, :conditions => { :accepted => true, :active => true }
has_attached_file :logo,
:styles => { :medium => "320x180>", :thumb => "100x100>" },
:url => "/assets/teams/:id/:style/:basename.:extension",
:path => ":rails_root/public/assets/teams/:id/:style/:basename.:extension"
end

Related

How preview multiple images with nested form rails

I'm using paperclip to upload images and nested form.
I want to preview images as input, not just an image.
This is my form.
= nested_form_for #anime, html:{multipart:true} do |f|
- if #anime.errors.any?
#error_explanation
%h2= "#{pluralize(#anime.errors.count, "error")} prohibited this anime from being saved:"
%ul
- #anime.errors.full_messages.each do |msg|
%li= msg
.field
= f.label :name
= f.text_area :name
.fields
=f.fields_for :images do |i|
=i.file_field :content
=i.link_to_remove "Remove"
.field
=f.link_to_add "add Image", :images
.actions
= f.submit 'Save'
This is my model.
class Image < ApplicationRecord
belongs_to :imageable, :polymorphic => true, optional:true
has_attached_file :content, :styles=>{:medium => "300x300>", :thumb => "100x100>"}
validates_attachment_content_type :content, :content_type => %w(image/jpeg image/jpg image/png)
end
class Anime < ApplicationRecord
has_many :images, :as => :imageable, dependent: :destroy
accepts_nested_attributes_for :images, :allow_destroy => true
end
This is my controller
class AnimesController < ApplicationController
before_action :set_anime, only: [:show, :edit, :update, :destroy]
# GET /animes
# GET /animes.json
def index
#animes = Anime.all
end
# GET /animes/1
# GET /animes/1.json
def show
end
# GET /animes/new
def new
#anime = Anime.new
#anime.images.build
end
# GET /animes/1/edit
def edit
end
# POST /animes
# POST /animes.json
def create
#anime = Anime.new(anime_params)
respond_to do |format|
if #anime.save
format.html { redirect_to #anime, notice: 'Anime was successfully created.' }
format.json { render :show, status: :created, location: #anime }
else
format.html { render :new }
format.json { render json: #anime.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /animes/1
# PATCH/PUT /animes/1.json
def update
respond_to do |format|
if #anime.update(anime_params)
format.html { redirect_to #anime, notice: 'Anime was successfully updated.' }
format.json { render :show, status: :ok, location: #anime }
else
format.html { render :edit }
format.json { render json: #anime.errors, status: :unprocessable_entity }
end
end
end
# DELETE /animes/1
# DELETE /animes/1.json
def destroy
#anime.destroy
respond_to do |format|
format.html { redirect_to animes_url, notice: 'Anime was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_anime
#anime = Anime.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def anime_params
params.require(:anime).permit(:name, images_attributes: [:content])
end
end
Please help me
Thanks so much.
ignore this message

How to parse nested JSON object in Rails?

I'm sending the following JSON to Rails 4.1.0
Started POST "/orders.json" for 127.0.0.1 at 2015-08-11 15:19:34 +0200
Processing by OrdersController#create as JSON
Parameters: {"order"=>{"name"=>"Jon", "surname"=>"Do", "line_items_attributes"=>[{"work_id"=>16, "quantity"=>1, "total_price"=>34.5}, {"work_id"=>12, "quantity"=>2, "total_price"=>40}]}}
Unpermitted parameters: line_items_attributes
but I'm getting Unpermitted parameters error. My Order model:
class Order < ActiveRecord::Base
belongs_to :user
belongs_to :dispatch_method
belongs_to :payment_method
has_many :line_items, :dependent => :destroy
accepts_nested_attributes_for :line_items
end
My orders_controller.rb
class OrdersController < ApplicationController
before_action :set_order, only: [:show, :edit, :update, :destroy]
def index
#orders = Order.all
end
def show
end
def new
#order = Order.new
end
def edit
end
def create
#order = Order.create(order_params)
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render action: 'show', status: :created, location: #order }
else
format.html { render action: 'new' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #order.update(order_params)
format.html { redirect_to #order, notice: 'Order was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
def destroy
#order.destroy
respond_to do |format|
format.html { redirect_to orders_url }
format.json { head :no_content }
end
end
private
def set_order
#order = Order.find(params[:id])
end
def order_params
params.require(:order).permit(:name, :surname, line_items_attributes: [:id, :work_id, :quantity, :total_price])
end
end
I'm able to create and save a new instance of order, but not of a line_item.
You can try to redefine your order_params like this:
def order_params
json_params = ActionController::Parameters.new(JSON.parse(params[:order]))
return json_params.require(:name, :surname).permit(line_items_attributes: [:id, :work_id, :quantity, :total_price])
end
As you see, I am parsing params[:order] to avoid parsing the full params var. You might need to add another json level here but I hope you get the idea.
something like this
render :json => #booking, :include => [:paypal,
:boat_people,
:boat => {:only => :name, :include => {:port => {:only => :name, :include => {:city => {:only => :name, :include => {:country => {:only => :name}}}}},
:boat_model => {:only => :name, :include => {:boat_type => {:only => :name}}}}}]

Rails, How i can create grouped_select?

I'm new in rails and i need a help.
I wanna to do a grouped selection on rails but i dont know how i can do it.
i have 3 db tables cars, car_brands and car_models. When i add new car i need to select car model, how i can do it with gtouped selection.
models/car_brand.rb
class CarBrand < ActiveRecord::Base
has_many :cars
has_many :car_models
mount_uploader :logo, CarBrandImgUploader
end
models/car_model.rb
class CarModel < ActiveRecord::Base
has_many :cars
belongs_to :car_brand
end
cars_controller.rb
class CarsController < ApplicationController
before_action :set_car, only: [:show, :edit, :update, :destroy]
before_action :set_model, only: [:index, :new, :edit]
# GET /cars
# GET /cars.json
def index
#cars = Car.all
end
# GET /cars/1
# GET /cars/1.json
def show
end
# GET /cars/new
def new
#car = Car.new
end
# GET /cars/1/edit
def edit
end
# POST /cars
# POST /cars.json
def create
#car = Car.new(car_params)
respond_to do |format|
if #car.save
if params[:ImagesCars]
params[:ImagesCars]['image'].each do |a|
#ImagesCar = #car.ImagesCars.create!(:image => a, :car_id => #car.id)
end
end
format.html { redirect_to #car, notice: 'Car was successfully created.' }
format.json { render :show, status: :created, location: #car }
else
format.html { render :new }
format.json { render json: #car.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /cars/1
# PATCH/PUT /cars/1.json
def update
respond_to do |format|
if #car.update(car_params)
if params[:ImagesCars]
params[:ImagesCars]['image'].each do |a|
#ImagesCar = #car.ImagesCars.create!(:image => a, :car_id => #car.id)
end
end
format.html { redirect_to #car, notice: 'Car was successfully updated.' }
format.json { render :show, status: :ok, location: #car }
else
format.html { render :edit }
format.json { render json: #car.errors, status: :unprocessable_entity }
end
end
end
# DELETE /cars/1
# DELETE /cars/1.json
def destroy
#car.destroy
respond_to do |format|
format.html { redirect_to cars_url, notice: 'Car was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_car
#car = Car.find(params[:id])
end
def set_model
#models = CarModel.all
#brands = CarBrand.all
end
# Never trust parameters from the scary internet, only allow the white list through.
def car_params
params.require(:car).permit(:title_en, :keys_en, :description_en, :text_en, :title_fr, :keys_fr, :description_fr, :text_fr, :title_ru, :keys_ru, :description_ru, :text_ru, :title_es, :keys_es, :description_es, :text_es, :model_id, :brand_id, :price_day, :price_week, :p_info, :images_cars => [:id, :car_id, :image])
end
end
cars/new.html.haml
= simple_form_for(#car, html: { role: 'form', multipart: true }) do |f|
= f.input :price_day, as: :integer, input_html: {class: 'form-control', placeholder: 'Price Day ej: 150'}
= f.cktext_area :text_en, as: :text, input_html: { class: 'form-control' }, :label => 'EN Website Content Text EN'
=f.input :model_id, collection: #models, as: :grouped_select, group_method: :brand_id
= f.submit 'Save'
i get this error:
undefined method `map' for nil:NilClass
Please help or explain how i can do the grouped selection.
Thx

Can't Mass assign attributes with nested form

I have 2 forms, a orders form and a products form. I would like the products form to be under the orders form. I am getting this error: Can't mass-assign protected attributes: products_attributes.
Here is my orders model
class Order < ActiveRecord::Base
attr_accessible :comments, :due_date, :order_type, :print_color, :print_location, :title,
:products
validates :order_type, :due_date, :print_color, :title, :presence => true
validates :title, :uniqueness => true
has_many :products
accepts_nested_attributes_for :products, :allow_destroy => true
end
products model
class Product < ActiveRecord::Base
attr_accessible :quantity
has_one :order
end
orders controller:
>class OrdersController < ApplicationController
# GET /orders
# GET /orders.json
def index
#orders = Order.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #orders }
end
end
# GET /orders/1
# GET /orders/1.json
def show
#order = Order.find(params[:id])
#products = #order.products.find(:all)
respond_to do |format|
format.html # show.html.erb
format.json { render json: #order }
end
end
# GET /orders/new
# GET /orders/new.json
def new
#order = Order.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #order }
end
end
# GET /orders/1/edit
def edit
#order = Order.find(params[:id])
end
# POST /orders
# POST /orders.json
def create
#order = Order.new(params[:order])
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render json: #order, status: :created, location: #order }
else
format.html { render action: "new" }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# PUT /orders/1
# PUT /orders/1.json
def update
#order = Order.find(params[:id])
respond_to do |format|
if #order.update_attributes(params[:order])
format.html { redirect_to #order, notice: 'Order was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# DELETE /orders/1
# DELETE /orders/1.json
def destroy
#order = Order.find(params[:id])
#order.destroy
respond_to do |format|
format.html { redirect_to orders_url }
format.json { head :no_content }
end
end
end
any help would be appreciated! thanks in advance.
Replace:
attr_accessible ..., :products
With:
attr_accessible ..., :products_attributes

Adding to has_one if text_field != blank or nil

I have a simple has_one relationship setup but I want to add records to Damages table only when the text_field is not blank or nil. Right now it's adding records that are blank or nil to the other table.
My view:
<%= f.fields_for :damage do |builder| %>
<%= builder.label 'Damage' %><br />
<%= builder.text_field :dam_detail %>
<% end %>
Packjob Model:
class Packjob < ActiveRecord::Base
attr_accessible :pj_damage
has_one :damage
accepts_nested_attributes_for :damage
end
Damage Model:
class Damage < ActiveRecord::Base
attr_accessible :dam_detail
belongs_to :packjob
end
How do I allow only non blank or nil values being added?
Is best practice to add logic for this to the helper?
EDIT:
Here's the controller for Packjobs:
class PackjobsController < ApplicationController
# GET /packjobs
# GET /packjobs.json
def index
#packjobs = Packjob.includes(:damage).all
#packers = Packer.find(:all)
#rigs = Rig.find(:all, :order => "rig_type_number")
respond_to do |format|
format.html # index.html.erb
format.json { render json: #packjobs }
end
end
# GET /packjobs/1
# GET /packjobs/1.json
def show
#packjob = Packjob.find(params[:id])
#packers = Packer.find(:all)
respond_to do |format|
format.html # show.html.erb
format.json { render json: #packjob }
end
end
# GET /packjobs/new
# GET /packjobs/new.json
def new
#packjob = Packjob.new
#packers = Packer.find(:all, :conditions => { :p_team => "t" }, :order => "p_name")
#rigs = Rig.find(:all, :conditions => { :rig_status => "t" }, :order => "rig_type_number")
#damage = #packjob.build_damage
##book = #author.build_book
respond_to do |format|
format.html # new.html.erb
format.json { render json: #packjob }
end
end
# GET /packjobs/1/edit
def edit
#packjob = Packjob.find(params[:id])
#packers = Packer.find(:all, :conditions => { :p_team => "t" }, :order => "p_name")
#rigs = Rig.find(:all, :conditions => { :rig_status => "t" }, :order => "rig_type_number")
end
# POST /packjobs
# POST /packjobs.json
def create
#packjob = Packjob.new(params[:packjob])
#packers = Packer.find(:all, :conditions => { :p_team => "t" }, :order => "p_name")
#rigs = Rig.find(:all, :conditions => { :rig_status => "t" }, :order => "rig_type_number")
respond_to do |format|
if #packjob.save
format.html { redirect_to #packjob, notice: 'Packjob was successfully created.' }
format.json { render json: #packjob, status: :created, location: #packjob }
else
format.html { render action: "new" }
format.json { render json: #packjob.errors, status: :unprocessable_entity }
end
end
end
# PUT /packjobs/1
# PUT /packjobs/1.json
def update
#packjob = Packjob.find(params[:id])
#packers = Packer.find(:all, :conditions => { :p_team => "t" }, :order => "p_name")
#rigs = Rig.find(:all, :conditions => { :rig_status => "t" }, :order => "rig_type_number")
respond_to do |format|
if #packjob.update_attributes(params[:packjob])
format.html { redirect_to #packjob, notice: 'Packjob was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #packjob.errors, status: :unprocessable_entity }
end
end
end
# DELETE /packjobs/1
# DELETE /packjobs/1.json
def destroy
#packjob = Packjob.find(params[:id])
#packjob.destroy
respond_to do |format|
format.html { redirect_to packjobs_url }
format.json { head :no_content }
end
end
end
Also the I want the packjob to allow for blanks in damage text_field, I just don't want the records added to the Damages table..
This is a job for validations. Specifically, you want two things:
You want your Damage class to validate that :dam_detail is not blank or nil:
class Damage < ActiveRecord::Base
# ... rest of class here ...
validates :dam_detail, :presence => true, :length => { :minimum => 1 }
end
You want your Packjob class to validate that its contained Damage object is valid:
class Packjob < ActiveRecord::Base
# ... rest of class here ...
validates_associated :damage
end
I also recommend modifying your database schema to add the restriction that the dam_detail field cannot be null. See the migrations guide for more info.
Even though its more commonly used for has_many the cocoon gem https://github.com/nathanvda/cocoon is great for this. That gem will allow you to build the relation on the fly from the front end. it will also allow you to destroy the relation too.

Resources