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
Related
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 %>
Could you please help with understanding why categories does not working in a right way? So I read quite a lot manuals about, and did not find how to resolve it
I created migration for category
class CreateCategories < ActiveRecord::Migration
def change
create_table :categories do |t|
t.string :name
t.text :description
t.integer :count
t.timestamps null: false
end
end
end
And added for posts new field - category
Then created model for category
class Category < ActiveRecord::Base
has_many :posts
end
Edit post model
class Post < ActiveRecord::Base
acts_as_ordered_taggable
belongs_to :category
validates :title, presence: true
validates :category, presence: true
..
end
Created template
<%= form_for #post do |f| %>
<p>
<%= f.label :title %> <br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :category %>
<%= f.select :category, Category.all.collect {|c| [c.name, c.name]} %>
</p>
<% end %>
Edited a bit post controller
def update
#post = Post.find(params[:id])
if #post.update(params[:post].permit(:title, :thumbnail, :body, :description, :tag_list, :#post.category))
redirect_to #post
else
render 'edit'
end
end
change this line in your controller:
if #post.update(params[:post].permit(:title, :thumbnail, :body, :description, :tag_list, :category_id))
I changed
:#post.category
to
:category_id
This passes a symbol to the permit method to allow the request parameter for the category
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
I'm trying to add a user profile sub module to a user module but having some problems.
Routes:
resources :users do
resources :userprofiles
end
userprofiles_controller.rb:
class UserprofilesController < ApplicationController
def edit
#user = current_user
#user.UserProfile ||= UserProfile.new
#userprofile = #user.UserProfile
end
def update
#user = current_user
#user.UserProfile ||= UserProfile.new
#userprofile = #user.UserProfile
if #userprofile.update_attributes(:userprofile => params[:userprofile])
redirect_to #user
flash[:notice] = "Changes saved."
else
render 'edit'
flash[:notice] = "Error."
end
end
end
user_profile.rb:
class UserProfile < ActiveRecord::Base
attr_accessible :first_name, :last_name, :summary
belongs_to :user
end
Error:
Can't mass-assign protected attributes for UserProfile: userprofile
Line:
if #userprofile.update_attributes(:userprofile => params[:userprofile])
EDIT
Form:
<%= form_for([#user, #userprofile], url: user_userprofile_path(#user, #userprofile)) do |form| %>
<%= form.label :first_name %>
<%= form.text_field :first_name %>
<%= form.label :last_name %>
<%= form.text_field :last_name %>
<%= form.label :summary %>
<%= form.text_area :summary %>
<%= form.submit "Update", class: "btn btn-block btn-primary" %>
<% end %>
Table:
create_table "user_profiles", force: true do |t|
t.string "last_name"
t.string "first_name"
t.text "summary"
t.integer "user_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
end
You just want
#userprofile.update_attributes(params[:userprofile])
That's a hash with keys :first_name, :last_name, and :summary, which are allowed attributes. When you try to update :userprofile => params[:userprofile], the model checks to see if the key :userprofile is allowed - and it isn't.
I also had this problem. The issue is that you still have attr_accessible in your model controller. Since you don't need them anymore with Rails 4 remove them, add your strong parameters to the controller, and you'll be able to mass-assign without issue.
I do not really understand how nested attributes work in Rails.
I have 2 models, Accounts and Users. Account has_many Users. When a new user fills in the form, Rails reports
User(#2164802740) expected, got Array(#2148376200)
Can Rails not read the nested attributes from the form? How can I fix it? How can I save the data from nested attributes to the database?
Thanks all~
Here are the MVCs:
Account Model
class Account < ActiveRecord::Base
has_many :users
accepts_nested_attributes_for :users
validates_presence_of :company_name, :message => "companyname is required."
validates_presence_of :company_website, :message => "website is required."
end
User Model
class User < ActiveRecord::Base
belongs_to :account
validates_presence_of :user_name, :message => "username too short."
validates_presence_of :password, :message => "password too short."
end
Account Controller
class AccountController < ApplicationController
def new
end
def created
end
def create
#account = Account.new(params[:account])
if #account.save
redirect_to :action => "created"
else
flash[:notice] = "error!!!"
render :action => "new"
end
end
end
Account/new View
<h1>Account#new</h1>
<% form_for :account, :url => { :action => "create" } do |f| %>
<% f.fields_for :users do |ff| %>
<p>
<%= ff.label :user_name %><br />
<%= ff.text_field :user_name %>
</p>
<p>
<%= ff.label :password %><br />
<%= ff.password_field :password %>
</p>
<% end %>
<p>
<%= f.label :company_name %><br />
<%= f.text_field :company_name %>
</p>
<p>
<%= f.label :company_website %><br />
<%= f.text_field :company_website %>
</p>
<% end %>
Account Migration
class CreateAccounts < ActiveRecord::Migration
def self.up
create_table :accounts do |t|
t.string :company_name
t.string :company_website
t.timestamps
end
end
def self.down
drop_table :accounts
end
end
User Migration
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.string :user_name
t.string :password
t.integer :account_id
t.timestamps
end
end
def self.down
drop_table :users
end
end
Thanks everyone. :)
Change the following view region:
<% form_for :account, :url => { :action => "create" } do |f| %>
into:
<% form_for #account do |f| %>
Inside your controller you should have something like this:
def new
#account = Account.new
# the new empty account doesn't have any users
# so the user fields inside your view won't appear unless you specify otherwise:
#account.users.build
#account.users.build
#account.users.build
end