I think this is a stupid mistake… When i create a record, my "resources" and "page_settings" tables getting populated.
But my "page_setting" does nothing when i try to update the record.
My models:
class Resource < ActiveRecord::Base
has_one :page_setting
accepts_nested_attributes_for :page_setting
end
class PageSetting < ActiveRecord::Base
belongs_to :resource
end
Here is the resources controller:
class ResourcesController < ApplicationController
# Initialize resource and belonging type model
before_filter :build_resource_and_type, :only => [:new, :create]
before_filter :get_resource_and_type, :only => [:edit, :update]
def new
end
def create
if #resource.save
flash[:notice] = "Resource wurde erstellt"
redirect_to root_url
else
flash[:error] = "Resource konnte nicht erstellt werden"
render :action => 'new'
end
end
def edit
end
def update
if #resource.update_attributes(params[:resource])
flash[:notice] = "#{#type_name} #{#resource.title} wurde aktualisiert"
redirect_to root_url
else
flash[:error] = "#{#type_name} #{#resource.title} konnte nicht aktualisiert werden"
render :action => 'edit'
end
end
private
def build_resource_and_type
# Get type from URL param (new action) or hidden field param (create action)
type = params[:type_name] || params[:resource][:type_name]
#resource = current_user.microsite.resources.new(params[:resource])
#resource.type_name = type
# Build belonging model depending on type param
case type
when 'page'
#resource.build_page_setting(params[:page_setting])
#type_name = 'page'
end
end
def get_resource_and_type
#resource = current_user.microsite.resources.find(params[:id])
#type_name = #resource.type_name
end
end
And the essential part of my resource form:
<%= form_for #resource do |resource_form| %>
<%= resource_form.hidden_field :type_name, :value => #type_name %>
…
<%= fields_for #resource.page_setting do |page_form| %>
<%= page_form.label :content, "Text" %>
<%= page_form.text_area :content %>
<% end %>
<% end %>
You have to make a small change in Your resource form:
<%= f.fields_for :page_setting, #resource.page_setting do |page_form| %>
Then it should work, like You want to.
Related
I've been following this tutorial to upload file to db Rails File Upload
.
The problem is file_contents field is blank when file gets saved and I'm uploading file with nested_attributes.
subject.rb //model
class Subject < ApplicationRecord
has_many :documents
accepts_nested_attributes_for :documents
end
document.rb //model
class Document < ApplicationRecord
belongs_to :subject
def initialize(params = {})
#file = params.delete(:file)
super
if #file
self.filename = sanitize_filename(#file.original_filename)
self.content_type = #file.content_type
self.file_contents = #file.read
end
end
private
def sanitize_filename(filename)
return File.basename(filename)
end
end
_form.html.erb //view
<%= form_for(subject) do |f| %>
.......
<div class="uk-form-row">
<%= f.fields_for :documents do |d| %>
<%= d.file_field :file, class:"uk-width-1-1 uk-form-large", placeholder:"upload document" %>
<% end %>
</div>
............
<% end %>
subjects_controller.rb
def new
#subject = Subject.new
#subject.documents.build
end
def create
#subject = Subject.new(subject_params)
respond_to do |format|
if #subject.save
format.html { redirect_to #subject, notice: 'Lesson was successfully created.' }
else
format.html { render :new }
end
end
end
private
def subject_params
params.require(:subject).permit(:title, documents_attributes:[:file])
end
Am I in the right way ? What am I missing ? I need your thoughts.
Thanks,
Rails 3.0
Following these instructions:
https://github.com/plataformatec/devise/wiki/How-To%3a-Require-admin-to-activate-account-before-sign_in
I've generated a migration :approved (boolean) for my devise user.rb. Now I want to edit it with a checkbox from a different controller: unapproved_users_controller.rb.
When I load the form in the edit I get this error: undefined method `user_path'.
routes.rb, the resources for my new controller
resources :unapproved_users
app/models/user.rb, notice that :approved is attr_accessible.
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me, :approved
def active_for_authentication?
super && approved?
end
def inactive_message
if !approved?
:not_approved
else
super # Use whatever other message
end
end
def self.send_reset_password_instructions(attributes={})
recoverable = find_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
if !recoverable.approved?
recoverable.errors[:base] << I18n.t("devise.failure.not_approved")
elsif recoverable.persisted?
recoverable.send_reset_password_instructions
end
recoverable
end
end
app/controllers/unapproved_controllers.rb
class UnapprovedUsersController < ApplicationController
def index
if params[:approved] == "false"
#users = User.find_all_by_approved(false)
else
#users = User.all
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
#user.update_attributes(params[:user])
end
end
app/views/unapproved_users/index.html.haml
%h1 Users
= link_to "All Users", :action => "index"
|
= link_to "Users awaiting approval", :action => "index", :approved => "false"
%table
- #users.each do |user|
%tr
%td= user.email
%td= user.approved
%td= link_to "Edit", edit_unapproved_user_path(user)
app/views/unapproved_users/edit.html.haml
= render 'form'
app/views/unapproved_users/_form.html.haml
= form_for (#user) do |f|
-if #user.errors.any?
#error_explanation
%h2= "#{pluralize(#user.errors.count, "error")} prohibited this user from being saved:"
%ul
- #user.errors.full_messages.each do |msg|
%li= msg
.field
= f.label :approved, 'Approved?'
= f.check_box :approved
.actions
= f.submit 'Save'
You need to change the form_for.
It should be
= form_for(#user, :url => unapproved_user_path(#user)) do |f|
I'm rather new to Rails and I'm writing a signup form that includes nested models. When I submit the form, the user is saved just fine, but the nested model does not save anything to the Subscription db, and the console throws no errors.
I sincerely hope I'm not missing something insanely obvious, and I appreciate any tips you can share. Thanks!
Here is the code-
Models:
class Plan < ActiveRecord::Base
attr_accessible :posts, :name, :price
has_many :users
end
class User < ActiveRecord::Base
belongs_to :plan
has_many :events
has_one :subscription, :autosave => true
accepts_nested_attributes_for :subscription
attr_accessible :subscription_attributes
def save_with_payment
if valid?
customer = Stripe::Customer.create(
email:email,
plan: plan_id,
card: stripe_card_token )
self.stripe_customer_token = customer.id
save!
end
rescue Stripe::InvalidRequestError => e
logger.error "Stripe error while creating customer: #{e.message}"
errors.add :base, "There was a problem with your credit card."
false
end
end
class Subscription < ActiveRecord::Base
attr_accessible :plan_id, :status, :user_id
belongs_to :user
end
This is the User controller:
def new
#user = User.new
plan = Plan.find(params[:plan_id])
#user = plan.user
#user.build_subscription
end
def create
#user = User.new(params[:user])
if #user.save_with_payment
sign_in #user
flash[:success] = "Welcome to the SendEvent!"
redirect_to #user
else
render 'new'
end
end
This is the form:
<%= form_for #user, :html => {:class => "form-inline"} do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="control-group">
<%= f.label :name, :class => "control-label" %>
<%= f.text_field :name %>
</div>
# A few more fields here and...
# The nested model:
<%= f.fields_for :subscription do |builder| %>
<%= builder.hidden_field :status, :value => true %>
<% end %>
<%= f.submit "Create my account", class: "btn btn-large btn-primary", id: "submitacct" %>
<% end %>
Sample app from RailsCasts
RailsCasts Episode #196: Nested Model Form (revised)
Maybe help you.
I am trying to roll together two Railscasts: http://railscasts.com/episodes/262-trees-with-ancestry and http://railscasts.com/episodes/154-polymorphic-association on my app.
My Models:
class Location < ActiveRecord::Base
has_many :comments, :as => :commentable, :dependent => :destroy
end
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
My Controllers:
class LocationsController < ApplicationController
def show
#location = Location.find(params[:id])
#comments = #location.comments.arrange(:order => :created_at)
respond_to do |format|
format.html # show.html.erb
format.json { render json: #location }
end
end
end
class CommentsController < InheritedResources::Base
def index
#commentable = find_commentable
#comments = #commentable.comments.where(:company_id => session[:company_id])
end
def create
#commentable = find_commentable
#comment = #commentable.comments.build(params[:comment])
#comment.user_id = session[:user_id]
#comment.company_id = session[:company_id]
if #comment.save
flash[:notice] = "Successfully created comment."
redirect_to :id => nil
else
render :action => 'new'
end
end
private
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
end
In my locations show view I have this code:
<%= render #comments %>
<%= render "comments/form" %>
Which outputs properly. I have a _comment.html.erb file that renders each comment etc. and a _form.html.erb file that creates the form for a new comment.
The problem I have is that when I try <%= nested_comments #comments %> I get undefined method 'arrange'.
I did some Googling and the common solution to this was to add subtree before the arrange but that throws and undefined error also. I am guessing the polymorphic association is the problem here but I am at a loss as to how to fix it.
Dumb mistake... forgot to add the ancestry gem and required migration which I thought I had already done. The last place I checked was my model where I eventually discovered my error.
Through other posts on SO I've learned that my sign-up process using a nested model form is flawed in that I create a new User, then redirect to create its Profile. Here is the process:
user = User.new
user.email = ...
user.password = ...
user.profile = Profile.new
user.profile.first_name = ...
...
user.profile.save
user.save
It seems as if one solution is to initiate the profile method from within the UsersController create(?) action, so that I POST to both models(?) then redirect to a page with a form to fill out the rest of the profile.
But I'm not entirely sure how to do that, as I am new to programming/Rails. So can anyone give me guidance on how to introduce the Profile method within the UsersController? I gave it a go but don't think it's correct. Code for both Users/ProfilesController below:
User:
def new
#user = User.new
#user.profile = Profile.new
end
def index
#user = User.all
end
def create
#user = User.new(params[:user])
if #user.profile.save
redirect_to profile_new_path, :notice => 'User successfully added.'
else
render :action => 'new'
end
end
Profile:
def new
#user.profile = Profile.new
end
def create
#profile = Profile.new(params[:profile])
if #profile.save
redirect_to profile_path, :notice => 'User successfully added.'
else
render :action => 'new'
end
end
Routes.rb:
match '/signup' => 'profiles#new', :as => "signup"
get "signup" => "profiles#new", :as => "signup"
root :to => 'users#new'
resources :users
resources :profiles
My nested model form (the relevant parts):
<%= form_for(:user, :url => { :action => :create }, :html => {:id => 'homepage'}) do |f| %>
<%= f.text_field :email, :size=> 13, :id => "user[email]" %>
<%= f.fields_for :profile do |f| %>
<% end%>
<% end %>
If anyone could help me I'd greatly appreciate it.
You should have something like this in your models:
class User < ActiveRecord::Base
has_one :profile
accepts_nested_attributes_for :profile
end
class Profile < ActiveRecord::Base
belongs_to :user
end
...of course all backed up with proper migrations. Then while building up a form you can use fields_for helper. Here is slightly modified example from docs:
<%= form_for #user do |user_form| %>
Email: <%= user_form.text_field :email %>
<%= user_form.fields_for :profile do |profile_fields| %>
First Name: <%= profile_fields.text_field :first_name %>
<% end %>
<% end %>
And update your user and his profile in the controller in one go, thanks to accepts_nested_attributes_for :profile declaration in your model.