I am new to rails 4.I used nested attributes for multiple image upload.But i'm having few problems with this
im getting ActiveRecord::StatementInvalid in Products#index
Mysql2::Error: Unknown column 'pictures.product_id' in 'where clause': SELECT pictures. FROM pictures WHERE pictures.product_id = 11* error
My models are as follows
class Picture < ActiveRecord::Base
belongs_to :product
has_attached_file :image
end
class Product < ActiveRecord::Base
belongs_to :user
belongs_to :category
has_many :comments , dependent: :destroy
has_many :pictures
accepts_nested_attributes_for :pictures
end
products_controller.rb
class ProductsController < ApplicationController
def show
#product = Product.find(params[:id])
#comment = #product.comments.build
#category_id = #product.category_id
#category1 = Category.find_by(id: #category_id)
end
def new
#product = current_user.products.build
#product.pictures.build
end
def create
#product = current_user.Product.new(product_params)
#product.save
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: #product }
else
format.html { render :new }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
#product = Product.find(params[:id])
end
def product_params
params.require(:product).permit(:name, :price, :description, :reason, :user_id,:status,:category_id,pictures_attributes: [:image])
end
def correct_user
#product = current_user.products.find_by(id: params[:id])
redirect_to root_url if #product.nil?
end
end
Schema.rb
ActiveRecord::Schema.define(version: 20151226132302) do
create_table "pictures", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "products", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name", limit: 255
t.integer "price", limit: 4
t.text "description", limit: 65535
t.text "reason", limit: 65535
t.integer "user_id", limit: 4
t.string "image_file_name", limit: 255
t.string "image_content_type", limit: 255
t.integer "image_file_size", limit: 4
t.datetime "image_updated_at"
t.string "status", limit: 255
t.integer "category_id", limit: 4
t.integer "product_id", limit: 4
end
end
My migration file
20151226132302_add_product_id_to_product.rb
class AddProductIdToPictures < ActiveRecord::Migration
def change
add_reference :pictures, :product, index: true
end
end
Even with above migration product_id is not added to pictures model.
Can somebody help me with this?
It will be helpful if someone can give me nice reference for RAILS 4
unknown attribute 'product_id'
Suggests you don't have the product_id column in your pictures table.
If you're using has_many / belongs_to, you'll need to set the foreign_key for your belongs_to model in its table:
If you don't have the product_id column in your pictures table, you'll need to use the following:
$ rails g migration AddProductIdToPictures
# db/migrate/add_product_id_to_pictures_________.rb
class AddProductIdToPictures < ActiveRecord::Migration
def change
add_reference :pictures, :product, index: true
end
end
$ rake db:migrate
Ref: Add a reference column migration in Rails 4
Another issue you may have is that you're using .build in the new method. I know that new and build have very little difference, but I was under the impression to use new:
def new
#product = current_user.products.new
#product.pictures.build
end
You've also got an error in your create action:
def create
#NO - #product = current_user.Product.new(product_params) #-> cannot use constant
#Should be this:
#product = current_user.products.new
#product.save
end
Related
I'm new to ROR. The query I created below is functioning properly. I'm trying to prepare an interrogation. But I didn't succeed. The query is as follows;
#rad_user_group.groupname = SELECT groupname FROM radgrs INNER JOIN nas WHERE radgrs.grdefault = true AND radgrs.tenant_id = nas.tenant_id AND nas.realipaddr = "192.168.22.175" AND nas.active = true
How do I make a switch case for the following queries in another question? Returns NULL if the query fails.
Thank you for caring.
def realipaddr
request.remote_addr
end
def create
#rad_check = RadCheck.new(rad_check_params)
#rad_check.tenant_id = Na.find_by(realipaddr: realipaddr, active: :true).tenant_id
respond_to do |format|
if #rad_check.save
format.html { redirect_to #rad_check, notice: 'Rad check was successfully created.' }
format.json { render :show, status: :created, location: #rad_check }
else
format.html { render :new }
format.json { render json: #rad_check.errors, status: :unprocessable_entity }
end
end
end
RadCheck Model
class RadCheck < ApplicationRecord
has_one :rad_user_group, dependent: :destroy
after_initialize :add_rad_user_group
before_save :set_radcheck
def add_rad_user_group
self.rad_user_group ||= RadUserGroup.new if self.new_record?
end
def set_radcheck
self.rad_user_group.username = username
self.op = ":="
self.attribu = "Cleartext-Password"
end
end
class CreateRadChecks < ActiveRecord::Migration[5.2]
def change
create_table :rad_checks do |t|
t.integer :tenant_id
t.string :username
t.string :password
t.string :attribu
t.string :op
t.string :realipaddr
t.string :groupname
t.timestamps
end
end
end
Radgr Model
class Radgr < ApplicationRecord
end
class CreateRadgrs < ActiveRecord::Migration[5.2]
def change
create_table :radgrs do |t|
t.integer :tenant_id
t.string :groupname
t.string :realipaddr
t.boolean :grdefault
end
end
end
RadUserGroup Model
class RadUserGroup < ApplicationRecord
belongs_to :rad_check
end
class CreateRadUserGroups < ActiveRecord::Migration[5.2]
def change
create_table :rad_user_groups do |t|
t.integer :tenant_id
t.string :username
t.string :groupname
t.references :rad_check, foreign_key: true
t.timestamps
end
end
end
Na Model
class Na < ApplicationRecord
end
class CreateNas < ActiveRecord::Migration[5.2]
def change
create_table :nas do |t|
t.integer :tenant_id
t.string :nasname
t.string :realipaddr
t.boolean :active
end
end
end
PhpMyAdmin Query
You should better organize the object associations. The objects obviously having some sort of relations.
Like Radgr model and Na model. I think you can make relation between these two, so later you can use query command all = Radgr.includes(:nas).where("nas.realipaddr =?", "192.168.22.175") or something similar.
Also here is a good site for converting SQL to ActiveRecord query, but you need here to create your models and associations for testing.
Please check:
http://www.scuttle.io/
A little bit of background: I recently got a new job as a Rails developer which is all fine and dandy (I have a Rails background), but I am running into a problem and I cannot figure it out. The job I took involved taking over a project someone else at the company started but never finished. So I have a unfinished CRM application in my lap, and need the help of more experienced developers to point me in the right direction.
When I try to create a new job, I get an error "ActiveModel::MissingAttributeError in Jobs#new", followed by "can't write unknown attribute `opportunity_id'".
The error from the terminal is:
Started GET "/jobs/new" for 127.0.0.1 at 2016-08-17 10:07:44 -0700
Processing by JobsController#new as HTML
Rendered jobs/new.html.erb within layouts/application (2.0ms)
Completed 500 Internal Server Error in 10ms
ActionView::Template::Error (can't write unknown attribute `opportunity_id'):
1: <% #job[:opportunity_id] = params[:opportunity_id] %>
2: <% title "New #{#job.opportunity.name} Job"%>
3:
4: <%
app/views/jobs/new.html.erb:1:in `_app_views_jobs_new_html_erb__443350051_40007592'
Rendered C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.1.4/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.0ms)
Rendered C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.1.4/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.0ms)
Rendered C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.1.4/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb within rescues/layout (34.0ms)
The error comes from line 1 which is:
<% #job[:opportunity_id] = params[:opportunity_id] %>
UPDATED: Added job model and job controller, along with the view and jobs table from shcema.rb file.
Job Model:
class Job < ActiveRecord::Base
mount_uploader :file1, AttachmentUploader
belongs_to :cost_proposal
has_many :opportunities
end
Job Controller:
class JobsController < ApplicationController
before_action :set_job, only: [:show, :edit, :update, :destroy]
skip_load_and_authorize_resource
# GET /jobs
# GET /jobs.json
def index
#jobs = Job.all
end
# GET /jobs/1
# GET /jobs/1.json
def show
end
# GET /jobs/new
def new
end
# GET /jobs/1/edit
def edit
end
# POST /jobs
# POST /jobs.json
def create
#job = Job.new(job_params)
respond_to do |format|
if #job.save
format.html { redirect_to #job, notice: 'Job was successfully created.' }
format.json { render :show, status: :created, location: #job }
else
format.html { render :new }
format.json { render json: #job.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /jobs/1
# PATCH/PUT /jobs/1.json
def update
respond_to do |format|
if #job.update(job_params)
format.html { redirect_to #job, notice: 'Job was successfully updated.' }
format.json { render :show, status: :ok, location: #job }
else
format.html { render :edit }
format.json { render json: #job.errors, status: :unprocessable_entity }
end
end
end
# DELETE /jobs/1
# DELETE /jobs/1.json
def destroy
#job.destroy
respond_to do |format|
format.html { redirect_to jobs_url, notice: 'Job was successfully deleted.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_job
#job = Job.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def job_params
params.require(:job).permit(:opportunity_id, :number, :name, :flight_date, :flight_sub, :camera, :roll, :map_type, :plan_only, :lab_only, :est_hrs_model, :due_date, :edge_job_id, :custom_trans, :comp_inhouse, :delivered_date, :done, :control_in, :control_status, :at_date, :control_results, :control_check, :scan_staff, :scan_date, :scan_check, :comp_staff, :comp_date, :comp_check, :comp_sub, :comp_sub_due_date, :comp_sub_rec, :img_staff, :img_date, :img_check, :edit_staff, :edit_date, :edit_check, :notes, :file1, :file2, :file3, :file4, :file5, :add_files)
end
end
Jobs table from schema.rb:
create_table "jobs", force: true do |t|
t.integer "cost_proposal_id"
t.string "number"
t.string "name"
t.date "flight_date"
t.string "flight_sub"
t.string "camera"
t.string "roll"
t.string "map_type"
t.integer "plan_only"
t.integer "lab_only"
t.integer "est_hrs_model"
t.date "due_date"
t.integer "edge_job_id"
t.integer "custom_trans"
t.integer "comp_inhouse"
t.date "delivered_date"
t.integer "done"
t.date "control_in"
t.string "control_status"
t.date "at_date"
t.string "control_results"
t.integer "control_check"
t.string "scan_staff"
t.date "scan_date"
t.integer "scan_check"
t.string "comp_staff"
t.date "comp_date"
t.integer "comp_check"
t.string "comp_sub"
t.date "comp_sub_due_date"
t.integer "comp_sub_rec"
t.string "img_staff"
t.date "img_date"
t.integer "img_check"
t.string "edit_staff"
t.date "edit_date"
t.integer "edit_check"
t.text "notes"
t.string "file1"
t.string "file2"
t.string "file3"
t.string "file4"
t.string "file5"
t.string "add_files"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "flown"
t.integer "cust_trans"
t.integer "delivered"
t.string "at_staff"
t.integer "at_check"
end
Opportunities table from schema.rb:
create_table "opportunities", force: true do |t|
t.integer "employee_id"
t.integer "emp2_id"
t.integer "emp3_id"
t.string "name"
t.datetime "prop_date"
t.integer "opp_status_id"
t.string "delay"
t.date "con_signed"
t.integer "quote_won_id"
t.float "total_cost"
t.date "exp_close"
t.integer "pri_comp_id"
t.text "notes"
t.datetime "created_at"
t.datetime "updated_at"
t.string "lost"
t.string "won"
t.string "location"
t.integer "pm_id"
end
Jobs new view (where error is occuring):
<% #job[:opportunity_id] = params[:opportunity_id] %>
<% title "New #{#job.opportunity.name} Job"%>
<%
#job[:name] = #job.opportunity.name
#pm = #job.opportunity.pm_id
%>
<br><br>
<%= render 'form' %>
If you need more files from the project, let me know. Thanks in advance!
An ActiveModel::MissingAttributeError is raised when you try to set an attribute on a model which does not exist. Remember that ActiveRecord "automagically" creates setters and getters by reading the schema from the database.
The most common reasons are:
typo (for example the db column is named oportunity_id)
the migration which adds the column to the schema has not been run
there is no migration to add the column
Also assigning attributes to the model in the view is a pretty bad code smell. Do it in the controller instead:
class JobsController < ApplicationController
# ...
def new
#job = Job.new do |j|
if params[:opportunity_id].present?
j.opportunity_id = params[:opportunity_id]
end
end
end
# ...
end
On line 2 of your view, it looks like you're expecting new jobs to already have an associated opportunity.
<% title "New #{#job.opportunity.name} Job"%>
If this is the case, then the job routes should be nested under opportunities. So in config/routes.rb
resources :opportunities do
resources :jobs
end
You can then create new jobs through http://localhost:3000/opportunities/:id/jobs/new
And in your JobsController:
def new
#opportunity = Opportunity.find(params[:opportunity_id])
#job = Job.new(opportunity: #opportunity)
# ...
So when I look through your two table definitions I see that 1) there is no opportunity_id key in jobs and conversely, 2) no job_id key in opportunities. In order for your has_many :opportunities to work, you need to add a job_id field to the opportunities table. Here is a vastly simplified example of what I mean:
def Job < ActiveRecord::Base
has_many :opportunities
end
def Opportunity < ActiveRecord::Base
end # shown for completeness of answer only
You will need to add the job_id foreign key to the opportunities table with a migration, for example:
class AddJobForeignKeyToOpportunities < ActiveRecord::Migration
def change
add_column :opportunities, :job_id, :integer
end
end
If you're unsure how to deal with the migration, check out the Rails Guide for the rails command-line tool. Once you have that in place Rails will automagically give you access to the Opportunities associated with a Job as you might expect:
job = Job.first
job.opportunities
Keep in mind that you still won't be able to access job.opportunity_id as the error in your original question mentions. The many to one association you've set up requires that the Opportunity model have the foreign key. However, Rails will give you access to job.opportunity_ids plural.
[edit] To add an opportunity to a job you'll want to do something along the lines of:
opportunity = Opportunity.find(params[:opportunity_id])
job.opportunities << opportunity
You should always avoid referring to the foreign key directly on the associated model. Someone said this somewhere in another answer or comment here but I can't find it to credit them.
Instead rely on the Rails provided methods. In this example above, the << operator is effectively setting job_id on the opportunity to link them up.
I'm new to rails so I'm still trying to figure things out so any help is greatly appreciated! I am building an app that will define "seasons" and there will be multiple "danceclasses" associated with those seasons. After you create a season, you should have the option to create "danceclasses" so as part of my show on the seasons I have:
<h2>Dance Classes Created</h2>
<%= #seasons.danceclass.each do |danceclass| %>
<p>
However I get the following error:
undefined method `danceclass' for nil:NilClass
My data model is I have a seasons table, a danceclasses table and a season_danceclasses table.
My model for seasons is this:
class Season < ActiveRecord::Base
has_many :season_class
has_many :danceclass, through: :season_class
end
My model for dance classes looks like this:
class Danceclass < ActiveRecord::Base
belongs_to :season
has_many :student_class
has_many :student, through: :student_class
end
And my model for season_danceclass looks like this:
class SeasonDanceclasses < ActiveRecord::Base
belongs_to :season
belongs_to :danceclass
end
My season_controller looks like this:
class SeasonsController < ApplicationController
before_action :set_season, only: [:show, :edit, :update, :destroy]
# GET /seasons
# GET /seasons.json
def index
#seasons = Season.all
end
# GET /seasons/1
# GET /seasons/1.json
def show
end
# GET /seasons/new
def new
#season = Season.new
end
# GET /seasons/1/edit
def edit
end
# POST /seasons
# POST /seasons.json
def create
#season = Season.new(season_params)
respond_to do |format|
if #season.save
format.html { redirect_to #season, notice: 'Season was successfully created.' }
format.json { render :show, status: :created, location: #season }
else
format.html { render :new }
format.json { render json: #season.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /seasons/1
# PATCH/PUT /seasons/1.json
def update
respond_to do |format|
if #season.update(season_params)
format.html { redirect_to #season, notice: 'Season was successfully updated.' }
format.json { render :show, status: :ok, location: #season }
else
format.html { render :edit }
format.json { render json: #season.errors, status: :unprocessable_entity }
end
end
end
# DELETE /seasons/1
# DELETE /seasons/1.json
def destroy
#season.destroy
respond_to do |format|
format.html { redirect_to seasons_url, notice: 'Season was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_season
#season = Season.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def season_params
params.require(:season).permit(:season_name, :season_start, :season_end)
end
end
What am I doing wrong?
EDIT: Adding Schema.rb
# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160729111417) do
create_table "danceclasses", force: :cascade do |t|
t.string "class_id", limit: 255
t.string "class_name", limit: 255
t.text "class_description", limit: 65535
t.integer "min_students", limit: 4
t.integer "max_students", limit: 4
t.string "category", limit: 255
t.datetime "start_date"
t.datetime "end_date"
t.integer "week_frequency", limit: 4
t.integer "day_frequency", limit: 4
t.string "start_time", limit: 255
t.string "end_time", limit: 255
t.integer "fee", limit: 4
t.string "level", limit: 255
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "season_classes", force: :cascade do |t|
t.integer "season_id", limit: 4
t.integer "danceclass_id", limit: 4
end
create_table "seasons", force: :cascade do |t|
t.string "season_name", limit: 255
t.datetime "season_start"
t.datetime "season_end"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "student_classes", force: :cascade do |t|
t.integer "student_id", limit: 4
t.integer "class_id", limit: 4
end
create_table "students", force: :cascade do |t|
t.string "first_name", limit: 255
t.string "last_name", limit: 255
t.string "student_id", limit: 255
t.datetime "date_of_birth"
t.text "notes", limit: 65535
t.string "gender", limit: 255
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "user_students", force: :cascade do |t|
t.integer "user_id", limit: 4
t.integer "student_id", limit: 4
end
create_table "users", force: :cascade do |t|
t.string "username", limit: 255
t.string "email", limit: 255
t.string "password", limit: 255
t.string "first_name", limit: 255
t.string "last_name", limit: 255
t.string "phone_number", limit: 255
t.datetime "date_of_birth"
t.string "street_1", limit: 255
t.string "street_2", limit: 255
t.string "city", limit: 255
t.string "state", limit: 255
t.string "zipcode", limit: 255
t.boolean "enabled"
t.boolean "is_admin"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
You need to change your has_many association properly.
class Season < ActiveRecord::Base
has_many :season_classes
has_many :danceclasses, through: :season_class
end
Hope this help you!
First of all the associations you have taken should be plural for has_many,
class Season < ActiveRecord::Base
has_many :season_classes
has_many :dance_classes, through: :season_classes
end
class Danceclass < ActiveRecord::Base
belongs_to :season
has_many :student_classes
has_many :students, through: :student_classes
end
class SeasonDanceclasses < ActiveRecord::Base
belongs_to :season
belongs_to :danceclass
end
Now, as you said that view is show page for season your season show action is,
class SeasonsController < ApplicationController
before_action :set_season, only: [:show, :edit, :update, :destroy]
def index
#seasons = Season.all
end
def show
end
end
Your show method contains #season variable but not #seasons, which was set in set_season action,
so app/views/seasons/show.html.erb is,
This is with your old association
<h2>Dance Classes Created</h2>
<% #season.danceclass.each do |danceclass| %>
-----------
----------
<% end %>
<p></p>
This is with changed associations
<h2>Dance Classes Created</h2>
<% #season.dance_classes.each do |danceclass| %>
-----------
----------
<% end %>
<p></p>
I've been trying to get the answer to this problem but without any luck. I guess it's an association problem and probably a rookie mistake (I'm one).
This is the functionality:
I need to create packs of beers for specific profiles (I know everything sounds fun with beers but it's killing me)
I have 3 models:
A beer model:
class Beer < ActiveRecord::Base
include PermissionsConcern
validates :name, presence: true
has_many :ratings
has_many :users, through: :ratings
has_many :packs
end
A profile model:
class Profile < ActiveRecord::Base
has_many :packs
end
A Pack model:
class Pack < ActiveRecord::Base
belongs_to :beer
belongs_to :profile
end
This is the packs_controller
class PacksController < ApplicationController
before_action :set_pack, only: [:show, :edit, :update, :destroy]
def index
#packs = Pack.all
end
def show
end
def edit
#beers = Beer.all #Implementación incompleta. Revisar Filtros
#profiles = Profile.all
end
def create
#pack = Pack.new(pack_params)
respond_to do |format|
if #pack.save
format.html { redirect_to #pack, notice: 'Pack was successfully created.' }
else
format.html { render :new }
end
end
end
def update
respond_to do |format|
if #pack.update(pack_params)
format.html { redirect_to #pack, notice: 'Pack was successfully updated.' }
else
format.html { render :edit }
end
end
end
...
private
def set_pack
#pack = Pack.find(params[:id])
end
def pack_params
params.require(:pack).permit(:delivery_date, :profile_id, :beer_id, :status)
end
end
With this configuration I have the following situation:
in the Index view I do
#packs.each do |p|
p.beer.name #works fine
p.profile.name #brings an "undefined method `name' for nil:NilClass" message
end
In the show view I do:
#pack.beer.name #works fine.
#pack.profile.name #WORKS FINE ALSO
I tried to do it in the console and the results are the same:
Pack.last.profile.name # works fine
Pack.all # works and shows the profile_id correctly.
packs = Pack.all
packs.each do |p|
print p.beer.name #works fine
print p.profile.name #nil class again
end
Just in case I'm including the Schema:
create_table "beers", force: :cascade do |t|
t.string "name", limit: 255
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "beer_type", limit: 255
end
create_table "packs", force: :cascade do |t|
t.date "delivery_date"
t.integer "profile_id", limit: 4
t.integer "beer_id", limit: 4
t.integer "status", limit: 4
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "packs", ["beer_id"], name: "index_packs_on_beer_id", using: :btree
add_index "packs", ["profile_id"], name: "index_packs_on_profile_id", using: :btree
create_table "profiles", force: :cascade do |t|
t.string "ibu_range", limit: 255
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name", limit: 255
end
add_foreign_key "packs", "beers"
add_foreign_key "packs", "profiles"
end
I tried to explain the situation as detailed as possible. Can anyone help me understand what I'm doing wrong? Thanks!!!
Some of the packs may not have profile?
Since you are using console, try this:
Pack.all.select{|item| item.profile.nil?}.size
If size>0 and you don't want this, then please add validates :profile, presence: true.
I've managed to get a few HABTM relationships set up without any problems, but for some reason I can't make a belongs_to/has_many relationship record the values.
An Article belongs_to a Type (news, editorial, chronicle, etc.)
A Type has_many Articles
Schema.db shows the type_id integer column, the models use belongs_to and has_many and a drop down of article types appears in the form on the new/edit article pages.
But on choosing a type from the drop down (e.g. 'chronicle'), it says it creates or edits the article successfully but does not register the link between the article and 'chronicle'. On going back to edit the same article, the drop down just shows the top type ('analysis'), not 'chronicle'.
So not sure where I'm going wrong. Here are all the relevant bits, starting with the database.
From schema.db:
create_table "articles", force: :cascade do |t|
t.string "headline"
t.string "lede"
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "type_id"
end
create_table "types", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Then the models:
class Article < ActiveRecord::Base
has_and_belongs_to_many :categories
has_and_belongs_to_many :regions
has_and_belongs_to_many :stories
belongs_to :type
end
class Type < ActiveRecord::Base
has_many :articles
end
And the articles controller:
# GET /articles/new
def new
#article = Article.new
#regions = Region.all.order(:region)
#categories = Category.all.order(:category)
#stories = Story.all.order(:story)
#types = Type.all.order(:name)
end
# GET /articles/1/edit
def edit
#regions = Region.all.order(:region)
#categories = Category.all.order(:category)
#stories = Story.all.order(:story)
#types = Type.all.order(:name)
end
# POST /articles
# POST /articles.json
def create
#article = Article.new(article_params)
respond_to do |format|
if #article.save
format.html { redirect_to #article, notice: 'Article was successfully created.' }
format.json { render :show, status: :created, location: #article }
else
format.html { render :new }
format.json { render json: #article.errors, status: :unprocessable_entity }
end
end
end
/* …and then at the bottom… */
def article_params
params.require(:article).permit(:headline, :lede, :body, :category_ids => [], :region_ids => [], :story_ids => [], :type_id => [])
end
And finally in the articles form:
<strong>Type:</strong> <%= f.collection_select :type_id, #types, :id, :name %>
Any ideas?
You need to change the article_params to below
def article_params
params.require(:article).permit(:headline, :lede, :body, :type_id, :category_ids => [], :region_ids => [], :story_ids => [])
end
Notice the change :type_id => [] to :type_id
As there will be only one type_id in each articles record, your required params should not contain array of type_id. so change it to only :type_id instead of :type_id => []
def article_params
params.require(:article).permit(:headline, :lede, :body, :type_id, :category_ids => [], :region_ids => [], :story_ids => [])
end