I have an app with an account model and an account manager (user).
I would like the account manager to be able to add other users to the account by typing in their email.
The account id of the account manager should be added to the new user's record.
My model looks like
class Account < ActiveRecord::Base
has_many users
...
end
class User < ActiveRecord::Base
belongs_to account
...
end
In the console it's fairly simple.
u = User.find(2)
u.update_attributes(account_id: 1)
But I'm not sure how to do this on the site.
I have the below partial which renders fine but when I put an email in the box nothing happens.
I get the message, user not added.
<h4>Add User</h4>
<div class = "row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(:add_user, url: add_users_path) do |f| %>
<%= f.hidden_field #account = Account.find(params[:id]) %>
<%= f.label :email %>
<%= f.email_field :email, class:'form-control' %>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
</div>
</div>
I don't necessarily want/need to route to another page for example "url: add_users_path" but without that line the code breaks and won't render.
I added this to user.rb
def add_user_to_account
update_attribute(:account_id)
end
I also created this controller
class AddUsersController < ApplicationController
before_action :get_user, only: [:edit, :update]
def new
end
def edit
end
def create
#user = User.find_by(email: params[:email])
if #user
#user.add_user_to_account
flash[:info] = "Added User to Account"
redirect_to accounts_url
else
flash[:danger] = "User NOT Added"
redirect_to accounts_url
end
end
def update
if params[:user][:account_id].empty?
#user.errors.add(:account_id, "can't be empty")
render 'edit'
elsif #user.update_attributes(user_params)
log_in #user
flash[:success] = "Account Updated"
redirect_to #user
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:account_id, :user_id)
end
def get_user
#user = User.find_by(email: params[:email])
end
end
Am I on the right track? Is there a better way to do this?
UPDATE: Added schema
create_table "accounts", force: :cascade do |t|
t.string "name"
t.integer "account_manager_id"
t.integer "subscription_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "password_digest", null: false
t.string "remember_digest"
t.string "email", null: false
t.string "activation_digest"
t.boolean "activated"
t.datetime "activated_at"
t.string "reset_digest"
t.datetime "reset_sent_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "access_granted"
t.boolean "requested_access"
t.string "slug"
t.integer "account_id"
end
I think that you had the params wrong.
you are using params[:email] instead of params[:add_user][:email] to find the user by email
in you controller
class UsersController < ApplicationController
...
def add_users
user = User.find_by(email: params[:add_user][:email])
if user
user.add_user_to_account
...
else
...
end
end
end
Related
Showing /home/arthur/Desktop/application/todo/app/views/tasks/index.html.erb where line #7 raised:SQLite3::SQLException: no such column: tasks.list_id
This error appears when I am trying to open the created list to add new tasks. I think the problem is the app can't get the id of the list I am trying to open. But I can't understand what's wrong. (new with ruby and rails). Do I need to add views or something else?
Task Controller
class TasksController < ApplicationController
helper_method :task, :list, :tasks
def create
task.save
redirect_to list_tasks_path(list)
end
def update
task.update task_params
redirect_to list_tasks_path(list)
end
def complete
task.complete
redirect_to list_tasks_path(list)
end
def destroy
task.destroy
redirect_to list_tasks_path(list)
end
private
delegate :tasks, to: :list, private: true
def task
#task ||= params[:id] ? list.tasks.find(params[:id]) : list.tasks.new(task_params)
end
def list
#list ||= List.find params[:list_id]
end
def task_params
params.require(:task).permit(:title, :completed)
end
end
and ListsController
class ListsController < ApplicationController
#helper_method :list, :lists
def index
#lists = List.order('created_at')
end
def new
#list = List.new
end
def create
#list = List.new list_params
#list.save
redirect_to lists_path
end
def edit
#list = List.find params[:id]
redirect_to lists_path
end
def update
#list = List.find params[:id]
#list.update list_params
redirect_to lists_path
end
def destroy
#list = List.find params[:id]
#list.destroy
redirect_to lists_path
end
private
def list_params
params.require(:list).permit(:title)
end
end
View Index.html.erb
<div class="col-md-12">
<h2>Tasks</h2>
<div class="buffer-top"><%= link_to "New Task", new_list_task_path(list), class: 'btn btn-primary' %></div>
<div class="buffer-top">
<% tasks.each do |task| %> <----------- this line
<%= render partial: 'task', object: task %>
<% end %>
</div>
<div class="buffer-top"><%= link_to "Back to Lists", lists_path, class: 'btn btn-primary btn-sm' %></div>
</div>
class Task < ApplicationRecord
belongs_to :lists
def complete!
self.completed = true
save
end
end
class List < ApplicationRecord
has_many :tasks
end
schema
ActiveRecord::Schema.define(version: 2020_04_06_202846) do
create_table "lists", force: :cascade do |t|
t.string "title"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "tasks", force: :cascade do |t|
t.string "title"
t.boolean "completed"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
end
You have belongs_to :lists in your Task model but no list_id in your corresponding tasks table. Your tasks table needs a migration with t.integer "list_id", :null => false in it.
create_table "tasks", force: :cascade do |t|
t.integer "list_id", :null => false
t.string "title"
t.boolean "completed"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
I have this method in my micropost.rb, the error is souly when I run this method. When I submit my form I do not get the errors from the model but the rendering of the else condition in the controller. Something seems to be wrong in the model but don't see why I get rollback transaction from server?
The method just checks that a user has not entered and sent more than one field.
Micropost.rb
validate :return_media_field_errors
private
def return_media_field_errors
if :img_url? && :video_url?
errors.add(:img_url, "Can only submit one field at a time")
end
end
MicropostController
def create
#micropost = current_user.microposts.build(micropost_params)
if #micropost.save
flash[:success] = "Micropost created!"
#micropost = current_user.microposts.build
#feed_items = current_user.feed.paginate(page: params[:page])
render 'static_pages/home'
else
#feed_items = []
render 'shared/error_messages'
end
end
private
def micropost_params
params.require(:micropost).permit(:content, :picture, :picture_cache, :image_url, :video_url, :gif_url)
end
micropost schema.rb
create_table "microposts", force: :cascade do |t|
t.text "content"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "picture"
t.string "image_url"
t.string "video_url"
t.string "gif_url"
t.index ["user_id", "created_at"], name: "index_microposts_on_user_id_and_created_at"
t.index ["user_id"], name: "index_microposts_on_user_id"
end
View params
<div class="media_field_1">
Image <%= f.text_field :image_url, class: 'form-control' %>
</div>
<div class="media_field_2">
Video <%= f.text_field :video_url, class: 'form-control' %>
</div>
I think the problem is this line:
if :img_url? && :video_url?
here :img_url? is a symbol, not an attribute
What you want is self.image_url? or just image_url, same for video_url
Im creating a blog application in ruby on rails. I have "album" model and a "photo" model. In the album edit view I want to be able to delete the uploaded images which are associated to an album.
Unfortunately I'm getting an undefined method error for checkbox?!
Do you have any solution or hints to make this work?
How can I get to the bottom of why it does not work?
If you need further information just let me know.
albums/edit.html.erb
<%= form_for #album do |f| %>
<% if #album.errors.any? %>
<h2><%= pluralize(#album.errors.count, "error") %> prevent this post from saving:</h2>
<ul>
<% #album.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>k
</ul>
<% end %>
<div class="blog_edit_wrapper">
<%= f.label :title %><br>
<%= f.text_field :title, class: "blog_edit_title" %>
<br>
<br>
<%= f.submit 'Submit', class: "blog_edit_submit" %>
</div>
<% end %>
<hr>
<% #album.photos.each do |photo| %>
<%= image_tag(photo.gallery_image) %>
<%= photo.check_box :remove_gallery_image %>
<br>
<br>
<%= f.submit 'Submit', class: "blog_edit_submit" %>
<% end %>
photos_controller.rb
class PhotosController < ApplicationController
before_action :find_photo, only: [ :show, :edit, :update, :destroy]
before_action :set_album
def index
#photo = Photo.all
end
def new
#photo = #album.photos.new
end
def show
end
def create
#photo = #album.photos.new photo_params
#photo.album = #album
if #photo.save
redirect_to #album
else
render :new
end
end
def edit
end
def update
#photo = #album.photos.find params[:id]
if #photo.update photo_params
redirect_to #album, notice: "Your photo was successfully saved!"
else
render 'edit'
end
end
def destroy
#photo.destroy
redirect_to photos_path
end
private
def set_album
#album = Album.find params[:album_id]
end
def photo_params
params.require(:photo).permit(:gallery_image, :album_id, :title, :remove_gallery_image)
end
def find_photo
#photo = Photo.find(params[:id])
end
end
photo.rb
class Photo < ActiveRecord::Base
mount_uploader :gallery_image, ImageUploader
belongs_to :album
end
albums_controller.rb
class AlbumsController < ApplicationController
before_action :find_album, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
#albums = Album.all.order("created_at desc").paginate(page: params[:page], per_page: 12)
end
def new
#album = Album.new
end
def show
#photo = Photo.all
end
def create
#album = Album.new album_params
if #album.save
redirect_to #album
else
render :new
end
end
def edit
end
def update
if #album.update album_params
redirect_to #album, notice: "Your article was successfully saved!"
else
render 'edit'
end
end
def destroy
#album.destroy
redirect_to albums_path
end
private
def album_params
params.require(:album).permit(:title)
end
def find_album
#album = Album.find(params[:id])
end
end
album.rb
class Album < ActiveRecord::Base
has_many :photos
end
schema.rb
ActiveRecord::Schema.define(version: 20170424131600) do
create_table "albums", force: :cascade do |t|
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "friendly_id_slugs", force: :cascade do |t|
t.string "slug", null: false
t.integer "sluggable_id", null: false
t.string "sluggable_type", limit: 50
t.string "scope"
t.datetime "created_at"
end
add_index "friendly_id_slugs", ["slug", "sluggable_type", "scope"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type_and_scope", unique: true
add_index "friendly_id_slugs", ["slug", "sluggable_type"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type"
add_index "friendly_id_slugs", ["sluggable_id"], name: "index_friendly_id_slugs_on_sluggable_id"
add_index "friendly_id_slugs", ["sluggable_type"], name: "index_friendly_id_slugs_on_sluggable_type"
create_table "photos", force: :cascade do |t|
t.string "gallery_image"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "album_id"
end
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "content"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "slug"
t.string "post_main_image"
end
add_index "posts", ["slug"], name: "index_posts_on_slug", unique: true
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
I believe your issue is that you're not using a form but just iterating over the photos.
Also you can place the code for editing the photos inside the first form.
Place this code below the <br> tags and remove the <% #album.photos.each do |photo| %> interation.
<%= fields_for(#album, #album.photos.build) do |f| %>
<%= image_tag(f.gallery_image)%>
<%= f.check_box :remove_gallery_image %>
<% end %>
Edit:
To clarify the above; place the aforementioned code inside your original edit #album form and remove the iteration for the #album.photos.each
Initially started with Contacts, as expected created a list of populated contacts which correctly allow CRUD. Then set up the login with devise which created Users. When logging in as two different users each should only see their own contacts however currently users sees all the same contacts.
Any help resolving this issue would be appreciated?
(Not sure if should have started with User and then created Contact, feels like this is created backwards.)
Understanding for associations is User 'has_many :contacts' and Contacts 'belongs_to :users' have been changing and spiking to no avail.
ContactsController
class ContactsController < ApplicationController
before_action :contact, only: [ :show, :edit, :update, :destroy] before_action :authenticate_user!
def index
#contacts = Contact.all end
def new
#contact = Contact.new end
def create
Contact.create(contact_params)
redirect_to '/contacts' end
def show end
def edit end
def update
#contact.update(contact_params)
redirect_to '/contacts/' + "#{#contact[:id]}" end
def destroy
#contact.destroy
redirect_to '/contacts' end
private
def contact_params
params.require(:contact).permit(:firstname, :surname, :email, :phone, :image) end``
def contact
#contact = Contact.find(params[:id]) end
end
UsersController
class UsersController < ApplicationController
end
model Contact
class Contact < ActiveRecord::Base
belongs_to :users
has_attached_file :image, styles: {thumb: "100x100>"}
validates_attachment_content_type :image, content_type:
/\Aimage\/.*\Z/
end
model user
class User < ActiveRecord::Base has_many :contacts, dependent: :destroy devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable end
indexhtml
<%if user_signed_in? %> <%= link_to 'Log out', destroy_user_session_path, method: :delete %> <%end%>
<% if #contacts.any? %> <% #contacts.each do |contact| %> <%= link_to image_tag(contact.image.url(:thumb)), contact_path(contact) %> <h3><%= contact.firstname%> <%=contact.surname%></h3> <%=contact.email%><br /> <%=contact.phone%> <br /> <br /> <%end%> <%else%> No contacts yet! <%end%> <br /> <br /> <%= link_to 'Add a contact', new_contact_path%>
show html
<p><%= image_tag #contact.image.url(:thumb) %></p> <p><%= #contact.firstname %> <%= #contact.surname %></p> <p><%= #contact.phone %></p> <p><%= #contact.email %></p>
<%= link_to 'Edit', edit_contact_path(#contact) %> <%= link_to 'Remove', contact_path(#contact), method: :delete %><br /><br /> <%= link_to 'Contacts', contacts_path %>
schema
ActiveRecord::Schema.define(version: 20160504125849) do
# These are extensions that must be enabled in order to support this database enable_extension "plpgsql"
create_table "contacts", force: :cascade do |t|
t.string "firstname"
t.string "surname"
t.string "email"
t.integer "phone"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at" end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false end
When logging in as two different users each should only see their own
contacts however currently users sees all the same contacts
The problem is with this line #contacts = Contact.all. It holds all the contacts. As you want to display only the current_user's contacts, you just need it to below
#contacts = current_user.contacts
ActionView::Template::Error: PG::UndefinedColumn: ERROR: column
contacts.user_id does not exist LINE 1: SELECT 1 AS one FROM
"contacts" WHERE "contacts"."user_id" ... ^ : SELECT 1 AS one FROM
"contacts" WHERE "contacts"."user_id" = $1 LIMIT 1
It seems the contacts table doesn't have user_id column. Create a new migration to add the same and do rake db:migrate
I am trying to build a simple friending system for a basic social site. I just need my "Wag" link to trigger an action to favorite that current pet to a favorites page for the owner. I followed the RailsCast here to set everything up.
This is the path link I am trying to set up.
<% #pets.each do |pet| %>
<div>
<%= link_to "Wag", owner_friendships_path(friend_id: owner), method: :post %>
</div>
<% end %>
</div>
It should go here:
<ul>
<% for friendship in #owner.friendships %>
<li>
<%= friendship.friend.name %>
(<%= link_to "remove", friendship, method: :delete %>)
</li>
<% end %>
</ul>
<p><%= link_to "Find Puppy Pals", pets_path %></p>
Routes:
Rails.application.routes.draw do
devise_for :owners
resources :pets
resources :owners do
resources :pets, shallow: true
resources :friendships
end
root to: "pets#index"
end
The relevant schema looks like:
create_table "friendships", force: true do |t|
t.integer "owner_id"
t.integer "friend_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "owners", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
...(devise defaults)
t.datetime "created_at"
t.datetime "updated_at"
t.string "profile_photo"
end
My friendship controller:
class FriendshipsController < ApplicationController
def index
#friendships = Friendship.all
end
def show
#friendship = Friendship.find(params[:id])
end
def create
#friendship = current_owner.friendships.build(params[:friend_id])
if #friendship.save
flash[:notice] = "Added puppy pal."
redirect_to root_url
else
flash[:error] = "Oops, we couldn't save that puppy pal."
redirect_to root_url
end
end
def destroy
#friendship = current_owner.friendships.find(params[:id])
#friendship.destroy
flash[:notice] = "Removed puppy pal."
redirect_to root_url
end
end
Pets controller:
Class PetsController < ApplicationController
def index
#pets = Pet.order("RANDOM()").limit(1)
end
def new
#pet = Pet.new
end
def create
#pet = Pet.new(pet_params)
#pet.owner_id = current_owner.id if current_owner
if #pet.save
flash[:notice] = 'Your pet profile was saved!'
redirect_to pets_path
else
flash.now[:notice] = 'Your pet profile could not be saved.'
render :new
end
end
def show
#pet = Pet.find(params[:id])
end
def edit
#pet = Pet.find(params[:id])
end
def update
#pet = Pet.find(params[:id])
if #pet.update(pet_params)
redirect_to pets_path
else
render :edit
end
end
def destroy
#pet = Pet.find(params[:id])
if current_owner == #pet.owner
#pet.destroy
redirect_to pets_path
end
end
private
def pet_params
params.require(:pet).permit(:name, :breed, :age,
:color, :weight, :personality, :favorite_things, :owner_id, :profile_photo)
end
end
Pets Table:
create_table "pets", force: true do |t|
t.string "name"
t.string "breed"
t.integer "age"
t.integer "weight"
t.text "personality"
t.text "favorite_things"
t.integer "owner_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "profile_photo"
end
Owner Controller:
class OwnersController < ApplicationController
def show
#pet = Pet.find(params[:id])
end
def edit
#owner = Owner.find(params[:id])
end
end
You need to change this line:
<%= link_to "Wag", friendships_path(friend_id: owner), method: :post %>
to this:
<%= link_to "Wag", friendships_path(friend_id: pet.owner_id), method: :post %>
owner is never defined by itself. whatever you're calling (I guess it is owner_id based on your db model) needs to be called on the instance of pet in the block