Has many through association with works from console not from controller. - sql

I have a problem with a has_many through association.
Somehow u.groups.create!(:name => "test group", :school => "the school") makes a correct insert with the trace:
(0.1ms) begin transaction SQL (4.5ms) INSERT INTO "groups"
("created_at", "findeble", "name", "school", "updated_at") VALUES (?,
?, ?, ?, ?) [["created_at", Tue, 01 Oct 2013 08:13:36 UTC +00:00],
["findeble", false], ["name", "test group"], ["school", "the school"],
["updated_at", Tue, 01 Oct 2013 08:13:36 UTC +00:00]] SQL (0.3ms)
INSERT INTO "usergroups" ("created_at", "group_id", "updated_at",
"user_id") VALUES (?, ?, ?, ?) [["created_at", Tue, 01 Oct 2013
08:13:36 UTC +00:00], ["group_id", 7], ["updated_at", Tue, 01 Oct 2013
08:13:36 UTC +00:00], ["user_id", 1]] (0.5ms) commit transaction
=> #
But when I try via the groups_controller
# GET /groups/new
# GET /groups/new.json
def new
#group = current_user.groups.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #group }
end
end
def create
#group = current_user.groups.new(params[:group])
respond_to do |format|
if #group.save
format.html { redirect_to #group, notice: 'Group was successfully created.' }
format.json { render json: #group, status: :created, location: #group }
else
format.html { render action: "new" }
format.json { render json: #group.errors, status: :unprocessable_entity }
end
end
end
This creates the trace:
Started POST "/groups" for 127.0.0.1 at 2013-10-01 10:20:15 +0200
Processing by GroupsController#create as HTML Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"frETQoB5Mu2gLnIBG644i09XDOHFsEBTGEvrEQmfgPA=",
"group"=>{"name"=>"Test group2", "school"=>"Another school",
"findeble"=>"1"}, "commit"=>"Create Group"} User Load (0.2ms)
SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
(0.1ms) begin transaction SQL (0.8ms) INSERT INTO "groups"
("created_at", "findeble", "name", "school", "updated_at") VALUES (?,
?, ?, ?, ?) [["created_at", Tue, 01 Oct 2013 08:20:15 UTC +00:00],
["findeble", true], ["name", "Test group2"], ["school", "Another
school"], ["updated_at", Tue, 01 Oct 2013 08:20:15 UTC +00:00]]
(6.1ms) commit transaction
This only creates a new group record and not a record in the joined table. I cant understand what makes this difference.

You need to use build method:
current_user.groups.build(params[:group])

lol007 is right or you can also do it like that
In new action
#group = current_user.groups.build
And in create action
#group = current_user.groups.create(params[:group])

Related

Unable to create record via nested attributes Rails API

I'm currently trying to create an Order instance. There is an association of the model Order with Items. The association is as follows. Order has many Items. I try following the documentation https://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
class Order < ApplicationRecord
has_many :items
accepts_nested_attributes_for :items
end
class OrdersController < ApplicationController
##
private
def order_params
params.require(:order).permit(:description,
items_attributes: [:id, :quantity])
end
end
From the following post, it shows that the id has to be pass in the params. Rails 5 Api create new object from json with nested resource
params = {order: {description: "this is a test"}, items_attributes: [{id: 3, quantity: 3, description: 'within order -> item'}]}
=> {:order=>{:description=>"this is a test"}, :items_attributes=>[{:id=>3, :quantity=>3, :description=>"within order -> item"}]}
[7] pry(main)> order_test = Order.create!(params[:order])
(0.4ms) BEGIN
Order Create (62.9ms) INSERT INTO "orders" ("description", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["description", "this is a test"], ["created_at", "2019-05-30 23:31:39.409528"], ["updated_at", "2019-05-30 23:31:39.409528"]]
(4.6ms) COMMIT
=> #<Order:0x00007ff91556e4b8 id: 14, description: "this is a test", created_at: Thu, 30 May 2019 23:31:39 UTC +00:00, updated_at: Thu, 30 May 2019 23:31:39 UTC +00:00>
I create an order however when I check for the items it returns an empty array.
=> #<Order:0x00007ff9142da590 id: 14, description: "this is a test", created_at: Thu, 30 May 2019 23:31:39 UTC +00:00, updated_at: Thu, 30 May 2019 23:31:39 UTC +00:00>
[11] pry(main)> Order.last.items
Order Load (0.4ms) SELECT "orders".* FROM "orders" ORDER BY "orders"."id" DESC LIMIT $1 [["LIMIT", 1]]
Item Load (0.3ms) SELECT "items".* FROM "items" WHERE "items"."order_id" = $1 [["order_id", 14]]
=> []
Here is the table for items:
class CreateItems < ActiveRecord::Migration[5.2]
def change
create_table :items do |t|
t.references :order, foreign_key: true
t.integer :quantity
t.string :description
t.timestamps
end
end
end
What is wrong?
The mistake was in the order the parameters were being passed.
{:order=>{:id=>22, :description=>"this is a test", :items_attributes=>[{:order_id=>22, :quantity=>3, :description=>"within order -> item"}]}}
This solved it:
order = Order.create!(params[:order])
<Order:0x00007ff918039ee0 id: 22, description: "this is a test", created_at: Fri, 31 May 2019 01:39:23 UTC +00:00, updated_at: Fri, 31 May 2019 01:39:23 UTC +00:00>
[39] pry(main)> order.items
Item Load (114.8ms) SELECT "items".* FROM "items" WHERE "items"."order_id" = $1 [["order_id", 22]]
=> [#<Item:0x00007ff9180394b8
id: 4,
order_id: 22,
quantity: 3,
description: "within order -> item",
created_at: Fri, 31 May 2019 01:39:23 UTC +00:00,
updated_at: Fri, 31 May 2019 01:39:23 UTC +00:00>]

Rails attributes not updating

I'm building an invitation system where a user can either invite a friend, setting their user.id to the sender field in the database, or request an invitation, which should set the sender to '0' (an integer field).
User model
...
has_many :invites, :class_name => 'Invitation', :foreign_key => 'sender' #sent_invitations
belongs_to :invitation
...
Invitation model
belongs_to :sender, :class_name => 'User'
has_one :recipient, :class_name => 'User'
Invitations controller
def create
#invitation = Invitation.new(invitation_params)
if current_user?
#invitation.sender = current_user
if #invitation.save
redirect_to invitations_url, notice: 'Thank you. Your invitation has been sent.'
else
render action: "new"
end
else
#invitation.sender = 0
if #invitation.save
redirect_to invitations_url, notice: 'Thank you. You request is being processed..'
else
render action: "new"
end
end
end
The invitation is being created (I can see it in the database), but the sender isn't being set. This is the output form the dev_log:
Started POST "/invitations" for 127.0.0.1 at 2016-05-14 17:49:54 -0600
Processing by InvitationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"aCasBmkfw0m1T/EwuBUlXTA/z+REEWo3Hpv2HpB9w6s=", "invitation"=>{"name"=>"john", "surname"=>"public", "recipient_email"=>"jp#sasdf.com"}, "commit"=>"Create Invitation"}
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."auth_token" = 'i__MG0iqyoIND68k6qJmvw' LIMIT 1
DEPRECATION WARNING: You're trying to create an attribute `sender_id'. Writing arbitrary attributes on a model is deprecated. Please just use `attr_writer` etc. (called from create at C:/Sites/template/app/controllers/invitations_controller.rb:38)
(0.0ms) begin transaction
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."email" = 'jp#sasdf.com' LIMIT 1
SQL (1.0ms) INSERT INTO "invitations" ("created_at", "invite_token", "name", "recipient_email", "sender", "sent_at", "surname", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?) [["created_at", Sat, 14 May 2016 23:49:55 UTC +00:00], ["invite_token", "m_1zd0UxW3W1JqoDdp1EMA"], ["name", "john"], ["recipient_email", "jp#sasdf.com"], ["sender", nil], ["sent_at", nil], ["surname", "public"], ["updated_at", Sat, 14 May 2016 23:49:55 UTC +00:00]]
(0.0ms) UPDATE "users" SET "invites_avail" = 4, "updated_at" = '2016-05-14 23:49:55.161966' WHERE "users"."id" = 2
(70.0ms) commit transaction
Redirected to http://localhost:3000/invitations
Completed 302 Found in 193.0ms (ActiveRecord: 76.0ms)
I'm stumped because #1, I'm not creating an arbitrary attribute "sender_id". The applicable column in the database is "sender", and #2, the POST isn't setting the sender id, which should either be "0" or the id of the current_user.
What am I doing wrong?
I couldn't find an answer to my question, so I monkeyed it instead.
Since I'm able to get the invitation.sender to save when the invitation is sent from a current_user, and the rest were just setting nothing (NULL) in the database, I changed the query parameters in the invitations_controller.rb to look for #invitation.sender = nil for all corporate-sent invitations.
I'll leave this up until/unless someone posts a better response. Cheers!

Ruby NoMethodError - undefined method `blah_url' for BlahController

I am calling this js from a link:
function createNewTopLevelEntry(){
var user_id = $("#user").val();
var header = prompt("Enter the name");
$.ajax( '/users/' + user_id + '/entries', {
data: {
entry: { header: header,
user: user_id } },
type: 'POST',
cache: false,
dataType: 'json',
success: displayTopLevelEntries
});
}
It hits this controller:
def create
#entry = Entry.new(params[:entry])
respond_to do |format|
if #entry.save
format.html { redirect_to #entry, notice: 'Entry was successfully created.' }
format.json { render json: #entry, status: :created, location: #entry }
else
format.html { render action: "new" }
format.json { render json: #entry.errors, status: :unprocessable_entity }
end
end
end
This is the response on the server:
Started POST "/users/1/entries" for 127.0.0.1 at 2013-03-25 21:50:36 -0700
Processing by EntriesController#create as JSON
Parameters: {"entry"=>{"header"=>"Hi", "user"=>"1"}, "user_id"=>"1"}
(0.1ms) begin transaction
SQL (0.5ms) INSERT INTO "entries" ("completed", "created_at", "endtime", "header", "parent", "starttime", "starttimeset", "text", "totaltime", "updated_at", "user") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["completed", nil], ["created_at", Tue, 26 Mar 2013 04:50:36 UTC +00:00], ["endtime", nil], ["header", "Hi"], ["parent", nil], ["starttime", nil], ["starttimeset", nil], ["text", nil], ["totaltime", nil], ["updated_at", Tue, 26 Mar 2013 04:50:36 UTC +00:00], ["user", "1"]]
(2.5ms) commit transaction
Completed 500 Internal Server Error in 10ms
NoMethodError - undefined method `entry_url' for #<EntriesController:0x007fb22b9f7fd8>:
(gem) actionpack-3.2.11/lib/action_dispatch/routing/polymorphic_routes.rb:129:in `polymorphic_url'
(gem) actionpack-3.2.11/lib/action_dispatch/routing/url_for.rb:150:in `url_for'
(gem) actionpack-3.2.11/lib/action_controller/metal/rendering.rb:60:in `_process_options'
(gem) actionpack-3.2.11/lib/action_controller/metal/streaming.rb:208:in `_process_options'
(gem) actionpack-3.2.11/lib/action_controller/metal/renderers.rb:34:in `block in _handle_render_options'
What is the entry_url? Why is it looking for it? Do i need to include something in the model. Its just has attr_accessors for the vars.
class Entry < ActiveRecord::Base
attr_accessible :completed, :endtime, :header, :starttime, :starttimeset, :totaltime, :user, :text, :parent
end
Heres is my routes file:
Tasks::Application.routes.draw do
match '/users/:id/projects' => 'users#show_projects_for_user'
authenticated :user do
root :to => 'home#index'
end
root :to => "home#index"
devise_for :users
resources :users do
resources :entries
end
end
Thanks for the help.
The entry_url is what it's asking you to redirect to when you say redirect_to #entry
You don't have an entries resource in the routes file. You do have one nested within user, but then you need to pass as well as the entry.
redirect_to [ #user, #entry ]
just saw your comment - if it's doing this on the JSON path similarly you need to have
location: [#user, #entry]
Basically anywhere you're asking rails to build a url for an entry you need to pass the entry's user in because you have entry nested within user in the routes and not as a standalone resource routing.
Adding an edit to respond to the comment because there's no formatting in comments:
Yes, this it will work to delete the location as it will no longer call the helper to build that location in the json, but I am presuming you want that. So try this to make the location work:
format.json { render json => { :entry => #entry, :status => created, :location => [#user, #entry] }}
from your comment... if that's not working then let's try calling the url helper directly
format.json { render json => { :entry => #entry, :status => created, :location => user_entry_url(#user, #entry) }}
If you are using Rails3, this might case because with rails3, the url has become path
Ex:
#rails2
entry_url
#rails3
entry_path
So try entry_path instead of entry_url

Validation is passing when it should fail - Michael Hartl's RoR, 6.2.2

I am trying to add validation to my User model, but instead of failing, the data keeps passing. For name, I have no entry. See below:
1.9.3p286 :012 > user = User.new(name: "", email: "fail#fail.com")
=> #<User id: nil, name: "", email: "fail#fail.com", created_at: nil, updated_at: nil>
1.9.3p286 :013 > user.save
(0.1ms) SAVEPOINT active_record_1
SQL (1.5ms) INSERT INTO "users" ("created_at", "email", "name", "updated_at") VALUES (?, ?, ?, ?) [["created_at", Sun, 23 Dec 2012 18:52:00 UTC +00:00], ["email", "fail#fail.com"], ["name", ""], ["updated_at", Sun, 23 Dec 2012 18:52:00 UTC +00:00]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> true
Here is what I have in app/models/user.rb:
class User < ActiveRecord::Base
attr_accessible(:name, :email)
validates(:name, presence: true)
end
This is supposed to fail. Any suggestions? Thank you!
It should work, I think u didn't reload a console after adding a validation

Simple Ajax from Rails tutorial is sending the request but not outputing the HTML?

I'm following this tutorial about making an Ajax request on Rails:
http://net.tutsplus.com/tutorials/javascript-ajax/using-unobtrusive-javascript-and-ajax-with-rails-3/
made _form remote:
<%= form_for(#post, :remote => true) do |f| %>
My scripts are loaded:
<script src="/assets/jquery.js?body=1" type="text/javascript"></script>
<script src="/assets/jquery_ujs.js?body=1" type="text/javascript"></script>
Added format.js to posts_controller.rb:
def create
#post = Post.new(params[:post])
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.js
else
format.html { render action: "new" }
format.js
end
end
end
Created create.js.erb:
$('body').html("<h1><%= escape_javaScript(#post.title) %></h1>").append("<%= escape_javaScript(#post.content) %>");
But when I click the submit button nothing happens in the view but the posts are being created.
I just get this in the terminal:
Started POST "/posts" for 127.0.0.1 at 2012-02-06 12:58:02 +0800
Processing by PostsController#create as JS Parameters: {"utf8"=>"✓",
"authenticity_token"=>"m4BT19I9aUQ+FwGD3Ub9WqKJc0IqjsPpD8+nOyQNhjo=",
"post"=>{"name"=>"asdsad", "title"=>"sadassad",
"content"=>"adasdadadad"}, "commit"=>"Create Post"} (0.2ms) begin
transaction SQL (86.7ms) INSERT INTO "posts" ("content",
"created_at", "name", "title", "updated_at") VALUES (?, ?, ?, ?, ?)
[["content", "adasdadadad"], ["created_at", Mon, 06 Feb 2012 04:58:02
UTC +00:00], ["name", "asdsad"], ["title", "sadassad"], ["updated_at",
Mon, 06 Feb 2012 04:58:02 UTC +00:00]] (120.0ms) commit
transaction Rendered posts/create.js.erb (307.9ms) Completed 500
Internal Server Error in 528ms
ActionView::Template::Error (undefined method `escape_javaScript' for
<#:0xb78ecd0>):
1: $('body').html("<h1><%= escape_javaScript(#post.title) %></h1>").append("<%= escape_javaScript(#post.content) %>");
app/views/posts/create.js.erb:1:in
_app_views_posts_create_js_erb__76139275_96235900'
app/controllers/posts_controller.rb:45:increate'
Rendered
/home/alex/.rvm/gems/ruby-1.9.2-p290/gems/actionpack-3.2.1/lib/action_dispatch/middleware/templates/rescues/_trace.erb
(9.9ms) Rendered
/home/alex/.rvm/gems/ruby-1.9.2-p290/gems/actionpack-3.2.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb
(3.1ms) Rendered
/home/alex/.rvm/gems/ruby-1.9.2-p290/gems/actionpack-3.2.1/lib/action_dispatch/middleware/templates/rescues/template_error.erb
within rescues/layout (19.1ms)
Any suggestions to fix this?
There's a typing error in that tutorial; escape_javaScript should be escape_javascript (lower case)
See also: escape_javascript()