I can't insert to my database rails - ruby-on-rails

i can't insert to my database whats is my problem?
it's bowling game and i have two tables with name "Player" and "Result"
view
<%= form_for player_new_path(#player) do |f|%>
<div class="text_field">
<p>
<%= f.label "Spelare namn" %>
<%= f.text_field :name %>
</p>
<p>
<%= f.submit "Lägg till en spelare"%>
</p>
</div>
Controller
def create
#player = Player.new(params[:players])
if #player.save
redirect_to players_new_path
else
render :action => "new"
end
end
Not work :/
my model:
class Player < ActiveRecord::Base # attr_accessible :title, :body
belongs_to :result
end
and my migrations:
class CreatePlayers < ActiveRecord::Migration
def change
create_table :players do |t|
t.string "name"
t.references :results
t.timestamps
end

Check your params hash. I bet the key isn't 'players', it's probably 'player'.

#player = Player.new(params[:players]) should probably be #player = Player.new(params[:player]) (You are getting a single player as a param)
Otherwise, what error are you getting

Related

Create objects based on received data from params in Ruby on Rails

Description
I am trying to create messages based on selected (via check box) users from the browser in Ruby on Rails.
Snapshot:
Steps to reproduce
My schema
ActiveRecord::Schema.define(version: 2021_11_13_142255) do
create_table "messages", force: :cascade do |t|
t.text "content"
t.integer "user_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "role"
t.integer "phone"
t.boolean "admin"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
end
messages_controller.rb
class MessagesController < ApplicationController
def new
#users = User.all
#message = Message.new(message_params)
end
def create
params[:user_objs].each do |u|
# "params.inspect" returns
# {"authenticity_token"=>"[FILTERED]",
# "user_objs"=>
# ["{\"id\":1,\"name\":\"Alex\",\"role\":\"Engineer\",\"phone\":998943333303,\"admin\":true,\"created_at\":\"2021-11-13T14:37:54.962Z\",\"updated_at\":\"2021-11-13T14:37:54.962Z\"}",
# "{\"id\":2,\"name\":\"Lucy\",\"role\":\"Accountant\",\"phone\":998943333303,\"admin\":false,\"created_at\":\"2021-11-13T14:39:52.742Z\",\"updated_at\":\"2021-11-13T14:39:52.742Z\"}"],
# "message"=>{"content"=>"Message from the browser"},
# "commit"=>"Send"}
person = JSON.parse(u)
#message = person.messages.new(message_params)
if #message.save
redirect_to root_path
else
#users = User.all
render :new
end
end
end
private
def message_params
params.permit(
:content,
:user_id
)
end
end
messages => new.html.erb
<div>
<h1>Create and send a new message!</h1>
<%= form_for(#message) do |form| %>
<% if #message.errors.any? %>
<div class="alert alert-danger">
<h5 class="fw-bold">Invalid input!</h5>
<%= #message.errors.full_messages.each do |error| %>
<div><%= error %></div>
<% end %>
</div>
<% end %>
<% #users.each do |u| %>
<div>
<p><%= check_box_tag "user_objs[]", u.to_json %> <%= u.name %></p>
</div>
<% end %>
<p class="mb-3">
<%= form.label :content, class: "form-label" %>
<%= form.text_field :content, class: "form-control", autofocus: true, placeholder: "John_D" %>
</p>
<p class="mb-3">
<%= form.submit "Send", class: "btn btn-primary" %>
</p>
<% end %>
</div>
<%= params.inspect %>
Models
# user.rb
class User < ApplicationRecord
has_many :messages
end
# message.rb
class Message < ApplicationRecord
belongs_to :user
end
Expected behavior
I was expecting the creation of messages for all selected users
Actual behavior
NoMethodError in MessagesController#create
undefined method `messages' for #<Hash:0x000000011fe2b420>
I tried different ways, but can't convert Ruby objects to JSON in my params user_objs[] so that I can parse it in my controller to create messages based on those selected users in the user_objs[] params.
Environment info
ruby -v
ruby 2.7.3p183 (2021-04-05 revision 6847ee089d) [arm64-darwin20]
rails -v
Rails 6.1.4.1
Thanks for any given help 🙏
If you want to create a system where you send a single message to multiple users you would setup a join table:
class User < ApplicationRecord
has_many :user_messages
has_many :recieved_messages, though: :user_messages,
source: :message,
inverse_of: :recipients
end
# rails g model user_message user:belongs_to message:belongs_to read:boolean
class UserMessage < ApplicationRecord
belongs_to :user
belongs_to :message
# make sure to add a compound unique index to the migration as well
validates_uniqueness_of :user_id, scope: :message_id
delegate :content, to: :message
end
class Message < ApplicationRecord
has_many :user_messages
has_many :recipients, though: :user_messages,
source: :user,
inverse_of: :recieved_messages
end
has_many :recipients will create a recipient_ids= setter and a recipient_ids getter that you can use in your form:
<div>
<h1>Create and send a new message!</h1>
<%= form_with(model: #message) do |form| %>
<% if #message.errors.any? %>
<div class="alert alert-danger">
<h5 class="fw-bold">Invalid input!</h5>
<%= #message.errors.full_messages.each do |error| %>
<div><%= error %></div>
<% end %>
</div>
<% end %>
<p class="mb-3">
<%= form.collection_checkboxes(:recipient_ids, #users, :id, :name) %>
</p>
<p class="mb-3">
<%= form.label :content, class: "form-label" %>
<%= form.text_field :content, class: "form-control", autofocus: true, placeholder: "John_D" %>
</p>
<p class="mb-3">
<%= form.submit "Send", class: "btn btn-primary" %>
</p>
<% end %>
</div>
There is absolutely no need to pass the entire record as JSON - you just pass an array of IDs and rails will do all the work of creating the join table rows for you:
class MessagesController < ApplicationController
def new
#users = User.all
#message = Message.new
end
def create
#message = Message.new(message_params)
if #message.save
redirect_to root_path
else
#users = User.all
render :new
end
end
private
def message_params
params.require(:message)
.permit(
:content,
recipient_ids: []
)
end
end
This avoids the complexity of creating multiple records from a single request and the whole conundrum that you're binding the form to a single instance of Message but creating a bunch of records which is bound to lead to confusion.
If you want to create multiple records at once it can be done but the complexity is far higher and you have to deal with stuff like how to handle errors if creating one message fails and this might be beyond your current skill level.
The issue is that you are assigning a json object/hash in person = JSON.parse(u). This is not an active record so when doing person.messages it throws the error. I believe what you need in the create action is something like:
user = JSON.parse(u)
# make sure user.inspect gives you the user object you want
person = User.find(user["id"])
# person.inspect should give you the active record for the user

Passing foreign key automatically from view to controller using HABTM models

I have two models, Companies and Employees, with a many-to-many association between them.
class Company < ActiveRecord::Base
has_and_belongs_to_many :employees
end
class Employee < ActiveRecord::Base
has_and_belongs_to_many :companies
end
I have a join table :companies_employees
class CreateCompaniesEmployeesJoin < ActiveRecord::Migration
def change
create_table :companies_employees, :id => false do |t|
t.integer "company_id"
t.integer "employee_id"
end
add_index :companies_employees, ["company_id", "employee_id"]
end
end
I have a Show view for Company, which includes a form_for adding a new Employee, who I want to associate with that Company via the HABTM association:
<%= form_for :employee, :url => employees_path do |f| %>
<p>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
</p>
<br>
<p>
<%= f.hidden_field :company_id, :value => #company.id %>
</p>
<p>
<%= f.submit "Save Employee", class: "btn btn-default" %>
</p>
<% end %>
I have a controller for Employee, through which I want to create a new Employee that will be automatically associated with the Company from the Company Show view:
def create
#company = Company.find(params[:company_id])
#employee = Employee.new(employee_params)
#company.employees << #employee
if #employee.save
flash[:success] = "Company Employee Added!"
redirect_to #employee
else
render 'new'
end
end
When I use the form to try to create a new employee, I get an error in EmployeeController -- "Couldn't find Company without an ID"
Seems my view is failing to pass the :company_id on to the create action in the EmployeeController.
I've scoured other posts and nothing seems to be on point. Any suggestions most appreciated!
Ok, the problem seems to be the nested attribute.
Try to change in the EmployeesController#create the first row in:
#company = Company.find(params[:employee][:company_id])
EDIT
Alternatively, and probably more easy, you can also change the form hidden_field like this:
hidden_field_tag(:company_id, #company.id)

How do I create a select box using two tables with a relationship?

I'm trying to create a select box that shows all my ejecutive_name and last_name from my table Ejecutives in my Policies view,but i need to create a search button to get parameters from Ejecutives that i selected
My models have a relationship:
class Policy < ActiveRecord::Base
unloadable
belongs_to :ejecutive
has_many :policy
end
class Ejecutive < ActiveRecord::Base
has_many :policies
end
My tables have a relationship by ejecutive_id:
class CreateEjecutives < ActiveRecord::Migration
def self.up
create_table :ejecutives do |t|
t.string :name,:null=>false
t.string :lastname1,:null=>false
t.timestamps
end
end
def self.down
drop_table :ejecutives
end
end
class CreatePolicies < ActiveRecord::Migration
def self.up
create_table :policies do |t|
t.string :num_policy, :null=>false
t.integer :ejecutive_id
t.timestamps
end
end
def self.down
drop_table :policies
end
end
This is my controller:
class PolicyManagement::PolicyController < ApplicationController
#ejecutives = Ejecutive.find(:all)
#policies = Policy.find(:all)
end
This is my view:
Select Ejecutive:
%= select_tag 'ejecutives',"<option value=\"\">Seleccione</option>"+options_for_select(#ejecutives.collect {|t| [t.name.to_s+" "+t.lastname1.to_s,t.id]})%>
Results
<% #policies.each do |policy| %>
<p> <%= policy.num_policy%> </p>
<p> <%= policy.ejecutive.name %> </p>
<p> <%= policy.ejecutive.last_name %> </p>
<% end %>
I tried this
<% form_tag :controller=>"policy_management/policy",:action =>"generate_print_ejecutive_comercial", :method => 'get' do %>
<p>
<%= text_field_tag :search,params[:search] %>
<%= select_tag "Ejecutives", options_from_collection_for_select(#ejecutives, "id", "name") %>
#Here i in select_tag "ejecutives" need to add searh params..
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
I'm using Rails 2.3.5.
Does somebody know about this problem? I'd really appreciate help.
If i understand correctly, you want the policies for a selected ejecutive, you can do this by saying Ejecutive.find().policies. If want a search button, put your select box in a form tag and post it. In the controller action, you will get the selected id, with which you can execute the line i mentioned above.Hope this helps.

I am getting the error NoMethodError in CarController#add

NoMethodError in CarController#add
undefined method `user_id=' for #<Car:0x7160c70>
RAILS_ROOT: C:/Users/Jatinder/BitNami RubyStack projects/mercedes_mod 2
add.html (for adding car)
<h1>Ask a Question or Discuss Your Car</h1>
<%= error_messages_for :car %>
<br>
<p>You can ask anything related to cars even if its not a Mercedes!</p>
<% form_for :car do |f| %>
<p>
<%= f.label :name, "Title of Question" %>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :description, "Describe Your Question" %>
<%= f.text_area :description %>
</p>
<p>
<%= f.submit "Add" %>
</p>
<% end %>
def add in car_controller.rb:
def add
#title = "Ask a New Question"
if request.post?
#car = Car.new(params[:car])
#car.user_id = User.logged_in(session).id
if #car.save
flash[:notice] = "Car #{#car.name} added!"
redirect_to :controller => :car, :action => :index
end
end
end
car.rb model:
class Car < ActiveRecord::Base
belongs_to :user
belongs_to :subject
validates_presence_of :name, :description
end
routes.rb
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
map.resources :car, :users => { :delete => :get }
map.root :controller => "main"
map.root :controller => "car", :action => "destroy"
end
create_cars migration:
class CreateCars < ActiveRecord::Migration
def self.up
create_table :cars do |t|
t.interger :user_id
t.string :name
t.string :description
t.timestamps
end
end
def self.down
drop_table :cars
end
end
Two errors:
user_id is declared as an "inte r ger"
I think you meant to write user = rather than user_id =
Chuck is correct. Your user_id is declared as an "interger". Consider using
t.references :user
instead of t.integer :user_id.
Also verify that your user model declares it's connection to the car model using has_one or has_many.
If User.logged_in(session) returns a User model object, you can do #car.user = User.logged_in(session) If not your code should work fine.
I want to know how is relation defined in your User model, might be you not defined the relation in User model due which its not able to find the user_id

Ruby on Rails default value on form

Hey, need a little help here.
I have two models:
class User < ActiveRecord::Base
has_many :jobs
end
and
class Job < ActiveRecord::Base
belongs_to :user
end
When i do migration i put
class CreateJobs < ActiveRecord::Migration
def self.up
create_table :jobs do |t|
t.references :user
.....
What should i put on my jobs/new action for user_id?
I use resfull_authentication, so i have current_user helper.
<% form_for(#job) do |f| %>
<%= f.error_messages %>
<p>
User:
<%= f.label current_user.login %> #works fine for me! current_user.id works fine two!
??????????????? But what should i put for value???????
</p>
<p>
<%= f.label :filename %><br />
<%= f.text_field :filename %>
</p>
Should i put current_user.id on controller? If so, how ?
Please help! Thank you very much!
Edit after more info:
In your controller, do something like:
#user = User.find_by_id(session[:user_id])
#job = Job.new(params[:job])
#user.jobs << job
Original answer:
You could have something like:
<%= f.collection_select :user_id, User.find(:all, :order => "name ASC"),
:id, :name, {:include_blank => true} %>
This'll give you a dropdown with user names in alphabetical order.
def new
#job = current_user.jobs.new
end
def create
#job = current_user.jobs.build(params[:job])
if #job.save
redirect_to #job
else
render 'new'
end
end
When the job gets created, the user_id column will automatically be assigned to the current_user id.
Is this what you're trying to do?
You can use hidden field tag.
View:
<%= hidden_field_tag 'user_id', current_user.id %>

Resources