My main problem is, that when uploading via carrierwave the file isn't truly uploaded.
My console output:
#<OptionPic id: 4, image_url: "game_of_thrones___tyrion_lannister_by_stanbos-d79k...", created_at: "2015-08-07 06:08:01", updated_at: "2015-08-07 06:08:01", option_id: 12>]>
The call to the image is following
-#product.options.each do |option|
-option.option_pics.each do |op|
=image_tag op.image_url.to_s
If I inspect the element on my webpage, this is what I get:
<img src="/images/game_of_thrones___tyrion_lannister_by_stanbos-d79k0u9_modified.jpg" alt="Game of thrones tyrion lannister by stanbos d79k0u9 modified">
However settings on the uploader are as following:
class ProductImageUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
include CarrierWave::RMagick
# include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
storage :file
# storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
Needless to say I have neither an image in the assets/images folder nor a public/uploads folder created.
This works perfectly on my other project (public/uploads folder is created with the same syntax as above), where images are stored as a separate model. In my current project I want them as a sub-option for a product class.
The structure is following:
models - product, option, optionpic(ture)
A product can have many options and in turn an option can have many pictures. For example - product is a T-Shirt. Options are: material and color. For each color I want a different picture of the shirt.
This is why I have everything in my ProductsController:
Class ProductsController < ApplicationController
before_action :find_product, only: [:show]
def show
end
def index
#products = Product.all
end
def new
#product = Product.new
#option = #product.options.new
#option_pic = OptionPic.new
end
def edit
end
def create
#product = Product.create(product_params)
#option = #product.options.create(option_params)
#option.product_id = #product.id
#option.save
#option_pic = #option.option_pics.create(pic_params)
#option_pic.option_id = #option.id
flash[:success] = "Product successfully created!"
redirect_to products_path
end
private
def product_params
params.require(:product).permit(:title, :description, :advertising_text, :fancy_quote)
end
def option_params
params.require(:option).permit(:size, :weight, :price, :material, :product_id)
end
def pic_params
params.require(:option_pic).permit(:image_url, :option_id)
end
def find_product
#product = Product.find(params[:id])
end
end
My optionpic(ture) model:
class OptionPic < ActiveRecord::Base
mount_uploader :product_image, ProductImageUploader
belongs_to :option
end
I think I am making just some dumb newbie mistake, but after hours of search I just can't figure out what is wrong.
Edit
I figured out two things - I used image_url instead of picture_image and forgot to actually save the option_picture values in the controller, i.e. #option_pic.save
How ever now there is no data transmission when uploading:
SQL (0.3ms) INSERT INTO "option_pics" ("product_image", "option_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["product_image", nil], ["option_id", 18], ["created_at", "2015-08-07 08:03:28.559319"], ["updated_at", "2015-08-07 08:03:28.559319"]]
I updated every value from :image_url to :product_image (in the view, in the pic_params etc.)
Edit 2
As requested, my upload form:
%h1 Create new product
=form_for #product, url: products_path do |f|
%p
=f.label :title
=f.text_field :title
%br
=f.label :description
=f.text_area :description
%br
=f.label :advertising_text
=f.text_area :advertising_text
%br
=f.label :fancy_quote
=f.text_area :fancy_quote
%p
= fields_for #option do |o|
=o.label :price
=o.text_field :price
%br
=o.label :size
=o.text_field :size
%br
=o.label :weight
=o.text_field :weight
%br
=o.label :material
=o.text_field :material
%p
= fields_for #option_pic, html: { multipart: true } do |op|
= op.label 'Upload image'
= op.file_field :product_image
=f.submit
Edit 3
As requested, my log parameters
Started POST "/products" for ::1 at 2015-08-07 12:25:31 +0300
Processing by ProductsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"DOeZMvYpdoVmZRpsGmg2Gr9LIc9RYaS1KT1vdfhXI2BJaV3pPZZbZN8PJnvwQAig8wLPpIUORuf7Kjcw3BE6Zg==", "product"=>{"title"=>"fafa", "description"=>"", "advertising_text"=>"", "fancy_quote"=>""}, "option"=>{"price"=>"", "size"=>"", "weight"=>"", "material"=>""}, "option_pic"=>{"product_image"=>"level-3-on-rails-for-zombies-2-0eaaf0109f83459c5aedef30bdf8bd96.png"}, "commit"=>"Create Product"}
(0.1ms) BEGIN
SQL (0.3ms) INSERT INTO "products" ("title", "description", "advertising_text", "fancy_quote", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["title", "fafa"], ["description", ""], ["advertising_text", ""], ["fancy_quote", ""], ["created_at", "2015-08-07 09:25:31.365739"], ["updated_at", "2015-08-07 09:25:31.365739"]]
(0.3ms) COMMIT
(0.1ms) BEGIN
SQL (0.2ms) INSERT INTO "options" ("size", "material", "product_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["size", ""], ["material", ""], ["product_id", 29], ["created_at", "2015-08-07 09:25:31.369112"], ["updated_at", "2015-08-07 09:25:31.369112"]]
(0.3ms) COMMIT
(0.1ms) BEGIN
(0.1ms) COMMIT
(0.1ms) BEGIN
SQL (0.3ms) INSERT INTO "option_pics" ("product_image", "option_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["product_image", nil], ["option_id", 21], ["created_at", "2015-08-07 09:25:31.372492"], ["updated_at", "2015-08-07 09:25:31.372492"]]
(0.3ms) COMMIT
Redirected to http://localhost:3000/products
Completed 302 Found in 10ms (ActiveRecord: 2.1ms)
You are not accessing your params value properly. The following will fix that:
def pic_params
params.require(:option_pic).require(:product_image)
end
Also, you have to make your OptionPic belonging to your Option when you build it:
def new
#product = Product.new
#option = #product.options.new
#option_pic = #option.option_pics.new
end
If someone encounters same problem, I will post my solution - I decided to recreate this system using nested attributes, now everything work fine!
So here I have my 3 models:
class Product < ActiveRecord::Base
belongs_to :category
belongs_to :subcategory
has_many :options
has_and_belongs_to_many :product_sizes
accepts_nested_attributes_for :options
end
The option class, which is the child of a product
class Option < ActiveRecord::Base
belongs_to :product
has_many :option_pics
accepts_nested_attributes_for :option_pics
end
And finally the option_pic, a child of an option
class OptionPic < ActiveRecord::Base
mount_uploader :product_image, ProductImageUploader
belongs_to :option
end
In the products controller my new and create actions look as following:
def new
#product = Product.new
option = #product.options.build
option_pic = option.option_pics.build
end
def edit
end
def create
#product = Product.new(product_params)
if #product.save!
flash[:success] = "Product successfully created!"
redirect_to products_path
end
end
private
def product_params
params.require(:product).permit(
:title, :description, :advertising_text, :fancy_quote, :category_id,
options_attributes: [:size, :weight, :price, :material, :product_id,
option_pics_attributes: [:product_image, :option_id]])
end
def find_product
#product = Product.find(params[:id])
end
The string params are double nested, which is important. Also important is the structure for the form_for helper. I did not refactor it, so right now it is one big list. The structure there is very important, I had my fields for option_pic intended on the level of the "f" variable, which was crucial and no images were uploaded.
=form_for #product, url: products_path do |f|
%p
=f.label :title
=f.text_field :title
%br
=f.label :description
=f.text_area :description
%br
=f.label :advertising_text
=f.text_area :advertising_text
%br
=f.label :fancy_quote
=f.text_area :fancy_quote
%br
=f.label :category_id
=f.collection_select :category_id, Category.all, :id, :title, { prompt: 'Please select category' }
%br
=f.label 'Product Size'
=f.collection_check_boxes(:product_size_ids, ProductSize.all, :id, :size)
%p
= f.fields_for :options do |builder|
=builder.label :price
=builder.text_field :price
%br
=builder.label :size
=builder.text_field :size
%br
=builder.label :weight
=builder.text_field :weight
%br
=builder.label :material
=builder.text_field :material
%br
=builder.fields_for :option_pics do |op|
= op.label 'Upload image'
= op.file_field :product_image
=f.submit
And voila, a wonderful commit:
(0.1ms) BEGIN
SQL (0.4ms) INSERT INTO "products" ("title", "description", "advertising_text", "fancy_quote", "category_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["title", "builder"], ["description", ""], ["advertising_text", ""], ["fancy_quote", ""], ["category_id", 1], ["created_at", "2015-08-11 11:34:11.618298"], ["updated_at", "2015-08-11 11:34:11.618298"]]
SQL (0.2ms) INSERT INTO "options" ("size", "price", "material", "product_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["size", ""], ["price", 555], ["material", ""], ["product_id", 82], ["created_at", "2015-08-11 11:34:11.619678"], ["updated_at", "2015-08-11 11:34:11.619678"]]
SQL (0.5ms) INSERT INTO "option_pics" ("product_image", "option_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["product_image", "b3c839_bd43d840e031469495137fa74e31faf4.jpg_srz_428_428_75_22_0.5_1.2_75_jpg_srz"], ["option_id", 66], ["created_at", "2015-08-11 11:34:11.620837"], ["updated_at", "2015-08-11 11:34:11.620837"]]
(0.3ms) COMMIT
Related
i have this situation in Ruby on Rails (5.0)
Many tags have many conditions
In case one same condition for more tags - then must be determined concrete percentage partition
Examples
Tag "work" has condition "VS Code" percent 40
Tag "paid" has condition "VS Code" percent 60
Tag "work" has condition "Calc" percent 100
Tag "funny" has condition "Youtube" percent 100
Main table Tag
table structure---------------------
t.string :name
t.datetime :valid_from
t.datetime :valid_to
with model--------------------------
class Tag < ApplicationRecord
has_many :groupings, dependent: :destroy
has_many :groups, through: :groupings
has_many :tag_conditionings, dependent: :destroy
has_many :tag_conditions, through: :tag_conditionings
accepts_nested_attributes_for :tag_conditions
accepts_nested_attributes_for :tag_conditionings
end
Another table Tag_condition
table structure---------------------
condition:string
with model--------------------------
class TagCondition < ApplicationRecord
belongs_to :tag, optional: true
end
And between table Tag_conditioning (with percent)
table structure---------------------
t.references :tag_condition, foreign_key: true
t.references :tag, foreign_key: true
t.integer :percent
with model--------------------------
class TagConditioning < ApplicationRecord
belongs_to :tag_condition, optional: true
belongs_to :tag, optional: true
end
I have one view with 2 nested forms - if i understand right
<%= form_for(tag) do |f| %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<%= f.fields_for :**tag_conditions** do |c| %>
<div class="field">
<%= c.label :**condition** %>
<%= c.text_field :**condition** %>
</div>
<% end %>
<%= f.fields_for :**tag_conditionings** do |c| %>
<div class="field">
<%= c.label :**percent** %>
<%= c.text_field :**percent** %>
</div>
<% end %>
<div class="field">
<%= f.label :valid_from %>
<%= f.datetime_select :valid_from %>
</div>
<div class="field">
<%= f.label :valid_to %>
<%= f.datetime_select :valid_to %>
</div>
Controller - tags_controllers.rb
def new
#tag = Tag.new
#tag.tag_conditions.build
#tag.tag_conditionings.build
end
def create
#tag = Tag.new(tag_params)
respond_to do |format|
if #tag.save
format.html { redirect_to #tag, notice: 'Tag was successfully created.' }
format.json { render :show, status: :created, location: #tag }
else
format.html { render :new }
format.json { render json: #tag.errors, status: :unprocessable_entity }
end
end
end
private
def tag_params
params.require(:tag).permit(:name, :percent, :valid_from, :valid_to, tag_conditions_attributes: [:condition], tag_conditionings_attributes: [:percent])
end
Everything is ok, only in table tag_conditionings i have double INSERTS and therefore double ROWS
INSERT INTO "tags" ("name", "valid_from", "valid_to", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["name", "sdf"], ["valid_from", "2020-05-08 19:56:00"], ["valid_to", "2020-05-08 19:56:00"], ["created_at", "2020-05-08 19:56:55.811745"], ["updated_at", "2020-05-08 19:56:55.811745"]]
**first INSERT**
INSERT INTO "tag_conditionings" ("tag_id", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["tag_id", 14], ["created_at", "2020-05-08 19:56:55.843693"], ["updated_at", "2020-05-08 19:56:55.843693"]]
INSERT INTO "tag_conditions" ("condition", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["condition", "50sd"], ["created_at", "2020-05-08 19:56:55.865495"], ["updated_at", "2020-05-08 19:56:55.865495"]]
**second INSERT**
INSERT INTO "tag_conditionings" ("tag_condition_id", "tag_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["tag_condition_id", 16], ["tag_id", 14], ["created_at", "2020-05-08 19:56:55.919774"], ["updated_at", "2020-05-08 19:56:55.919774"]]
I am amateur newie, can you help me? What I have wrong? I spent many hours for googling, reading, testing, but zero result.
Thank you very much
Ivanhoe
The reason you are getting two additional rows in the tag_conditionings is that rails will implicitly create rows in the join table when you have a has_many through: association:
Tag.first
.tag_conditions
.create(some_attribute: 'some_value')
The above create 1 row in tag_conditions and 1 row in tag_conditionings.
The same applies when you are using nested attributes:
Tag.create(
tag_conditions_attributes: [{ some_attribute: 'some_value' }]
)
If you want to create the join table entity explicitly and the joined entity you need to nest the nested attributes:
class TagConditioning < ApplicationRecord
belongs_to :tag_condition, optional: true
belongs_to :tag, optional: true
accepts_nested_attributes_for :tag_conditions
end
Tag.create(
tag_conditioning_attributes: [
{
percent: 50,
tag_condition_attributes: [
{ some_attribute: 'some_value' }
]
}
]
)
In the form you do this by nesting the call to fields_for:
<%= form_with(model: #tag) do |f| %>
<%= f.fields_for :tag_conditionings do |conditionings| %>
<%= conditionings.number_field :percent, in: 1..100 %>
<%= conditionings.fields_for :tag_conditions do |tc| %>
<%= tc.text_field :conditions %>
<% end %>
<% end %>
# ...
<% end %>
And you whitelist the nested-nested attributes through:
def tag_attributes
params.require(:tag)
.permit(
:foo,
:bar,
tag_conditionings_attributes: [
:percent,
tag_conditions_attributes: [
:conditions
]
]
)
end
I really would not recommend nesting deeper then this as the complexity level just gets insane. The alternative is setting up separate API endpoints and using ajax calls to update the "nested" records in a way that's seamless to the user but actually atomic.
I'm using devise in rails, and I'm trying to create a second registration path, the default registration path for users (which works perfectly), and a second registration path whereby a user registers and creates a project in a single action as a "Getting Started" action (Think Freelancer.com or any marketplace whereby non-users can register and create their first project in one action).
I've gone through so many threads but they all seem to want to replace the existing registration action. I want to keep the existing registration action and either add a getting_started_new and getting_started_create actions to the existing User::Registration controller, or create a new GettingStarted Controller with methods for new and create that would then allow the nested form (for a user and their new project).
My latest iteration looks something like this:
routes.rb
devise_for :users
resources :users do
resources :projects
end
devise_scope :user do
get "getting_started" =>'getting_started#new'
post "getting_started" =>'getting_started#create'
end
getting_started_controller.rb
class GettingStartedController < Devise::RegistrationsController
def new
#user = User.new
#user.projects.build
end
def create
#user = User.new(getting_started_params)
redirect_to root, notice: "Done"
end
private
def getting_started_params
params.require(:user).permit(:first_name, :last_name, :phone, :password, :email, projects_attributes: [:user_id, :project_type_id, :name, :industry_id, :description, :budget_id, :project_status_id, feature_ids:[], addon_ids:[]])
end
end
But when I try and actually submit the form, it loads the getaction from the new controller, and the post action from the devise registration controller.
Started GET "/getting_started" for ::1 at 2016-10-17 09:15:58 +0200
Processing by GettingStartedController#new as HTML
Rendering getting_started/new.html.erb within layouts/application
Project_type Load (0.5ms) SELECT "project_types".* FROM "project_types"
Industry Load (1.1ms) SELECT "industries".* FROM "industries" ORDER BY "industries"."name" ASC
Feature Load (0.5ms) SELECT "features".* FROM "features" ORDER BY "features"."name" ASC
Addon Load (0.4ms) SELECT "addons".* FROM "addons"
Budget Load (0.4ms) SELECT "budgets".* FROM "budgets"
Rendered getting_started/new.html.erb within layouts/application (32.9ms)
Rendered layouts/_header.html.erb (1.9ms)
Rendered layouts/_footer.html.erb (0.7ms)
Completed 200 OK in 97ms (Views: 86.4ms | ActiveRecord: 2.9ms)
Started POST "/users" for ::1 at 2016-10-17 09:16:54 +0200
Processing by Devise::RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"hYrC/15zIF3DzPvhpFQH6LVS9H8XbhfHY1aRkgc2iX6Mdfvz33/O4p72XTpmY4X8E6B+dGfOmjZw7IoizvYwSA==", "user"=>{"first_name"=>"John", "last_name"=>"Smith", "phone"=>"0340239402309", "email"=>"test#example.com", "password"=>"[FILTERED]", "project"=>{"name"=>"This is a test", "description"=>"Tester Description", "feature_ids"=>[""], "addon_ids"=>[""]}}, "project"=>{"project_type_id"=>"4", "industry_id"=>"2", "budget_id"=>"1"}, "commit"=>"Create account"}
Unpermitted parameter: project
(0.1ms) BEGIN
SQL (1.5ms) INSERT INTO "users" ("email", "encrypted_password", "created_at", "updated_at", "first_name", "last_name", "phone") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["email", "test#example.com"], ["encrypted_password", "$2a$11$VEVjSrnc5Y5c8ofXvNmlMOHrS.v4tQuBoKMLdHaSOA2S6fiVIHfE."], ["created_at", 2016-10-17 07:16:55 UTC], ["updated_at", 2016-10-17 07:16:55 UTC], ["first_name", "John"], ["last_name", "Smith"], ["phone", "0340239402309"]]
(139.1ms) COMMIT
(0.1ms) BEGIN
SQL (0.4ms) UPDATE "users" SET "sign_in_count" = $1, "current_sign_in_at" = $2, "last_sign_in_at" = $3, "current_sign_in_ip" = $4, "last_sign_in_ip" = $5, "updated_at" = $6 WHERE "users"."id" = $7 [["sign_in_count", 1], ["current_sign_in_at", 2016-10-17 07:16:55 UTC], ["last_sign_in_at", 2016-10-17 07:16:55 UTC], ["current_sign_in_ip", "::1/128"], ["last_sign_in_ip", "::1/128"], ["updated_at", 2016-10-17 07:16:55 UTC], ["id", 17]]
(0.3ms) COMMIT
Redirected to http://localhost:3000/
Completed 302 Found in 319ms (ActiveRecord: 141.7ms)
I realise that devise does a whole bunch of other stuff besides simply recording the user data, so it may be better to rather move these actions to the Devise User::RegistrationController, and then tweak the accepted params. But how do you override Devise so that it doesn't auto use the devise create method the second you click the submit button, and would instead use a getting_started_create action?
First off getting started is a pretty horrible name for a controller since it is not a noun. You can't say a getting started. So lets change it to QuickstartsController.
Lets setup the routes for this resource:
Rails.application.routes.draw do
# These are your "normal" devise routes
devise_for :users
# This is the mapping for the "quickstart" routes
devise_for :quickstarts,
class_name: 'User',
only: [],
controllers: { registrations: 'quickstarts' }
# These are the actual routes for quickstarts
devise_scope :quickstart do
get "/quickstarts/new", to: "quickstarts#new", as: :new_quickstart
post "/quickstarts", to: "quickstarts#create", as: :quickstarts
end
end
Whenever you are overriding a library controller it is important to take some time to study how the class you are superclassing actually works.
If you look at the Devise controllers almost all the actions have a line like:
yield resource if block_given?
Which lets you tap into the flow of the original implementation by calling super with a block:
class QuickstartsController < Devise::RegistrationsController
# GET /quickstarts/new
def new
# This block is passed to the super class implementation:
super do |resource|
resource.projects.build
end
end
# POST /quickstarts
def create
# You can pass a block here too if you want.
super
end
private
# This should redirect to the newly created project
def after_sign_up_path_for(resource)
polymorphic_path( resource.projects.last )
end
# This is the method Devise devise calls for the params.
def sign_up_params
# Don't write your params sanitiation on one line! Its not cool.
params.require(:user)
.permit(
:first_name, :last_name, :phone, :password, :email,
projects_attributes: [
:user_id, :project_type_id, :name,
:industry_id, :description, :budget_id,
:project_status_id,
feature_ids:[],
addon_ids:[]
]
)
end
end
But how do you override Devise so that it doesn't auto use the devise
create method the second you click the submit button, and would
instead use a getting_started_create action?
Point the form to the correct controller - by passing the url option to form_for.
app/views/quickstarts/new.html.erb:
<h2>Getting Started</h2>
<%= form_for( resource, as: :user, url: quickstarts_path ) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %>
</div>
<div class="field">
<%= f.label :password %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<fieldset>
<legend>Project</legend>
<% f.fields_for :projects do |pf| %>
<%# ... %>
<% end %>
</fieldset>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
I'd like users to be able to create a User System with multiple existing Parts. That it. Currently when I edit or create a user system with a part select I get.
Processing by UserSystemsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"LgudsjWoAROXi0DGpUaH0ie2GNAuooRGtsPN+fOg+Gtev6Q6QmJC4dYIwFW9evaBOa0TUWotrQec1o1ROCbwFQ==", "user_system"=>{"name"=>"adfa"}, "parts_user_systems"=>{"part_id"=>["", "2", "3"]}, "button"=>""}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 101]]
(0.1ms) BEGIN
SQL (0.6ms) INSERT INTO "user_systems" ("name", "user_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["name", "adfa"], ["user_id", 101], ["created_at", "2015-07-10 17:10:39.564555"], ["updated_at", "2015-07-10 17:10:39.564555"]]
(0.2ms) COMMIT
Nothing get's submitted to the join table.
class UserSystem < ActiveRecord::Base
has_many :parts_user_systems, foreign_key: "part_id"
has_many :parts, through: :parts_user_systems, foreign_key: "part_id"
end
class Part < ActiveRecord::Base
has_many :parts_user_systems
has_many :user_systems, through: :parts_user_systems
end
class PartsUserSystem < ActiveRecord::Base
belongs_to :part
belongs_to :user_system
end
class UserSystemsController < ApplicationController
def user_system_params
params.require(:user_system).permit(:name, :user_id, part_ids: [:ids])
end
end
_form.html.erb
<%= form_for(#user_system) do |f| %>
<div class="field">
<%= f.label :part_id, "Part " %><br/>
<%= collection_select :parts_user_systems, :part_id, Part.all, :id, :name, {:selected => 1}, {:multiple => true} %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
</div>
<% end %>
show.html.erb
<%= #user_system.parts.each do |part| %>
<li><%= part.name%> by by <%= part.parts_user_system%></li></li>
<% end %>
I'm stuck on something that doesn't make sense! I'm simply trying to submit a form with "comments" on a blog post.
Here is my form view:
<%= form_for #comment, :remote => true, :url => forumpost_comments_path(forumpost) do |s| %>
<div class="field">
<%= s.label :content, "Write a comment" %>
<%= s.text_area :content, :rows => "3" %>
</div>
<%= s.submit "Reply"%>
<% end %>
Here is my controller:
def create
#forumpost = Forumpost.find_by_id(params[:forumpost_id])
#comment = #forumpost.comments.build(params[:comment])
#comment.user_id = current_user.id
if #comment.save
redirect_to search_static_pages_path
else
redirect_to search_static_pages_path
end
end
Here is my model:
class Comment < ActiveRecord::Base
attr_accessible :content
belongs_to :user
belongs_to :forumpost
validates :user_id, presence: true
validates :forumpost_id, presence: true
end
And here are my logs:
Started POST "/forumposts/331/comments" for 127.0.0.1 at 2013-12-14 11:41:24 -0800
Processing by CommentsController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"3w3WACRYA6JEwvIg9C66k+cR1ZdRSWwA5Z+W0et1sS8=",
"forumpost"=>{"content"=>"test"}, "commit"=>"Reply", "forumpost_id"=>"331"}
(0.1ms) begin transaction
SQL (0.8ms) INSERT INTO "comments" ("content", "created_at", "forumpost_id", "updated_at", "user_id")
VALUES (?, ?, ?, ?, ?) [["content", nil], ["created_at", Sat, 14 Dec 2013 18:58:58 UTC +00:00],
["forumpost_id", 331], ["updated_at", Sat, 14 Dec 2013 18:58:58 UTC +00:00], ["user_id", 1]]
(14.3ms) commit transaction
As you can see, the content portion is nil even though I have filled out the content field and submitted it.
I would really appreciate any guidance on the matter! Thanks!
Currently implementing Threaded Messaging. via RailsCast
I've installed the Ancestry gem, however all messages that I create are parents. ie.) Ancestry = nil
Even after passing my parent:id to new action
Message Controller
def index
#message = Message.new
#user = current_user
#sent_messages = current_user.sent_messages
#received_messages = current_user.received_messages
end
def new
#message = Message.new
#message.parent_id = params[:parent_id]
end
Index.html
<% for incoming in #received_messages %>
<%= render partial: "message", locals: {incoming: incoming} %>
_message.html.erb
</div>
<%= link_to "Reply", new_message_path(:parent_id => incoming) ,class: "regular" %>
</div>
new.html.erb
<%= form_for #message do |f| %>
<p>
To:<br />
<%= f.hidden_field :parent_id %>
<%= f.hidden_field :recipient, :value => (#message.parent.sender.name) %>
</p>
<p>
Message<br />
<%= f.text_area :body %>
</p>
<p>
<%= submit_tag "Send Threaded Reply" %>
</p>
<% end %>
Message.rb
class Message < ActiveRecord::Base
attr_accessible :recipient, :subject, :body, :parent_id
has_ancestry
end
My console after creating a message:
Key point - I'm passing the parent_id (144) in Message however ancestry still passes as nil.
Parameters: {"utf8"=>"✓", "authenticity_token"=>"gKVr06oT+6OcAERHAzSX79vTlJLniofmEOjZPdZmfwM=", "message"=>{**"parent_id"=>"114"**, "recipient"=>"Rach Miller", "body"=>"meh and more meh"}, "commit"=>"Send Threaded Reply"}
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."id" = 17 LIMIT 1
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."name" = 'Rach Miller' LIMIT 1
(0.2ms) BEGIN
SQL (0.7ms) INSERT INTO "messages" ("ancestry", "body", "created_at", "read_at", "recipient_deleted", "recipient_id", "sender_deleted", "sender_id", "subject", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING "id" [["ancestry", nil], ["body", "meh and more meh"], ["created_at", Tue, 20 Aug 2013 03:14:15 UTC +00:00], ["read_at", nil], ["recipient_deleted", false], ["recipient_id", 18], ["sender_deleted", false], ["sender_id", 17], ["subject", nil], ["updated_at", Tue, 20 Aug 2013 03:14:15 UTC +00:00]]
After Bigxiang's comment, I decided to take a look at my create function.
I have been passing my params individually, So using
#message.parent_id = params[:message][:parent_id] worked for me
Cheers