Im using CanCan load_and_authorize_resource helper method for fetching resources and generating authorization, but I have a nested resource like this
load_and_authorize_resource :company
load_and_authorize_resource :accountings, :through => :company, :class => 'Departments::Accounting'
But I need
#accountings be found by another attribute rather that the Departmets::Accounting id and give a value to that attribute, for example
#accountings = #company.find_by_period_id(#period.id)
You can do it with two extra options:
load_and_authorize_resource :accountings,
:through => :company, :class => 'Departments::Accounting',
:find_by => :attr, # :period_id in your example
:id_param => :something # this searches the params hash for
# params[:something], and sends that
# value to .find_by_attr
Check the code for load_and_authorize_resource here.
Related
I'm following this tutorial on how to nest other Models in my Devise registration form. I'm getting an error in my New controller:
'NoMethodError in Users::RegistrationsController#new undefined method `languages_user=' for #'.
Languages_Users is a join table, and I'm wondering if this is the reason it isn't working, but I don't understand what the solution is. I want to add 2 different records of Languages_Users when the user signs up.
Models:
User.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :role
has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100#" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
validates_presence_of :first_name, :last_name, :location, :nationality, :bio
before_save :assign_role
def assign_role
self.role = Role.find_by name: "user" if self.role.nil?
end
has_many :languages_users
has_many :languages, :through => :languages_users
accepts_nested_attributes_for :languages_users
Language.rb
class Language < ActiveRecord::Base
has_many :languages_users
has_many :users, :through => :languages_users
end
Langauges_user.rb
class LanguagesUser < ActiveRecord::Base
belongs_to :user
belongs_to :language
validates_presence_of :user_id, :language_id, :level
validates :user_id, :uniqueness => {:scope => :language_id, :message => 'can only delcare each language once. Please change the level of the language in Manage Languages.'}
end
Controllers:
registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
def new
build_resource({})
self.resource.languages_user = LanguagesUser.new[sign_up_params]
respond_with self.resource
end
def create
#user_id = current_user.id
super
end
def sign_up_params
allow = [:email, :password, :password_confirmation, [languages_user_attributes: [:language_id, :user_id, :level]]]
end
end
Relevant sections of User's new.html.erb
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<%= f.fields_for :langauges_user do |lu| %>
<%#= lu.text_field :language_id %>
<%= lu.collection_select(:language_id, Language.order('language ASC').all, :id, :language) %><br>
<%= lu.hidden_field languages_user[level], value: 1 %>
<% end %>
<%= f.submit "Sign up" %>
<% end %>
Relevant routes
Rails.application.routes.draw do
resources :languages_users
devise_for :users, controllers: { registrations: "users/registrations" }
resources :users
get 'languages_users/:id/sign_up', to: 'languages_users#sign_up', as: 'sign_up'
end
I'm still learning - so please let me know if you need to see anything else. Thanks!
I'm not that up to speed on Devise as I only recently started using it myself, but if I understand correctly it's not a Devise related problem - just harder to get a fix on because of Devise's self.resource abstraction.
You've deviated from your tutorial in an important respect: in the tutorial a User creates a Company, but the Company has_many :users. In your case the User creates a LanguagesUser, but here, the User has_many :languages_users. This means new syntax. This line, that's causing your error currently:
self.resource.languages_user = LanguagesUser.new[sign_up_params]
Needs to be along the lines of:
self.resource.languages_users.build(sign_up_params) #but see below re sign_up_params
Or if you want to save the associated resource right off the bat (I assume not, since you're not at the moment), you can use create or create! instead of build.
Aside
You may run into different trouble with your sign_up_params method, which also appears to have deviated from the tutorial - it doesn't actually use the allow array to whitelist any params, at least as written in your question. In any case, note they didn't use it when instantiating the Company, so it may not be fit for purpose when building your LanguagesUser, either.
A simple call to sign_up_params[:languages_user_attributes] should get you over the line, once you've fixed the sign_up_params method. Or you can set the nested object up with its own params whitelist.
Paperclip provides the following code:
has_attached_file :image,
...
...
which is duplicated across several models.
Extracting to a module:
module AttachedImage
include Paperclip::Glue
has_attached_file :image,
...
...
raises Exception encountered: #<NoMethodError: undefined method 'class_attribute' for AttachedImage:Module> exception.
What does this mean? How to mix-in Paperclip has_attached_file code? Is there a better way to eliminate duplication?
I was looking for a similar solution just now and came up with the following:
module AttachedFileModule
extend ActiveSupport::Concern
included do
attr_accessible :avatar
extend Paperclip::Glue
has_attached_file :avatar,
:styles => { :medium => "300x300>", :thumb => "100x100>" },
:default_url => "/images/:style/missing.png"
end
end
As you can see in the above code we have to extend ActiveSupport::Concern so we can ise the attr_accessible method. We must also extend Paperclip::Glue so we can use the has_attached_file method.
Then in the model you want to attach images to:
class User < ActiveRecord::Base
include AttachedFileModule
end
My project:
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :email,
:password,
:password_confirmation,
:first_name,
:last_name,
:birth_date,
:residence,
:user_role,
:show_email,
:avatar
as_attached_file :avatar,
:default_url => '/images/system/user_avatars/default/default_avatar.png',
:url => "/public/images/system/user_avatars/:id_:style.:extension",
:path => "/public/system/user_avatars/:id_:style.:extension"
def update_profile(user_id, params) #params has :category and :user params
#user = User.find(user_id)
#user.update_attributes(params[:user])
return params[:category]
end
end
So, from my controller i call this method and i get no error. Paperclip shows attachment saved. The database is updated, but the image file is not saved. I have an registration made from scratch, so that's why i have the "attr_accessor :password"
I checked:
Have :multipart => true in form
Have attr_accessible :avatar in user model
Can any one give me some lead, cos i cant figure, why paperclip dosnt save the file.
Set attr_accessible :avatar_file_name as well, and you also need a paperclip.rb initializer:
require "paperclip"
Paperclip.options[:command_path] = "/ImageMagick"
And, of course, have ImageMagick installed.
hi im new in ROR development im just wondering why my app rise a
"undefined method `menu'
i seems to associate my models right
i would like to show a menu that the reservation reserverd and show its recipes inside that menu but it rises undefiend method 'menu'
package_line_item.rb
belongs_to :menu
belongs_to :reservation
reservation.rb
has_one :reservation_package
belongs_to :service
has_many :reservation_function_rooms
has_many :package_line_items
has_many :menus , :through => :package_line_items, :uniq => true
has_many :function_rooms, :through =>:reservation_function_rooms
menu.rb
has_many :package_line_items
has_many :menu_recipes
has_many :recipes, :through => :menu_recipes, :uniq => true
belongs_to :menu_category
package_line_item_controller.rb
def index
#package_line_items = PackageLineItems.all
end
def show
#reservation = Reservation.includes(:package_line_items => :menu).find(params[:id])
end
def new
#reservation = Reservation.find(params[:reservation_id])
#package_line_item = #reservation.package_line_items.build
end
def create
#reservation = Reservation.find(params[:reservation_id])
#reservation.package_line_items.build(params[:package_line_item])
if #package_line_item.save
redirect_to #reservation ,:notice => "added menu"
end
routes.rb
resources :services
resources :reservations do
resources :reservation_packages
resources :reservation_function_rooms
resources :packages
resources :package_line_items
resources :package_crews
end
resources :function_rooms
resources :crews
resources :menu_categories
resources :menus do
resources :menu_recipes
end
ActiveAdmin.routes(self)
devise_for :admin_users, ActiveAdmin::Devise.config
resources :recipe_categories
resources :recipes
package_line_item/show.html.erb
<p id="notice"><%= notice %></p>
<%= #reservation.package_line_items.menu.name%>
if other file is needed feel free to ask me thank you more power to us thanks
It might be because "menu" is a method in the ActiveAdmin DSL. I had a problem with a model called "Page" precisely for this reason. Try renaming your model and see what happens.
I have this code for creating a topic and post in a forum application in Rails 3.1:
def create
#topic = Topic.new(:name => params[:topic][:name], :last_post_at => Time.now)
#topic.forum_id = params[:topic][:forum_id]
#topic.user = current_user
if #topic.save
#post = Post.new(:content => params[:post][:content])
#post.topic = #topic
#post.user = current_user
#post.save!
...
When posting to the create method via the corresponding form, the topic and the post are created and both save calls are successful.
When I call the create method via a functional test, the topic is saved but the post has validation errors.
ActiveRecord::RecordInvalid: Validation failed:
app/controllers/topics_controller.rb:23:in `create'
test/functional/topics_controller_test.rb:26:in `block in <class:TopicsControllerTest>'
The test looks like this:
test "should create topic" do
post :create, :topic => {:name => "New topic", :forum_id => forums(:one).id}, :post => {:content => "Post content"}
end
(current_user is logged in via a setup method.)
When I display the errors of the post object via the debugger or with #post.errors.full_messages, the error array is empty.
The Post model looks like this:
class Post < ActiveRecord::Base
attr_accessible :content
belongs_to :topic
belongs_to :user
end
And the Topic model:
class Topic < ActiveRecord::Base
belongs_to :user
belongs_to :last_poster, class_name: 'User'
attr_accessible :name, :last_poster_id, :last_post_at
belongs_to :forum
has_many :posts, :dependent => :destroy
end
How can I find out what is causing the validation error?
The problem was that I used mocha's Post.any_instance.stubs(:valid?).returns(false) in a test that was executed before my failing test.
Apparently, you have to restore the original behavior before proceeding with other tests by calling Post.any_instance.unstub(:valid?).