I'm trying to attach a file "attachment" to my upload model. The attachment field in my db after creation is nil, and links link #upload.attachment.url just redirect to a parent object. Maybe I'm doing something wrong? I haven't used Carrierwave before.
# Model
require 'carrierwave/orm/activerecord'
class Upload < ActiveRecord::Base
mount_uploader :attachment, AttachmentUploader
end
Went with the basics for for the attachment field
# Form
= form_for #upload, :html => { :multipart => true } do |f|
%br
= f.file_field :attachment
And more basics with the controller:
def create
#upload = Upload.new(params[:upload])
#upload.attachment = params[:file]
if #upload.save
redirect_to #upload
end
end
I'm not getting any errors in my console, but the :attachment string on the student model is always nil.
Thanks!
Why u have added the line
#upload.attachment = params[:file]
remove it. it will work. attachment string is null because there is not params file in the form.
Related
I am using the following gem: https://github.com/apneadiving/Google-Maps-for-Rails
I am trying to create #users inside my controller to only display users with the parameter "status" equal to "active"
def index
#users = User.all
#hash = Gmaps4rails.build_markers(#users) do |user, marker|
marker.lat user.latitude
marker.lng user.longitude
marker.title user.title
user_link = view_context.link_to user.title, user_path(user)
marker.infowindow "<h4><u>#{user_link}</u></h4><i>#{user.address}</i>"
end
end
In views/users/index.html.erb, I have a js function.
handler = Gmaps.build('Google');
handler.buildMap({ provider: {}, internal: {id: 'map'}}, function(){
markers = handler.addMarkers(<%=raw #hash.to_json %>);
handler.bounds.extendWith(markers);
handler.fitMapToBounds();
});
and in index.json.jbuilder I have:
json.array!(#users) do |user|
json.extract! user, :id, :latitude, :longitude, :address, :status, :title
json.url user_url(user, format: :json)
end
I have tried a few matching functions in my controller, but I am unsure of where to put the IF logic, ie. is it best suited to be in the index.json.jbuilder, the index.hmtl.erb or the controller?
Probably best in the Model.
class User < ActiveRecord::Base
def self.active
where(status: true)
end
end
Then in your controller
#users = User.active
Build some simple project and stack on using accepts nested attributes + form_for.
Now i have no problem with code, all work and save, but when i uncomment accepts_nested_attributes_fori have error or my model doesnt create (i try differente variant for last 5 days, but can t build this right..). I think i have problem in controller.. My code (which works without accepted_nested_attributes).
Model:
class Project < ActiveRecord::Base
belongs_to :user
has_one :j_project
has_one :p_project
# accepts_nested_attributes_for :p_project, :j_project
validates :user_id, :title, presence: true
end
View:
= form_for(#project) do |f|
= f.label :title
= f.text_field :title
= fields_for #p_project do |fa|
= fa.label :requester
= fa.text_field :requester
= fields_for #j_project do |ffa|
= ffa.label :j_login
= ffa.text_field :j_login
= ffa.label :j_password
= ffa.text_field :j_password
= f.submit "Save", class: "btn btn-large btn-primary"
Controller:
class ProjectsController < ApplicationController
def new
#project = Project.new
#p_project = #project.build_p_project
#j_project = #project.build_j_project
end
def create
#project = Project.new(project_params)
#project.user = current_user
#p_project = #project.build_p_project(p_project_params)
#j_project = #project.build_j_project(j_project_params)
if #project.save && #p_project.save && #j_project.save
flash[:success] = "New project was added successfully"
redirect_to user_root_path
else
render 'new'
end
end
private
def project_params
params.require(:project).permit(:title)
end
def p_project_params
params.require(:p_project).permit(:requester)
end
def j_project_params
params.require(:j_project).permit(:j_login, :j_password)
end
end
The problems was with validation:
project_id in j_project and p_project - when I dell them, all works well.
I edit my simple_form and controllers too with guides from internet... But problems, which I cant find in google - was with validation.
I have created an app that splits up a Student's Information into multiple forms.
Everything works fine, but when I try to render Form_One after a Validation Error, it does not render the appropriate URL/Page.
EX.
adults/1/students/2/form_one
turns into
adults/1/students/2
I need to render the same url so I can proceed to form_2.
MODELS
class Adult < ActiveRecord::Base
has_many :students
end
class Student < ActiveRecord::Base
belongs_to :adult
validates :firstName, :presence => true,
length: { maximum: 50 }
validates :lastName, :presence => true,
length: { maximum: 50 }
end
CONTROLLER
def update
#adult = Adult.find(params[:adult_id])
#student = Student.find(params[:id])
if #student.update_attributes(student_params)
###IF PASS REDIRECT TO THE NEXT FORM
if URI(request.referer).path == form_one_adult_student_path(#adult, #student)
redirect_to form_two_adult_student_path(#adult, #student)
elsif URI(request.referer).path == form_two_adult_student_path(#adult, #student)
redirect_to form_three_adult_student_path(#adult, #student)
else
redirect_to adult_path(#district, #adult)
end
else
error_messages = #student.errors.messages
#adult = Adult.find(params[:adult_id])
#student = Student.find(params[:id])
#student.errors.messages.merge!(error_messages)
###IF ERROR AND ON FORM_ONE RENDER FORM_ONE
if URI(request.referer).path == form_one_adult_student_path(#adult, #student)
###FOR SOME REASON THIS RENDERS adults/1/students/2
###BUT I NEED IT TO RENDER adults/1/students/2/form_one
render 'form_one'
end
end
end
def form_one
#title = "Student Information"
#adult = Adult.find(params[:adult_id])
#student = Student.find(params[:id])
end
def form_two
#title = "Parent Information"
#adult = Adult.find(params[:adult_id])
#student = Student.find(params[:id])
end
ROUTES
resources :adults do
resources :students do
member do
get :form_one, :form_two
end
end
end
###FOR SOME REASON THIS RENDERS adults/1/students/2
###BUT I NEED IT TO RENDER adults/1/students/2/form_one
render 'form_one'
Try redirect_to instead of render.
Keep in mind the difference between rendering a template, and making an HTTP request. Try pretending you are an HTTP client and think about the requests and responses. Sometimes it helps to look through your server log to see which controller actions happen, in which order. Look for lines like Processing students#update or Redirecting to ....
In the future, you may want to try resourceful routes like #show instead.
I'm trying to learn Rails by creating a very simple application which just creates a website where someone can create a list of authors and books with an association that the book is written by an author. I was hoping this would be simple and DRY, but I've been having an unexpected amount of trouble with it.
First looking at my models, I've set up the association and made every data point required (author.name, book.title, and book.author). I do not want to add :author or :author_id to the attr_accessible lists because I want to use the appropriate Rails conventions.
app/models/author.rb:
class Author < ActiveRecord::Base
attr_accessible :name
validates_presence_of :name
has_many :books
end
app/models/book.rb:
class Book < ActiveRecord::Base
attr_accessible :title
validates_presence_of :title
belongs_to :author
validates_associated :author
end
The books controller and view I think is exactly from the scaffolding and very uninteresting. What is interesting is the books controller. Looking at the new method, all I did was add a collector which gets the array of author names with ids to pass to the view. (Honestly, I think I would prefer to not pass the id at all.)
app/controllers/books_controller.rb
# GET /books/new
# GET /books/new.json
def new
#book = Book.new
#authors = Author.all.collect {|a| [a.name, a.id]}
respond_to do |format|
format.html # new.html.erb
format.json { render json: #book }
end
end
Now over to the views, I used the default new.html.haml, but made changes to _form.html.haml. I added a select field using the values in #authors.
app/views/books/_form.html.haml
= form_for #book do |f|
- if #book.errors.any?
#error_explanation
%h2= "#{pluralize(#book.errors.count, "error")} prohibited this book from being saved:"
%ul
- #book.errors.full_messages.each do |msg|
%li= msg
.field
= f.label :name
= f.text_field :name
.field
= f.label :author
= f.select(:author, #authors, {:include_blank => ""})
.actions
= f.submit 'Save'
Lastly, back to my controller for the create method. I try to save the basic parameters and create an author association from the selected author.
app/controllers/books_controller.rb
# POST /books
# POST /books.json
def create
#book = Book.new(params[:book])
#book.author = Author.find_by_id(params[:author])
respond_to do |format|
if #book.save
format.html { redirect_to #book, notice: 'Book was successfully created.' }
format.json { render json: #book, status: :created, location: #book }
else
format.html { render action: "new" }
format.json { render json: #book.errors, status: :unprocessable_entity }
end
end
end
When I click 'Save' I get the following error:
Can't mass-assign protected attributes: author
I understand that this is because the value I selected was put in params[:book] instead of params[:author]. So I have two questions.
1) How do I fix my select statement to have it send in params[:author] instead of params[:book]?
2) Is there an even better way to do this that completely hides the id association?
"Can't mass-assign protected attributes: author" means that your attribute isn't listed as attr_accessible in your model
I think I've mostly figured it out, and as I suspected, I didn't need to change my model code at all.
I changed my controllers new method definition of #authors to only return author names with the following:
#authors = Author.pluck(:name)
This accomplished my goal of hiding the id though it's probably a tad slower when I need to search by name instead of id in the controller create method (below).
Next, I fixed my views to set params[:author] instead of params[:book][:author].
= label :author, :name, 'Author'
= select_tag(:author, options_for_select(#authors), {:include_blank => ""})
Finally, I changed the new methods creation of the #book:
#book = Author.find_by_name(params[:author]).books.create(params[:book])
I'm fairly happy with this. The only thing I don't really like is that the label creates an "author_name" label instead of simply "author".
Using Rails 3.1.3 with Devise 1.5.3. My app has accounts and users. Each account can have multiple users. A user can have one role, "user" or "account_admin". Devise signup routes to accounts#new. The account and an initial account_admin user are created simultaneously. Got this working as described here (although things have evolved some since then).
An account_admin signs should be able to create additional users in that account. That's where I'm running into trouble: instead of creating new users, it's just redirecting to the user_path (users#show) page with the message "You are already signed in." (user_path is my overridden after_sign_in_path.)
This article asks a similar question. The answer suggests a separate namespace for admins, but since admins are part of my regular app I don't think that applies.
I've defined a complete UsersController. According to the log, GET "/users/new" renders from my "UsersController#new". However POST "/users" is intercepted by Devise and rendered from "Devise::RegistrationsController#create".
config/routes.rb
devise_for :users
devise_scope :user do
get "signup", :to => "accounts#new"
get "signin", :to => "devise/sessions#new"
get "signout", :to => "devise/sessions#destroy"
end
resources :users
resources :accounts
app/controllers/users_controller.rb
class UsersController < ApplicationController
before_filter :authenticate_user!
load_and_authorize_resource # CanCan
...
def new
# CanCan: #user = User.new
end
def create
# CanCan: #user = User.new(params[:user])
#user.skip_confirmation! # confirm immediately--don't require email confirmation
if #user.save
flash[:success] = "User added and activated."
redirect_to users_path # list of all users
else
render 'new'
end
end
...
end
I've tried overriding the Devise controller, thinking I could tell it to use my users#create action if the user is already signed in. The log tells me it is using my controller ("Processing by RegistrationsController#create as HTML"), but it doesn't seem to execute its code. I've commented out my custom actions and just left in the logger lines, but I don't get my logging messages. And in spite of super being commented out, the behavior doesn't change--it still redirects with "You are already signed in."
config/routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}
app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def new
logger.info "Custom RegistrationsController: new"
super
end
def create
logger.info "Custom RegistrationsController: create"
# super unless user_signed_in?
# render "users#create"
end
def update
super
end
end
What am I missing? How can I let the account_admin user create additional users?
The main issue is that Devise was intercepting the POST "/users" (and a few other routes). Found this workaround to allow my Users controller handle those routes: change the devise_for to skip registrations, then add back in the routes for which Devise normally defines aliases:
routes.rb
devise_for :users, :skip => [:registrations]
devise_scope :user do
get "signup", :to => "accounts#new"
get "signin", :to => "devise/sessions#new"
get "signout", :to => "devise/sessions#destroy"
get "cancel_user_registration", :to => "devise/registrations#cancel"
post "user_registration", :to => "users#create"
get "new_user_registration", :to => "accounts#new"
get "edit_user_registration", :to => "users#edit"
end
resources :users
resources :accounts
Never figured out why the Devise controller override wasn't working.
A user on this thread pointed out the devise_invitable gem which might be an interesting alternative.
This is how I ended up getting this to work with my setup (Devise tied to my User model -- no separate Editor/Admin model):
class UsermakersController < ApplicationController
before_action :authenticate_user!
def new
#user = User.new
end
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to users_path, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render users_path }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
private
def user_params
userParams = params.require(:user).permit(:name, :email)
end
end
From here, when you want to add a new User as another User, simply call the Usermakers#new url in your form, e.g., I have this at the bottom of my Users index page:
<%= link_to 'Add User', new_usermaker_path, id: 'new_user_link' %>
And the Usermakers form looks like:
= simple_form_for #user, url: usermakers_path, html: {multipart: true} do |f|
=f.error_notification errors: true
= f.input :name
= f.input :email
%p
= f.button :submit, 'Create User', class: 'button'
Of course, you'd need to add a dummy new.html.erb file which simply renders _form.html.erb to use this.
Just add the new and create methods to your routes.rb file (whether by resources :usermakers, or more specific routes) and you should be good to go. Hope this helps!