I am new to ROR and using active admin for generating a small app. I have belongs to and has many relation ships defined in the models. My app is working good for the pages where belongs to does not apply. In the page where belongs to comes into action I have drop down created by Active Admin, however when I select the values from drop down and save the form, values selected from drop down is not getting saved. below are my model controller and active admin pages codes. Please help me fix this issue.
ActiveAdmin.register Componentdetail do
models:
class Preference < ActiveRecord::Base
def permitted_params
params.permit preference: [:prefname, :prefdisplay, :helptext]
end
def preference_params
params.require(:preference).permit(:prefname, :prefdisplay, :helptext)
end
attr_accessible :prefname, :prefdisplay, :helptext
has_many :prefcomprelation
#accepts_nested_attributes_for :prefcomprelation, :allow_destroy => true
def display_name
return self.prefname
end
def input
self.id
end
end
class Prefcomprelation < ActiveRecord::Base
def permitted_params
params.permit prefcomprelation: [:comment, :preference, :componentdetail]
end
def prefcomprelation_params
params.require(:prefcomprelation).permit(:comment, :preference, :componentdetail)
end
# def to_s
# description
# end
attr_accessible :comment, :preference, :componentdetail
#acts_as_list column: :preference, :scope => :preference
belongs_to :preference
#acts_as_list column: :componentdetail, :scope => :componentdetail
belongs_to :componentdetail
validates :comment, presence: true
validates :preference, presence: true
validates :componentdetail, presence: true
#controller do
def new
#prefcomprelation = Prefcomprelation.new
end
def update
#prefcomprelation = Prefcomprelation.new(precomprelation_params)
#prefcomprelation.save
end
def create
#prefcomprelation = Prefcomprelation.new(precomprelation_params)
#prefcomprelation.save
end
#end
end
class Message < ActiveRecord::Base
def permitted_params
params.permit message: [:message, :componentdetail]
end
def message_params
params.require(:message).permit(:message, :componentdetail)
end
attr_accessible :message, :componentdetail
belongs_to :componentdetail
end
class Componentdetail < ActiveRecord::Base
def permitted_params
params.permit componentdetail: [:compname, :compdisplay, :prefcomprelation]
end
def componentdetail_params
params.require(:componentdetail).permit(:compname, :compdisplay, :prefcomprelation)
end
attr_accessible :compname, :compdisplay, :prefcomprelation
has_many :prefcomprelation
#accepts_nested_attributes_for :prefcomprelation, :allow_destroy => true
has_many :message
#accepts_nested_attributes_for :message, :allow_destroy => true
def name
return self.compname
end
end
controllers
class PreferenceController < ApplicationController
def index
#preference = Preference.all
end
def show
end
end
class PrefcomprelationController < ApplicationController
def index
#prefcomprelation = Prefcomprelation.all
end
def create
#prefcomprelation = Prefcomprelation.new(precomprelation_params)
#prefcomprelation.save
end
def new
#prefcomprelation = Prefcomprelation.new(precomprelation_params)
#prefcomprelation.save
end
def show
end
end
class MessageController < ApplicationController
def index
#message = Message.all
end
def create
#message = Message.new(message_params)
#message.save
end
def show
end
end
class ComponentdetailController < ApplicationController
def index
#componentdetail = Componentdetail.all
end
def show
end
end
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
end
Admin Pages
ActiveAdmin.register Preference do
end
ActiveAdmin.register Prefcomprelation do
index do
selectable_column
id_column
column :comment
column :preference
column :created_at
actions
end
filter :comment
filter :preference
filter :componentdetail
form do |f|
f.inputs "Prefcomprelation" do
f.input :comment
#f.inputs do
f.input :preference
f.input :componentdetail
end
f.actions
# f.input :preference
end
end
ActiveAdmin.register Message do
index do
column :message
column :created_at
actions
end
form :html => { :enctype => "multipart/form-data" } do |f|
f.inputs 'Details' do
f.input :message
f.input :componentdetail
end
f.actions
end
end
ActiveAdmin.register Componentdetail do
end
issue comes when I try to create new Prefcomprelation and select preference and componentdetails value from the dropdown menu and try to save.
same happens to the message page.
form do |f|
f.inputs "Product Details" do
f.input :name, :as => :select,
:collection => Product.all.map{|u| ["#{u.product_name}", u.product_name]}
f.input :description
f.input :image
f.input :quantity
end
f.actions
end
Try to add drop down like above and save select value in active admin.
Related
I recently updated my Rails app from 4.0 to 4.1. Everything seems to work fine, except this one line in my Resource_Tag Model that was working before.
Essentially, I want to search/find District_Resources by Tag Name and by the District_Resource Name.
**ex.**
If I search the word "Tutoring"
*I should get all District_Resources with the Resource_Tag "Tutoring"
*And all District Resources that include the word Tutoring in it's Name.
(i.e Tutoring Services)
For some reason, I keep getting this error:
wrong number of arguments (1 for 0)
all(:conditions => (string ? [cond_text, *cond_values] : []))
CONTROLLER
class ResourceTagsController < ApplicationController
def index
if params[:search].present?
#Calls Search Model Method
#resource_tags = ResourceTag.search(params[:search])
#tagsearch = ResourceTag.search(params[:search])
#tag_counts = ResourceTag.count(:group => :name,
:order => 'count_all DESC', :limit => 100)
else
#resource_tags = ResourceTag.all
end
end
end
MODELS
class DistrictResource < ActiveRecord::Base
has_many :district_mappings, dependent: :destroy
has_many :resource_tags, through: :district_mappings
accepts_nested_attributes_for :resource_tags
end
class ResourceTag < ActiveRecord::Base
#create relationships with all resource and mapping models
has_many :district_mappings, dependent: :destroy
has_many :district_resources, through: :district_mappings
#I GET AN ERROR HERE
def self.search(string)
return [] if string.blank?
cond_text = string.split(', ').map{|w| "name like ?"}.join(" OR ")
cond_values = string.split(', ').map{|w| "%#{w}%"}
all(:conditions => (string ? [cond_text, *cond_values] : []))
end
end
VIEWS
<%= form_tag(resource_tags_path, :method => 'get', class: "navbar-search") do %>
<form>
<%= text_field_tag :search, params[:search], :class => "search-query form-control" %>
<%= submit_tag "Search", :name => nil, :class => "search-button" %>
</form>
<% end %>
After an hour search I came to know that In rails 4.1 onward all method of ActiveRecord does not take any parameters that's why extra argument error occurs. You can try where instead. Here is your search method
def search(string)
return [] if string.blank?
cond_text = string.split(', ').map{|w| "name like ?"}.join(" OR ")
cond_values = string.split(', ').map{|w| "%#{w}%"}
self.where(string ? [cond_text, *cond_values] : [])
end
I'm getting this error ActionController::UrlGenerationError in Manufacturers#index along with No route matches {:action=>"new", :controller=>"cars"} missing required keys: [:manufacturer_id] for the following code. I have looked around and can't find the answer for this one.
cars_controller.rb
class CarsController < ApplicationController
def index
#cars = Car.all
end
def show
#car = Car.find(params[:id])
end
def new
#manufacturer = Manufacturer.find(params[:manufacturer_id])
#car = Car.new(params[:id])
#car.manufacturer = #manufacturer
end
def create
#manufacturer = Manufacturer.find(params[:manufacturer_id])
#car = Car.new(cars_params)
#car.manufacturer = #manufacturer
if #car.save
flash[:notice] = "You have successfully created a car"
redirect_to manufacturer_cars_path
else
render 'new'
end
end
private
def cars_params
params.require(:car).permit(:make, :color, :year, :mileage, :description, :country)
end
end
manufacturers_controller.rb
class ManufacturersController < ApplicationController
def index
#manufacturers = Manufacturer.all
end
def show
#manufacturer = Manufacturer.find(params[:id])
#car = Car.new
end
def new
#manufacturer = Manufacturer.new
end
def create
#manufacturer = Manufacturer.new(manufacturer_params)
if #manufacturer.save
flash[:notice] = "You have successfully created a new manufacturer"
redirect_to root_path(#manufacturer)
else
flash[:alert] = "Please try again"
render :new
end
end
private
def manufacturer_params
params.require(:manufacturer).permit(:name, :country)
end
end
models/car.rb
class Car < ActiveRecord::Base
belongs_to :manufacturer
validates :make, presence: true
validates :color, presence: true
validates :year, presence: true
validates :mileage, presence: true
validates :country, presence: true
end
models/manufacturer.rb
class Manufacturer < ActiveRecord::Base
has_many :cars
validates :name, presence: true
validates :country, presence: true
end
this link works in my cars/index.html.erb <%= link_to "Add Car", new_manufacturer_car_path %> but not in my layouts/application.html.erb or elsewhere. In manufacturers/index.html.erb it asks for the :manufacturer_id so i tried different ways and no luck. perhaps I'm missing something here.
these are my routes
Prefix Verb URI Pattern Controller#Action
root GET / manufacturers#index
manufacturer_cars GET /manufacturers/:manufacturer_id/cars(.:format) cars#index
POST /manufacturers/:manufacturer_id/cars(.:format) cars#create
new_manufacturer_car GET /manufacturers/:manufacturer_id/cars/new(.:format) cars#new
manufacturer_car GET /manufacturers/:manufacturer_id/cars/:id(.:format) cars#show
manufacturers GET /manufacturers(.:format) manufacturers#index
POST /manufacturers(.:format) manufacturers#create
new_manufacturer GET /manufacturers/new(.:format) manufacturers#new
manufacturer GET /manufacturers/:id(.:format) manufacturers#show
I appreciate the help.
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.
The idea is simple. I require a nested attribute tag for user registration. tag requires a user_id.
the view
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: {role: :form}) do |f| %>
<%= f.fields_for :tags, resource.tags.build do |a| %>
<%= a.text_field :tagname %>
<% end %>
<% end %>
tag migration
class CreateTags < ActiveRecord::Migration
def change
create_table :tags do |t|
t.string :tagname
t.references :user, index: true
t.timestamps
end
add_index :tags, :tagname, unique: true
end
end
the tag model
class Tag < ActiveRecord::Base
belongs_to :user
validates_presence_of :user_id
validates_uniqueness_of :tagname
end
the user model
class User < ActiveRecord::Base
has_many :tags, autosave: true, dependent: :destroy
accepts_nested_attributes_for :tags
end
strong parameters
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(
:tags_attributes => [:id, :user_id, :tagname]
) }
The save feature is untouched at the moment. The form passes the nested attribute :tagname just fine. But I've been unable to get the "would be" user_id from resource.
I've already looked for hours online for any answer to this. None has appeared, but the idea that the nested attribute should be saved after the initial user object is saved sounds like a workable solution. But then it's no longer handled as a nested attribute.
Help is appreciated! Thanks!
Solution
Alright I solved it. I bastardised my devise registrations controller a bit, but it works.
First I removed user_id verification from my tag model.
class Tag < ActiveRecord::Base
belongs_to :user
validates_uniqueness_of :tagname
end
I then proceeded with modifying the devise registration controller.
def create
build_resource(sign_up_params)
# added code begins here
#tag = nil
#tag.define_singleton_method(:valid?) {false}
if params["user"].has_key? "tags_attributes"
#tag = Tag.new(params["user"].delete("tags_attributes").values.first)
if #tag.valid?
resource_saved = resource.save # original line of code
else
resource.errors.add(*#tag.errors.first)
flash.delete :tagname_error
set_flash_message :alert, :tag_taken if is_flashing_format?
end
else
set_flash_message :alert, :need_tag if is_flashing_format?
end
# end added code
yield resource if block_given?
if resource_saved
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_flashing_format?
sign_up(resource_name, resource)
# This is where current_user has been created and resource.id == current_user.id
# begin added code
#tag.user_id= resource.id
# end added code
respond_with resource, location: after_sign_up_path_for(resource)
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
expire_data_after_sign_in!
respond_with resource, location: after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
#validatable = devise_mapping.validatable?
if #validatable
#minimum_password_length = resource_class.password_length.min
end
respond_with resource
end
end
I've defined :tag_taken and :need_tag in my devise locales file for translations of the error string.
And everything works!
For the record this is in addition to the existing code in the question.
I'm following this video tutorial and learning how to create authentication from scratch:
http://www.youtube.com/watch?v=O5RDisWr_7Q
Here is my migration file for User:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :email
t.string :password_hash
t.string :password_salt
t.timestamps
end
end
end
And my controller:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:users])
if #user.save
redirect_to root_url, :notice => "Signed up!"
else
render "new"
end
end
end
And finally my Model:
class User < ActiveRecord::Base
attr_accessible :email, :password_hash, :password_salt
before_save :encrypt_password
validates_confirmation_of :password
validates :password, presence: true
validates :email, presence: true
def encrypt_password
if password.present?
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
end
end
end
Now, I think I know why this error is firing; obviously the #user.save call is trying to save the value in password to the password field in the User table, but that field doesn't exist in the database. In the video he mentions that to fix this bug I should just add: attr_accessible :password to my model and it should work, but I get the following error:
NoMethodError in UsersController#create
undefined method `password' for #
app/controllers/users_controller.rb:8:in `create'
Any suggestions? I just would like to take advantage of the validations that come with using a strongly typed model instead of loose html fields.
You have attr_accessible :password_hash, :password_salt, but I think it should be attr_accessible :password together with attr_accessor :password since you need a virtual attribute password on which you work in your encrypt_password method. So:
class User < ActiveRecord::Base
attr_accessible :email, :password
attr_accessor :password
end
attr_accessor creates the virtual attribute which is not available as a database field (therefore virtual).
attr_accessible is a security mechanism to white-list attributes which are allowed to be set through mass-assignment like you do with User.new(params[:users])