I'm learning Rails and I am working on a blog. I'm facing the problem that one of the fields of the form is not mapping to the database. When I save a new article the name maps to the db but not story. I end Up having a null column in the db.
My migration
class CreateArticles < ActiveRecord::Migration
def change
create_table :articles do |t|
t.string :name
t.text :story
t.timestamps
end
end
end
forms/new.html.erb
<h1>New Article</h1>
<%= form_for :article, url: articles_path do |f| %>
<p>
<%= f.label :name %><br>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :story %><br>
<%= f.text_area :story %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
controller
class ArticlesController < ApplicationController
def new
end
def create
#article = Article.new(article_params)
#article.save
redirect_to #article
end
def show
#article = Article.find(params[:id])
end
private
def article_params
params.require(:article).permit(:name, :story)
end
end
Uses debugger gem and check the params are passes correct it will be good if you can just share the devlopment.log
Related
I have 2 Models: Unit and Emp
Also I have 2 controllers: Units and Emps
class CreateEmps < ActiveRecord::Migration[6.0]
def change
create_table :emps do |t|
t.string :name
t.references :unit
t.timestamps
end
end
end
class CreateUnits < ActiveRecord::Migration[6.0]
def change
create_table :units do |t|
t.string :name
t.timestamps
end
end
end
Looks simple.... but I guess too simple. I haven't found example how to do the following:
I need to have form for Emp creation.
So my question is .... how should it look like?
I want to have ComboBox with list of all objects in Units.
<%= form_with model: #emp do |f| %>
<p><%= f.label :name %>
<%= f.text_field :name %> </p>
<!-- What should go here? to ComboBox (option->select) -->
<%= f.submit "Create" %>
<% end %>
I am also confused how should it look like regargding emp_params for permiting.
EDIT:
class EmpsController < ApplicationController
def new
#emp = Emp.new
#unit_options = Unit.all.collect{|unit| [unit.name, unit.id] }
end
def create
#emp = Emp.new(emp_params)
#emp.save
redirect_to :action => :list
end
def destroy
#emp = Emp.find([:id])
#emp.destroy
redirect_to :action => :list
end
def list
#emps = Emp.all
end
def emp_params
params.require(:emp).permit(:name, :unit_id)
end
end
You want to use a select tag.
In your controller:
#unit_options = Unit.all.collect{|unit| [unit.name, unit.id] }
This creates a list of names and IDs, the order of each is name then value for the select option. You can of course scope or filter the results as needed.
In your view:
<%= form_with model: #emp do |f| %>
<div>
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div>
<%= f.label :unit_id, 'Unit' %>
<%= f.select :unit_id, #unit_options, {include_blank: true} %>
</div>
<%= f.submit "Create" %>
<% end %>
When used to edit the model, rails will select the option for the current value.
I am new to ruby on rails and I am trying to store nested json in the table.
json:
articles: {
title: "abc",
text: "a",
address: {
flat: "abc",
city: "bang"
}
}
Migrations:
class CreateArticles < ActiveRecord::Migration[5.2]
def change
create_table :articles do |t|
t.string :title
t.text :text
t.string :address
t.timestamps
end
end
end
class CreateAddresses < ActiveRecord::Migration[5.2]
def change
create_table :addresses do |t|
t.string :flat
t.string :city
t.timestamps
end
end
end
models:
class Article < ApplicationRecord
has_one :address
accepts_nested_attributes_for :address
end
class Address < ApplicationRecord
end
controller:
class ArticlesController < ApplicationController
def create
#article = Article.new(params.require(:article).permit(:title, :text, :address))
#article.save
redirect_to #article
end
def show
#article = Article.find(params[:id])
end
end
form(new.html.erb):
<%= form_with scope: :article, url: articles_path, local: true do |form| %>
<p>
<%= form.label :title %><br>
<%= form.text_field :title %>
</p>
<p>
<%= form.label :text %><br>
<%= form.text_area :text %>
</p>
<%=form.fields_for :address do |a| %>
<div>
<%=a.label :flat%><br>
<%= a.text_field :flat%><br>
<%=a.label :city%><br>
<%= a.text_field :city%>
</div>
<%end%>
<p>
<%= form.submit %>
</p>
I am not able to store the adrress to the table. address is always saved as nil. Can anyone guide me if what i am doing wrong. I want to parse the json to the table and store the json as string. Updated the question with controller and form that i am using.
When you want to permit nested attributes you do specify the attributes of nested object within an array. Pls, try this one #article = params.require(:articles).permit(:text, :title, :address =>[:flat, :city])
Rails has a very good documentation pls take a look https://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit
I saw a similar answered question here which got me this far. But now I am facing an error in Form. The solution I am looking for is basically saving to two tables in Ruby Rails where saving the Property with address in first table also saves 2 images in Pictures' second table.
Migration1:
class CreateProperties < ActiveRecord::Migration[5.0]
def change
create_table :properties do |t|
t.string :address
t.timestamps
end
end
end
Migration2:
class CreatePictures < ActiveRecord::Migration[5.0]
def change
create_table :pictures do |t|
t.string :image1
t.string :image2
t.timestamps
end
end
end
Property Model:
class Property < ApplicationRecord
has_many :pictures
accepts_nested_attributes_for :pictures
end
Picture Model:
class Picture < ApplicationRecord
belongs_to :property
end
PropertiesController:
class PropertiesController < ApplicationController
before_action :set_property
def new
#property = Property.new
end
def create
#property = properties.build(property_params)
if #property.save
flash[:success] = "Property was successfully created"
redirect_to property_path(#property)
else
render 'new'
end
end
private
def property_params
params.require(:property).permit(:address, picture_attributes: [:image1, :image2])
end
end
The FORM which I don't know is done as below:
<%= form_for(#property) do |f| %>
<%= f.label :address %>
<%= f.text_field :address %>
<%= f.label :image1 %>
<%= f.text_field :image1 %>
<%= f.label :image2 %>
<%= f.text_field :image2 %>
<%= f.submit %>
<% end %>
Error Picture:
Error on new.html.erb
You should use the fields_for method to have a form for pictures inside the property form:
# inside the property form_for
<%= f.fields_for #property.pictures.build do |p| %>
<%= p.file_field :image1 %>
<%= p.file_field :image2 %>
<% end %>
I am very new to Rails. I completed a tutorial here that walks you through the steps of creating a blog using it.
Part of the tutorial shows you how to create a controller that allows users to add comments to an article. I am trying to modify it so that users can only delete their own comments (and not others' comments).
Question:
Is there a way to modify the code so that way you can limit users to deleting their own comments? Any resources/tutorials are welcome too. I really just have no clue on how to start.
I feel like the right way to go is to mark the user some way when they submit the comment. Save that information in the database, and then check that information when someone goes to delete a comment. But I can't think of a way to do that without trying to build a full on log in system for users.
Code:
Here is the code from the tutorial:
Database Migration:
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.string :commenter
t.text :body
t.references :article, index: true, foreign_key: true
t.timestamps null: false
end
end
end
Controller:
class CommentsController < ApplicationController
def create
#article = Article.find(params[:article_id])
#comment = #article.comments.create(comment_params)
redirect_to article_path(#article)
end
private
def comment_params
params.require(:comment).permit(:commenter, :body)
end
end
Template:
<p>
<strong>Title:</strong>
<%= #article.title %>
</p>
<p>
<strong>Text:</strong>
<%= #article.text %>
</p>
<h2>Add a comment:</h2>
<%= form_for([#article, #article.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br>
<%= f.text_field :commenter %>
</p>
<p>
<%= f.label :body %><br>
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<%= link_to 'Edit', edit_article_path(#article) %> |
<%= link_to 'Back', articles_path %>
Delete Comment:
class CommentsController < ApplicationController
def create
#article = Article.find(params[:article_id])
#comment = #article.comments.create(comment_params)
redirect_to article_path(#article)
end
def destroy
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
#comment.destroy
redirect_to article_path(#article)
end
private
def comment_params
params.require(:comment).permit(:commenter, :body)
end
end
I found a similar question here, but there wasn't an answer that worked.
In CommentsController Edit your destroy method like below :
def destroy
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
if #comment.user.id == current_user.id
flash[:success] = "Comment Deleted Successfully!"
#comment.destroy
else
flash[:error] = "You can only delete your own comments!"
end
redirect_to article_path(#article)
end
Add a migration to add user_id to the comment table :
class AddUserIdToComments < ActiveRecord::Migration
def change
add_column :comments, :user_id, :integer
end
end
Comment & User Model should be like below to track the user from comment :
class User < ActiveRecord::Base
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :user
end
View:
<p>
<strong>Title:</strong>
<%= #article.title %>
</p>
<p>
<strong>Text:</strong>
<%= #article.text %>
</p>
<h2>Add a comment:</h2>
<%= form_for([#article, #article.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br>
<%= f.text_field :commenter %>
<%= f.hidden_field :user_id, current_user.id %>
</p>
<p>
<%= f.label :body %><br>
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<%= link_to 'Edit', edit_article_path(#article) %> |
<%= link_to 'Back', articles_path %>
In Comment Controller change comment_params
def comment_params
params.require(:comment).permit(:commenter, :body, :user_id)
end
When submitting the form for a new proposal I'm getting this error. I don't understand why.
ArgumentError in ProposalsController#create
wrong number of arguments (1 for 0)
Controller:
class ProposalsController < ApplicationController
def new
#proposal = Proposal.new
end
def create
#proposal = Proposal.new(prop_params)
#proposal.save
# if #proposal.save
# redirect_to proposal_path(params[:proposal][:id])
# else render 'new'
# end
end
def show
#proposal = Proposal.find(params[:id])
end
def index
#proposals = Proposal.all
end
def prop_params
params.require(:proposal).permit(:content, :title)
end
end
New View:
<div class="pform">
<%= form_for #proposal do |f| %>
<%= f.label :title, 'Titlu' %><br />
<%= f.text_field :title %><br />
<%= f.label :content, 'Conţinut' %><br />
<%= f.text_area :content %> <br />
<%= f.submit, 'Trimite' %>
<% end %>
</div>
Proposal migration model
class CreateProposals < ActiveRecord::Migration
def change
create_table :proposals do |t|
t.string :title
t.string :content
t.timestamps null: false
end
end
end