I am new to ruby on rails,and I am learning by creating a blog. I am not able to save to my blogs table and I get this error "can't write unknown attribute url"
Blogs migration: db/migrate/
class CreateBlogs < ActiveRecord::Migration
def change
create_table :blogs do |t|
t.string :title
t.text :description
t.string :slug
t.timestamps
end
end
end
Blogs Model: /app/models/blogs.rb
class Blogs < ActiveRecord::Base
acts_as_url :title
def to_param
url
end
validates :title, presence:true
end
Blogs Controller: /app/controllers/blogs_controller.rb
class BlogsController < ApplicationController
before_action :require_login
def new
#blogs = Blogs.new
end
def show
#blogs = Blogs.find_by_url(params[:id])
end
def create
#blogs = Blogs.new(blogs_params)
if #blogs.save
flash[:success] = "Your Blog has been created."
redirect_to home_path
else
render 'new'
end
end
def blogs_params
params.require(:blogs).permit(:title,:description)
end
private
def require_login
unless signed_in?
flash[:error] = "You must be logged in to create a new Blog"
redirect_to signin_path
end
end
end
Blogs Form:/app/views/blogs/new.html.erb
Blockquote
<%= form_for #blogs, url: blogs_path do |f| %><br/>
<%= render 'shared/error_messages_blogs' %><br/>
<%= f.label :title %><br/>
<%= f.text_field :title %><br/>
<%= f.label :description %><br/>
<%= f.text_area :description %><br/>
<%= f.submit "Submit Blog", class: "btn btn-large btn-primary" %><br/>
<% end %><br/>
and I have also added "resources :blogs" to my routes.rb file.
I get this error in controller at
if #blogs.save
The error states exactly what your issue is: "can't write unknown attribute url" Implies that the url variable you are trying to access in def to_params of your Blogs model to which is unknown as you wish to store this in slug. The acts_as_url method is added and used by the stringex gem and because you aren't getting an error regarding an unknown method acts_as_url, the gem must successfully be installed, just misconfigured.
Looking further into the documentation for the gem, the gem sets the value of the url to a db column that should already exists in your model. From your database schema, the url should use the column slug and not url (the default of stringex). Changing your Blogs Class to the following should fix the issue:
class Blogs < ActiveRecord::Base
acts_as_url :title, url_attribute: :slug
def to_param
slug
end
validates :title, presence:true
end
Related
What I want to achieve is that list each member with schools and thereafter list Schools with all belonging members. Schools can have many members and members can have many schools also. I have the following set up in the system, but have problems finding the solution for it. Here it is how my code looks like:
controller:
class MembersController < ActionController::Base
before_action :set_school
def index
#members = Member.all
end
def new
#member = Member.new
end
def create
#member = Member.new(member_params)
#member.school = #school
#member.save
redirect_to members_path
end
private
def set_school
#school = School.find(params[:school])
end
def member_params
params.require(:member).permit(:name, :email,:school)
end
end
This is my route:
Rails.application.routes.draw do
get 'schools/index'
resources :members
resources :school
end
My view looks like:
<% #members.each do |member| %>
<%= member.name %>
<%= member.email %>
<%= member.school %>
<% end %>
model for members:
class CreateMembers < ActiveRecord::Migration[5.0]
def change
create_table :members do |t|
t.string :name
t.string :email
t.timestamps
end
end
my School model :
class CreateSchools < ActiveRecord::Migration[5.0]
def change
create_table :schools do |t|
t.string :name
t.timestamps
end
and the reference:
class AddSchoolRefToMembers < ActiveRecord::Migration[5.0]
def change
add_reference :members, :school, foreign_key: true
end
Any help would be great! Thank you!
You have set before_action for all actions in controller. For, index and new there is no school_id, so you have to run before_action only for create.
Change below code
before_action :set_school
to
before_action :set_school, only: ['create']
<%= simple_form_for [#member] do |f| %>
<%= f.input :name %>
<%= f.input :email %>
<%= f.collection_select :school_id, School.all, :id, :name %>
<%= f.submit %>
<% end %>
Change the strong params
def member_params
params.require(:member).permit(:name, :email, :school_id)
end
And you can remove the before_action :set_school
Also you need to change the action as school_id is already in params
def create
#member = Member.create(member_params)
redirect_to members_path
end
#imocsari to get the name of school change your view like
<% #members.each do |member| %>
<%= member.name %>
<%= member.email %>
<%= member.school.try(:name) %>
<% end %>
member.school will give you associated school of member with all column, if you want to show name of school this is way member.school.try(:name) or member.school.name
member.school.try(:name) this will return nil if there is not any school for member, It will by pass exception
member.school.name this will raise error if there is not any school for member.
so I have looked at other instances of this error in other questions on SO and none seem to be helpful. So, my authentication system should allow a Business to sign up, and allow a user to sign up under their business. However, I'm getting a "couldn't find business without ID" error.
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.references :company, foreign_key: true
t.timestamps
t.string :first_name
t.string :last_name
t.string :email
t.string :password_digest
t.string :remember_digest
t.string :role
end
class CustomersController < ApplicationController
def new
set_business
#customer = #business.customers.create(user_params)
end
def create
#customer = Customer.new(customer_params)
#customer.save!
session[:customer_id] = #customer.id
redirect_to '/'
rescue ActiveRecord::RecordInvalid => ex
render action: 'new', alert: ex.message
end
private
def customer_params
params.require(:customer).permit(:first_name, :last_name, :business_no, :email, :password_digest, :business_id)
end
def set_business
#business = Business.find (params[:business_id])
end
HTML snippet: Customer.new.html.erb
<h1>Sign Up</h1>
<%= form_for(#customer) do |f| %>
<%= f.label :first_name %>
<%= f.text_field :first_name, :placeholder => "First name" %>
<%= f.label :last_name %>
<%= f.text_field :last_name, :placeholder => "Last name" %>
<%= f.label :email %>
<%= f.email_field :email, :placeholder => "Email" %>
<%= f.label :company_id %>
<%= f.collection_select :business_id, Business.all, :id, :name %>
<%= f.password_field :password_digest, :placeholder => "Password" %>
<%= f.submit "Create Account", class: "btn-submit" %>
<% end %>
class Business < ActiveRecord::Base
has_many :customers
end
class Customer < ActiveRecord::Base
belongs_to :business
end
How am I supposed to define the #business variable without getting this error so that a user can sign up under their business? I want them to select from a list of available companies on the form, which will then link them in the database when the user signs up. What am I doing wrong? I am very new to Ruby and I may need some good explanation to why this is happening.
thank you for your time :)
You should take a look at the contents of the params[], since there's no plain :business_id key, it's nested in a :customers hash:
change your set_business to somethink like this:
def set_business
#business = Business.find (params[:customer][:business_id])
end
EDIT: This will not work, since the first call to new method, the params is not supplied. You should only get a list of businesses to populate the form!
def new
#customer = Customer.new
#businesses = Business.all
end
EDIT2: In create method you don't need to set the business either, since it's already set by the form!
def create
#customer = Customer.create(customer_params)
#customer.save
end
Update the controller
customers_controller.rb
class CustomersController < ApplicationController
before_action :set_business
def new
#customer = #business.customers.build
end
def create
begin
#customer = #business.customers.new(customer_params)
#customer.save!
session[:customer_id] = #customer.id
redirect_to '/'
rescue ActiveRecord::RecordInvalid => ex
render action: 'new', alert: ex.message
end
end
private
def customer_params
params.require(:customer).permit(:first_name, :last_name, :business_no, :email, :password_digest, :business_id)
end
def set_business
#business = Business.find (params[:business_id])
end
end
I am currently building a tricky form. I am still a fairly young Rails developer so half the battle is grasping how to go about this.
I need to build a form that launches a Campaign. This Campaign will need to be named and commented. It also needs to choose a .zip file form a pre-populated dropdown box. Under that will be the ability to choose one of 5 .pdf files via a check box. Zip files and pdf files are a part of the same model Upload.
So far my Campaign model...
models/campaign.rb
class Campaign < ActiveRecord::Base
has_many :uploads
validates :name, presence: true,
uniqueness: true
accepts_nested_attributes_for :uploads
end
The Uploads model represents the table that holds zip and pdf files..
models/uploads.rb
class Upload < ActiveRecord::Base
has_one :campaign
end
Here is the Campaign controller..
controllers/campaigns_controller.rb
class CampaignsController < ApplicationController
def index
#campaigns = Campaign.all.order("created_at DESC")
end
def new
#campaign = Campaign.new
end
def create
#campaign = Campaign.new(campaign_params)
if #campaign.save
flash[:success] = "Campaign Successfully Launched!"
redirect_to #campaign
else
flash[:error] = "There was a problem launching your Campaign."
redirect_to new_campaign_path
end
end
def show
#campaign = Campaign.find(params[:id])
end
private
def campaign_params
params.require(:campaign).permit(:name, :comment)
end
end
My form looks like this...
views/campaigns/_form.html.erb
<%= form_for #campaign, url: {action: "create"} do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :comment %>
<%= f.text_area :comment %>
#....this is where I lose it..
<%= f.label :data_file %>
<% end %>
How should I got about this? Is this a case use for collection_select? Any advice or even tutorial links will be highly appreciated.
Note: Rails newb here.
So, I recently created a Rails app with mongoid gem for use of MongoDB. I have a namespace route of :blog with a nest of resource of posts
Routes.rb:
Rails.application.routes.draw do
namespace :blog do
resources :posts
end
end
The error comes from app/controllers/blog/posts_controller.rb:
Class Blog::PostsController < ApplicationController
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post
else
render 'new'
end
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
I also have a 'post' model that comes with a title and body:
Class Post
include Mongoid::Document
field :title, type: String
field :body, type: String
end
In new.html.erb:
<h1>Rails Sample Blog</h1>
<%= form_for #post, url: blog_post_path do |f| %>
<div><%= f.label :title %><%= f.text_field :title %></div>
<div><%= f.label :body %><%= f.text_area :body %></div>
<% end %>
Is there something I left out that I didn't catch? It's slowly haunting me.
Edit: See this Git repo: https://github.com/hackathons-com/Rails-MongoDB-Devise-test
Edit 2:
undefined method `post_url' for #<Blog::PostsController:0x007f3d19105ee8>
Try this:
def create
#blog = Blog.find(params[:blog_id])
#post= #blog.posts.build(post_params)
(This assumes that you already added a column of blog_id and have your associations correct, although looking at your model it looks like you may have missing associations?)
app/controllers/blog/post_controller.rb:
Shouldn't this be posts_controller.rb?
Also
Class Blog::PostController < ApplicationController
should be
Class Blog::PostsController < ApplicationController
I'm having an inordinate amount of trouble using a nested model with fields_for in a form. Specifically, not all of the nested fields save. A User has many Experiences, but when I submit the form, an Experience with the correct user_id but NO CONTENT is inserted into the database.
Looking at the logs, I also get an error:
unpermitted parameters: experience.
Rails 4 nested attributes not saving doesn't help, unfortunately.
Here's the code:
SCHEMA
create_table "experiences", force: true do |t|
t.string "content", null: false, default: ""
t.integer "user_id"
end
MODEL
#user.rb
class User < ActiveRecord::Base
has_many :experiences
accepts_nested_attributes_for :experiences
#experience.rb
class Experience < ActiveRecord::Base
belongs_to :user
end
CONTROLLER
class UsersController < ApplicationController
def new
#user = User.new
#user.experiences.build
end
def update
#user = current_user
#user.experiences.build
#user.update!(user_params)
redirect_to root_path
end
def user_params
params.require(:user).permit(:username, :email, :password,
:password_confirmation, :title, :blurb, :city, :state,
:style_list, :experience_attributes => [:id, :content])
end
VIEW
<%= form_for #user do |f| %>
<!-- (Omitted) user fields -->
<%= f.fields_for :experience do |experience_fields| %>
<%= experience_fields.text_field :content, placeholder: 'Content' %>
<% end %>
<%= f.submit 'Edit profile' %>
<% end %>
Any help would be greatly appreciated!
Here's your problem:
#user.experiences.build # -> note "experience**s**"
This means when you use fields_for, you have to reference :experiences (you're currently referencing the singular):
<%= f.fields_for :experiences do |experience_fields| %>
<%= experience_fields.text_field :content, placeholder: 'Content' %>
<% end %>
This also goes for your strong_params:
params.require(:user).permit(experiences_attributes: [:id, :content])