Rails 4 with CanCan: unknown attribute error after including load_and_authorize_resource - cancan

I'm working in Rails 4 and have gotten CanCan to work well with instructions from this issue, except for one use case that I think might be relatively common.
I have a Comment model, which has_many :comments, through: :replies for nested comments. All of this is working well, until I add load_and_authorize_resource to my comments controller. The problem seems to stem from a hidden field sending an optional :parent_comment_id attribute to my create action.
I've permitted this attribute via strong parameters:
def comment_params
params.require(:comment).permit(:content, :parent_comment_id, :post_id, :comment_id, :user_id)
end
So that I can create the association if a :parent_comment_id is included:
if comment_params[:parent_comment_id] != nil
Reply.create({:parent_comment_id => comment_params[:parent_comment_id], :comment_id => #comment.id})
end
But once I add load_and_authorize_resource, I get an unknown attribute error for :parent_comment_id. What am I missing?

Solution came to me in my sleep. Here's what I did to solve the problem:
The only reason comment_params wasn't normally having a problem on create, was because I was excluding the extra :parent_comment_id parameter, like this:
#comment = post.comment.create(comment_params.except(:parent_comment_id))
When CanCan used the comment_params method however, it did no such sanitation. Hence, the problem. It would have been messy to add that sanitation to CanCan on a per-controller basis, so I did what I should have done all along and instead of passing the :parent_comment_id inside :comment, I used hidden_field_tag to pass it outside of :comment and accessed it through plain, old params.
I hope this helps someone else who makes a similar mistake!

Related

Grails mail plugin runtime configuration

Using grails mail plugin 1.0.7.
https://jira.grails.org/browse/GPMAIL-36 states that it's possible to change plguin configuration since 1.0.1 at runtime. Sadly it does not explains how to achieve it.
I want to be able to change the username at runtime to be able to use different mail accounts.
Thanks.
Based on this code, you should be able to change the configuration at runtime and the mail plugin will automagically re-deploy and update mail sender based on your changes.
Example:
Holders.config.grails.mail.username = 'foo'
Holders.config.grails.mail.password = 'bar'
sendMail {
to "foo#bar.com"
from "bar#foo.com"
subject "Hi"
body "This is an email"
}
Update:
It would appear that changing the configuration in this manner does not, in fact, fire the onConfigChange event. Per this, you can fire the event manually. Something like this:
Holders.pluginManager.getGrailsPlugin('mail').notifyOfEvent(GrailsPlugin.EVENT_ON_CONFIG_CHANGE, Holders.config)
I've realized this can be done accessing the mailSender bean from the context and updating it like is explained here
Changing mail configuration in runtime
However if #rmlan solution finally works it may be a much cleaner solution.
Actually thr rmlan solution works with the following fix. Since the onConfigChange compares hashCode of existing config map and new one, so if you set new configs in original configuration (Holders.config.grails.mail), then both configs are same and it never pass the condition to apply new changes, so a new structure should be created and pass it to notifyOfEvent method to mark the change as different hashCodes.
def mailConfig = [ grails: [ mail: [:] ] ]
mailConfig.grails.mail.host = newHost
mailConfig.grails.mail.port = newPort
Holders.pluginManager.getGrailsPlugin('mail').
notifyOfEvent(GrailsPlugin.EVENT_ON_CONFIG_CHANGE, mailConfig)
Still using async-mail and this one make the below exception
No qualifying bean of type [grails.plugin.mail.MailService] is defined: expected single matching bean but found 2: nonAsynchronousMailService,mailService
that is thrown because of the following part of onConfigChange
event.ctx.getBean(MailService.class).setPoolSize(mailConfig.poolSize?:null)
Commenting it let it works as a workaround, but making sendMail of mail plugin is called, not async-mail, so exception may raise if async-mail features is used on constructing mail. Hence to use async-mail in this workaround should use sendAsynchronousMail method.

ZF1 is calling unexpected controller

I have controller named
AbcController
, which is in default module. So it's normally called like
somedomain.com/abc
..and everything is dispatched correctly, however in case uf URL
somedomain.com/!abc
OR
somedomain.com/#abc
iƧ's still routed to
AbcController
, question is why ? Or better question is, where exactly is the url param transformed to controller name ? I'm trying to find that few hours by debugger.
Expected behavior: controller not found exception
Current behavior: view !abc/inde.phtml not found
This is completely strange, please point me. Thank you.
Update:
So, after more time I found the reason, why any characters such ! and # are trimmed:
Zend_Controller_Dispatcher_Abstract::_formatName()
function is doing following:
$segment = preg_replace('/[^a-z0-9 ]/', '', $segment);
Question is, how to skip that and to get correct state (not existing controller)
OK, so there isn't clear solution, or at least I didn't find any. Actually I have workaround - using static router to some other action, like "ind" instead of "index". In case of bad character, controller will be matched, but default action not, what will result in requested 404 response.
Issue is in ZF1 itself, as controller names are claned, but action names aren't. Shoulld be both or nothing, I think.

Moped::Errors::OperationFailure when creating an embedded object

I'm using mongoid 3.1.4 altogether with moped 1.5.1, mongodb 2.4.1, and ruby 1.9.3.
I have next models:
class Practice
include Mongoid::Document
embeds_many :distresses
end
class Distress
include Mongoid::Document
embedded_in :practice
end
When I do something like this it seems to be working:
practice = Practice.create
practice.distresses.create
But when I place safe: true in my config file and I do the same, then I get:
Moped::Errors::OperationFailure: The operation: #<Moped::Protocol::Command
#length=82
#request_id=22
#response_to=0
#op_code=2004
#flags=[]
#full_collection_name="collection.$cmd"
#skip=0
#limit=-1
#selector={:getlasterror=>1, :safe=>true}
#fields=nil>
And actually, I got the error when creating the distress in any way. This also throws the exception:
practice = Practice.create
distress = practice.distresses.build
distress.save
When I check with practice.distresses.count I can see that distresses where created successfully in the database, however I get the exception mentioned above.
Ok, after some days I was able to fix this problem.
In my Distress model I had a before_create callback that was trying to update a field on the Practice parent object. Somehow this makes Moped to create a wrong request that makes MongoDB to fail.
I changed before_create callback for after_create and everything is working now.
Hope this helps somebody else.

Django Tastypie, Remove Elements From ManyToMany Fields

I am using Tastypie, Django for my project.
To Update a many to many field I have used save_m2m hook.
def save_m2m(self, bundle):
for field_name, field_object in self.fields.items():
if not getattr(field_object, 'is_m2m', False):
continue
if not field_object.attribute:
continue
if field_object.readonly:
continue
related_mngr = getattr(bundle.obj, field_object.attribute)
related_objs = []
print bundle.data[field_name]
for related_bundle in bundle.data[field_name]:
try:
stock = Stock.objects.get(nse_symbol = related_bundle.obj.nse_symbol)
print stock.__dict__
except Stock.DoesNotExist as e:
dataa = {"error_message": e}
raise ImmediateHttpResponse(response=HttpBadRequest(content=json.dumps(dataa), content_type="application/json; charset=UTF-8"))
related_objs.append(stock)
related_mngr.add(*related_objs)
Now I want to remove elements from the same many to many field.
How should I achieve this. Do I have to send a patch request or delete request and how to handle this.
I am begineer in tastypie. I googled it some time and I couldn't find a proper way. Please guide me how to complete this.
Thanks.
I've thought a lot about handing m2m relationships, since most of our app depends on m2m links.
I've settled for the approach of an update method. Pass in the all the references of the relationships you want changed (add and remove), then update the db accordingly. We only pass in the changed values, since if you have a paginated list, you only want to update the items the user has identified. Generally I use a custom hook for this defined in override_urls.
I used to have a separate add and remove method, which worked well until we changed the gui and allowed users simply to change checkboxes. In that approach having an update method was much more useful. You'll have to decide on which method suits your application the best.

How do I use add_to in Class::DBI?

I'm trying to use Class::DBI with a simple one parent -> may chidren relationships:
Data::Company->table('Companies');
Data::Company->columns(All => qw/CompanyId Name Url/);
Data::Company->has_many(offers => 'Data::Offer'=>'CompanyId'); # =>'CompanyId'
and
Data::Offer->table('Offers');
Data::Offer->columns(All => qw/OfferId CompanyId MonthlyPrice/);
Data::Offer->has_a(company => 'Data::Company'=>'CompanyId');
I try to add a new record:
my $company = Data::Company->insert({ Name => 'Test', Url => 'http://url' });
my $offer = $company->add_to_offers({ MonthlyPrice => 100 });
But I get:
Can't locate object method "add_to_offers" via package "Data::Company"
I looked at the classical Music::CD example, but I cannot figure out what I am doing wrong.
I agree with Manni, if your package declarations are in the same file, then you need to have the class with the has_a() relationship defined first. Otherwise, if they are in different source files, then the documentation states:
Class::DBI should usually be able to
do the right things, as long as all
classes inherit Class::DBI before
'use'ing any other classes.
As to the three-argument form, you are doing it properly. The third arg for has_many() is the column in the foreign class which is a foreign key to this class. That is, Offer has a CompanyId which points to Company's CompanyId.
Thank you
Well, the issue was actually not my code, but my set up. I realized that this morning after powering on my computer:
* Apache + mod_perl on the server
* SMB mount
When I made changes to several files, not all changes seems to be loaded by mod_perl. Restarting Apache solves the issue. I've actually seen this kind of issue in the past where the client and SMB server's time are out of sync.
The code above works fine with 1 file for each module.
Thank you
I really haven't got much experience with Class:DBI, but I'll give this a shot anyway:
The documentation states that: "the class with the has_a() must be defined earlier than the class with the has_many()".
I cannot find any reference to the way you are using has_a and has_many with three arguments which is always 'CompanyId' in your case.